Merge 6.1.121 into android14-6.1-lts

Changes in 6.1.121
	bpf: Fix UAF via mismatching bpf_prog/attachment RCU flavors
	ksmbd: fix racy issue from session lookup and expire
	tcp: check space before adding MPTCP SYN options
	blk-cgroup: Fix UAF in blkcg_unpin_online()
	ALSA: usb-audio: Add implicit feedback quirk for Yamaha THR5
	usb: host: max3421-hcd: Correctly abort a USB request.
	ata: sata_highbank: fix OF node reference leak in highbank_initialize_phys()
	usb: dwc2: Fix HCD resume
	usb: dwc2: hcd: Fix GetPortStatus & SetPortFeature
	usb: dwc2: Fix HCD port connection race
	usb: ehci-hcd: fix call balance of clocks handling routines
	usb: typec: anx7411: fix fwnode_handle reference leak
	usb: typec: anx7411: fix OF node reference leaks in anx7411_typec_switch_probe()
	usb: gadget: u_serial: Fix the issue that gs_start_io crashed due to accessing null pointer
	usb: dwc3: xilinx: make sure pipe clock is deselected in usb2 only mode
	drm/i915: Fix memory leak by correcting cache object name in error handler
	xfs: update btree keys correctly when _insrec splits an inode root block
	xfs: don't drop errno values when we fail to ficlone the entire range
	xfs: return from xfs_symlink_verify early on V4 filesystems
	xfs: fix scrub tracepoints when inode-rooted btrees are involved
	xfs: only run precommits once per transaction object
	bpf,perf: Fix invalid prog_array access in perf_event_detach_bpf_prog
	bpf, sockmap: Fix update element with same
	smb: client: fix UAF in smb2_reconnect_server()
	exfat: support dynamic allocate bh for exfat_entry_set_cache
	exfat: fix potential deadlock on __exfat_get_dentry_set
	wifi: nl80211: fix NL80211_ATTR_MLO_LINK_ID off-by-one
	wifi: mac80211: clean up 'ret' in sta_link_apply_parameters()
	wifi: mac80211: fix station NSS capability initialization order
	acpi: nfit: vmalloc-out-of-bounds Read in acpi_nfit_ctl
	amdgpu/uvd: get ring reference from rq scheduler
	batman-adv: Do not send uninitialized TT changes
	batman-adv: Remove uninitialized data in full table TT response
	batman-adv: Do not let TT changes list grows indefinitely
	tipc: fix NULL deref in cleanup_bearer()
	net/mlx5: DR, prevent potential error pointer dereference
	selftests: mlxsw: sharedbuffer: Remove h1 ingress test case
	selftests: mlxsw: sharedbuffer: Remove duplicate test cases
	selftests: mlxsw: sharedbuffer: Ensure no extra packets are counted
	ptp: kvm: Use decrypted memory in confidential guest on x86
	ptp: kvm: x86: Return EOPNOTSUPP instead of ENODEV from kvm_arch_ptp_init()
	net: lapb: increase LAPB_HEADER_LEN
	net: defer final 'struct net' free in netns dismantle
	net: mscc: ocelot: fix memory leak on ocelot_port_add_txtstamp_skb()
	net: mscc: ocelot: improve handling of TX timestamp for unknown skb
	net: mscc: ocelot: ocelot->ts_id_lock and ocelot_port->tx_skbs.lock are IRQ-safe
	net: mscc: ocelot: be resilient to loss of PTP packets during transmission
	net: mscc: ocelot: perform error cleanup in ocelot_hwstamp_set()
	spi: aspeed: Fix an error handling path in aspeed_spi_[read|write]_user()
	net: sparx5: fix FDMA performance issue
	net: sparx5: fix the maximum frame length register
	ACPI: resource: Fix memory resource type union access
	cxgb4: use port number to set mac addr
	qca_spi: Fix clock speed for multiple QCA7000
	qca_spi: Make driver probing reliable
	ASoC: amd: yc: Fix the wrong return value
	Documentation: PM: Clarify pm_runtime_resume_and_get() return value
	net: dsa: felix: fix stuck CPU-injected packets with short taprio windows
	net/sched: netem: account for backlog updates from child qdisc
	bonding: Fix feature propagation of NETIF_F_GSO_ENCAP_ALL
	team: Fix feature propagation of NETIF_F_GSO_ENCAP_ALL
	ACPICA: events/evxfregn: don't release the ContextMutex that was never acquired
	Bluetooth: iso: Fix recursive locking warning
	Bluetooth: SCO: Add support for 16 bits transparent voice setting
	blk-iocost: Avoid using clamp() on inuse in __propagate_weights()
	bpf: sync_linked_regs() must preserve subreg_def
	tracing/kprobes: Skip symbol counting logic for module symbols in create_local_trace_kprobe()
	xen/netfront: fix crash when removing device
	x86: make get_cpu_vendor() accessible from Xen code
	objtool/x86: allow syscall instruction
	x86/static-call: provide a way to do very early static-call updates
	x86/xen: don't do PV iret hypercall through hypercall page
	x86/xen: add central hypercall functions
	x86/xen: use new hypercall functions instead of hypercall page
	x86/xen: remove hypercall page
	ALSA: usb-audio: Fix a DMA to stack memory bug
	x86/static-call: fix 32-bit build
	Linux 6.1.121

Change-Id: Ic4aa66a4ef3978ba32c31f859f7fc66b95edec96
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Greg Kroah-Hartman
2024-12-30 09:34:42 +00:00
84 changed files with 984 additions and 458 deletions

View File

@@ -347,7 +347,9 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
`int pm_runtime_resume_and_get(struct device *dev);` `int pm_runtime_resume_and_get(struct device *dev);`
- run pm_runtime_resume(dev) and if successful, increment the device's - run pm_runtime_resume(dev) and if successful, increment the device's
usage counter; return the result of pm_runtime_resume usage counter; returns 0 on success (whether or not the device's
runtime PM status was already 'active') or the error code from
pm_runtime_resume() on failure.
`int pm_request_idle(struct device *dev);` `int pm_request_idle(struct device *dev);`
- submit a request to execute the subsystem-level idle callback for the - submit a request to execute the subsystem-level idle callback for the

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
VERSION = 6 VERSION = 6
PATCHLEVEL = 1 PATCHLEVEL = 1
SUBLEVEL = 120 SUBLEVEL = 121
EXTRAVERSION = EXTRAVERSION =
NAME = Curry Ramen NAME = Curry Ramen

View File

@@ -199,6 +199,8 @@ static inline unsigned long long l1tf_pfn_limit(void)
return BIT_ULL(boot_cpu_data.x86_cache_bits - 1 - PAGE_SHIFT); return BIT_ULL(boot_cpu_data.x86_cache_bits - 1 - PAGE_SHIFT);
} }
void init_cpu_devs(void);
void get_cpu_vendor(struct cpuinfo_x86 *c);
extern void early_cpu_init(void); extern void early_cpu_init(void);
extern void identify_boot_cpu(void); extern void identify_boot_cpu(void);
extern void identify_secondary_cpu(struct cpuinfo_x86 *); extern void identify_secondary_cpu(struct cpuinfo_x86 *);

View File

@@ -65,4 +65,19 @@
extern bool __static_call_fixup(void *tramp, u8 op, void *dest); extern bool __static_call_fixup(void *tramp, u8 op, void *dest);
extern void __static_call_update_early(void *tramp, void *func);
#define static_call_update_early(name, _func) \
({ \
typeof(&STATIC_CALL_TRAMP(name)) __F = (_func); \
if (static_call_initialized) { \
__static_call_update(&STATIC_CALL_KEY(name), \
STATIC_CALL_TRAMP_ADDR(name), __F);\
} else { \
WRITE_ONCE(STATIC_CALL_KEY(name).func, _func); \
__static_call_update_early(STATIC_CALL_TRAMP_ADDR(name),\
__F); \
} \
})
#endif /* _ASM_STATIC_CALL_H */ #endif /* _ASM_STATIC_CALL_H */

View File

@@ -8,7 +8,7 @@
#include <asm/special_insns.h> #include <asm/special_insns.h>
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
static inline void iret_to_self(void) static __always_inline void iret_to_self(void)
{ {
asm volatile ( asm volatile (
"pushfl\n\t" "pushfl\n\t"
@@ -19,7 +19,7 @@ static inline void iret_to_self(void)
: ASM_CALL_CONSTRAINT : : "memory"); : ASM_CALL_CONSTRAINT : : "memory");
} }
#else #else
static inline void iret_to_self(void) static __always_inline void iret_to_self(void)
{ {
unsigned int tmp; unsigned int tmp;
@@ -55,7 +55,7 @@ static inline void iret_to_self(void)
* Like all of Linux's memory ordering operations, this is a * Like all of Linux's memory ordering operations, this is a
* compiler barrier as well. * compiler barrier as well.
*/ */
static inline void sync_core(void) static __always_inline void sync_core(void)
{ {
/* /*
* The SERIALIZE instruction is the most straightforward way to * The SERIALIZE instruction is the most straightforward way to

View File

@@ -39,9 +39,11 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/pgtable.h> #include <linux/pgtable.h>
#include <linux/instrumentation.h>
#include <trace/events/xen.h> #include <trace/events/xen.h>
#include <asm/alternative.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/smap.h> #include <asm/smap.h>
#include <asm/nospec-branch.h> #include <asm/nospec-branch.h>
@@ -86,11 +88,20 @@ struct xen_dm_op_buf;
* there aren't more than 5 arguments...) * there aren't more than 5 arguments...)
*/ */
extern struct { char _entry[32]; } hypercall_page[]; void xen_hypercall_func(void);
DECLARE_STATIC_CALL(xen_hypercall, xen_hypercall_func);
#define __HYPERCALL "call hypercall_page+%c[offset]" #ifdef MODULE
#define __HYPERCALL_ENTRY(x) \ #define __ADDRESSABLE_xen_hypercall
[offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0])) #else
#define __ADDRESSABLE_xen_hypercall __ADDRESSABLE_ASM_STR(__SCK__xen_hypercall)
#endif
#define __HYPERCALL \
__ADDRESSABLE_xen_hypercall \
"call __SCT__xen_hypercall"
#define __HYPERCALL_ENTRY(x) "a" (x)
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
#define __HYPERCALL_RETREG "eax" #define __HYPERCALL_RETREG "eax"
@@ -148,7 +159,7 @@ extern struct { char _entry[32]; } hypercall_page[];
__HYPERCALL_0ARG(); \ __HYPERCALL_0ARG(); \
asm volatile (__HYPERCALL \ asm volatile (__HYPERCALL \
: __HYPERCALL_0PARAM \ : __HYPERCALL_0PARAM \
: __HYPERCALL_ENTRY(name) \ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
: __HYPERCALL_CLOBBER0); \ : __HYPERCALL_CLOBBER0); \
(type)__res; \ (type)__res; \
}) })
@@ -159,7 +170,7 @@ extern struct { char _entry[32]; } hypercall_page[];
__HYPERCALL_1ARG(a1); \ __HYPERCALL_1ARG(a1); \
asm volatile (__HYPERCALL \ asm volatile (__HYPERCALL \
: __HYPERCALL_1PARAM \ : __HYPERCALL_1PARAM \
: __HYPERCALL_ENTRY(name) \ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
: __HYPERCALL_CLOBBER1); \ : __HYPERCALL_CLOBBER1); \
(type)__res; \ (type)__res; \
}) })
@@ -170,7 +181,7 @@ extern struct { char _entry[32]; } hypercall_page[];
__HYPERCALL_2ARG(a1, a2); \ __HYPERCALL_2ARG(a1, a2); \
asm volatile (__HYPERCALL \ asm volatile (__HYPERCALL \
: __HYPERCALL_2PARAM \ : __HYPERCALL_2PARAM \
: __HYPERCALL_ENTRY(name) \ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
: __HYPERCALL_CLOBBER2); \ : __HYPERCALL_CLOBBER2); \
(type)__res; \ (type)__res; \
}) })
@@ -181,7 +192,7 @@ extern struct { char _entry[32]; } hypercall_page[];
__HYPERCALL_3ARG(a1, a2, a3); \ __HYPERCALL_3ARG(a1, a2, a3); \
asm volatile (__HYPERCALL \ asm volatile (__HYPERCALL \
: __HYPERCALL_3PARAM \ : __HYPERCALL_3PARAM \
: __HYPERCALL_ENTRY(name) \ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
: __HYPERCALL_CLOBBER3); \ : __HYPERCALL_CLOBBER3); \
(type)__res; \ (type)__res; \
}) })
@@ -192,7 +203,7 @@ extern struct { char _entry[32]; } hypercall_page[];
__HYPERCALL_4ARG(a1, a2, a3, a4); \ __HYPERCALL_4ARG(a1, a2, a3, a4); \
asm volatile (__HYPERCALL \ asm volatile (__HYPERCALL \
: __HYPERCALL_4PARAM \ : __HYPERCALL_4PARAM \
: __HYPERCALL_ENTRY(name) \ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
: __HYPERCALL_CLOBBER4); \ : __HYPERCALL_CLOBBER4); \
(type)__res; \ (type)__res; \
}) })
@@ -206,12 +217,9 @@ xen_single_call(unsigned int call,
__HYPERCALL_DECLS; __HYPERCALL_DECLS;
__HYPERCALL_5ARG(a1, a2, a3, a4, a5); __HYPERCALL_5ARG(a1, a2, a3, a4, a5);
if (call >= PAGE_SIZE / sizeof(hypercall_page[0])) asm volatile(__HYPERCALL
return -EINVAL;
asm volatile(CALL_NOSPEC
: __HYPERCALL_5PARAM : __HYPERCALL_5PARAM
: [thunk_target] "a" (&hypercall_page[call]) : __HYPERCALL_ENTRY(call)
: __HYPERCALL_CLOBBER5); : __HYPERCALL_CLOBBER5);
return (long)__res; return (long)__res;

View File

@@ -906,7 +906,7 @@ void detect_ht(struct cpuinfo_x86 *c)
#endif #endif
} }
static void get_cpu_vendor(struct cpuinfo_x86 *c) void get_cpu_vendor(struct cpuinfo_x86 *c)
{ {
char *v = c->x86_vendor_id; char *v = c->x86_vendor_id;
int i; int i;
@@ -1672,15 +1672,11 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
detect_nopl(); detect_nopl();
} }
void __init early_cpu_init(void) void __init init_cpu_devs(void)
{ {
const struct cpu_dev *const *cdev; const struct cpu_dev *const *cdev;
int count = 0; int count = 0;
#ifdef CONFIG_PROCESSOR_SELECT
pr_info("KERNEL supported cpus:\n");
#endif
for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) { for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) {
const struct cpu_dev *cpudev = *cdev; const struct cpu_dev *cpudev = *cdev;
@@ -1688,20 +1684,30 @@ void __init early_cpu_init(void)
break; break;
cpu_devs[count] = cpudev; cpu_devs[count] = cpudev;
count++; count++;
}
}
void __init early_cpu_init(void)
{
#ifdef CONFIG_PROCESSOR_SELECT
unsigned int i, j;
pr_info("KERNEL supported cpus:\n");
#endif
init_cpu_devs();
#ifdef CONFIG_PROCESSOR_SELECT #ifdef CONFIG_PROCESSOR_SELECT
{ for (i = 0; i < X86_VENDOR_NUM && cpu_devs[i]; i++) {
unsigned int j; for (j = 0; j < 2; j++) {
if (!cpu_devs[i]->c_ident[j])
for (j = 0; j < 2; j++) { continue;
if (!cpudev->c_ident[j]) pr_info(" %s %s\n", cpu_devs[i]->c_vendor,
continue; cpu_devs[i]->c_ident[j]);
pr_info(" %s %s\n", cpudev->c_vendor,
cpudev->c_ident[j]);
}
} }
#endif
} }
#endif
early_identify_cpu(&boot_cpu_data); early_identify_cpu(&boot_cpu_data);
} }

View File

@@ -170,6 +170,15 @@ void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
} }
EXPORT_SYMBOL_GPL(arch_static_call_transform); EXPORT_SYMBOL_GPL(arch_static_call_transform);
noinstr void __static_call_update_early(void *tramp, void *func)
{
BUG_ON(system_state != SYSTEM_BOOTING);
BUG_ON(!early_boot_irqs_disabled);
BUG_ON(static_call_initialized);
__text_gen_insn(tramp, JMP32_INSN_OPCODE, tramp, func, JMP32_INSN_SIZE);
sync_core();
}
#ifdef CONFIG_RETHUNK #ifdef CONFIG_RETHUNK
/* /*
* This is called by apply_returns() to fix up static call trampolines, * This is called by apply_returns() to fix up static call trampolines,

View File

@@ -5,6 +5,7 @@
#endif #endif
#include <linux/console.h> #include <linux/console.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/instrumentation.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/panic_notifier.h> #include <linux/panic_notifier.h>
@@ -25,7 +26,8 @@
#include "smp.h" #include "smp.h"
#include "pmu.h" #include "pmu.h"
EXPORT_SYMBOL_GPL(hypercall_page); DEFINE_STATIC_CALL(xen_hypercall, xen_hypercall_hvm);
EXPORT_STATIC_CALL_TRAMP(xen_hypercall);
/* /*
* Pointer to the xen_vcpu_info structure or * Pointer to the xen_vcpu_info structure or
@@ -72,6 +74,67 @@ EXPORT_SYMBOL(xen_start_flags);
*/ */
struct shared_info *HYPERVISOR_shared_info = &xen_dummy_shared_info; struct shared_info *HYPERVISOR_shared_info = &xen_dummy_shared_info;
static __ref void xen_get_vendor(void)
{
init_cpu_devs();
cpu_detect(&boot_cpu_data);
get_cpu_vendor(&boot_cpu_data);
}
void xen_hypercall_setfunc(void)
{
if (static_call_query(xen_hypercall) != xen_hypercall_hvm)
return;
if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
boot_cpu_data.x86_vendor == X86_VENDOR_HYGON))
static_call_update(xen_hypercall, xen_hypercall_amd);
else
static_call_update(xen_hypercall, xen_hypercall_intel);
}
/*
* Evaluate processor vendor in order to select the correct hypercall
* function for HVM/PVH guests.
* Might be called very early in boot before vendor has been set by
* early_cpu_init().
*/
noinstr void *__xen_hypercall_setfunc(void)
{
void (*func)(void);
/*
* Xen is supported only on CPUs with CPUID, so testing for
* X86_FEATURE_CPUID is a test for early_cpu_init() having been
* run.
*
* Note that __xen_hypercall_setfunc() is noinstr only due to a nasty
* dependency chain: it is being called via the xen_hypercall static
* call when running as a PVH or HVM guest. Hypercalls need to be
* noinstr due to PV guests using hypercalls in noinstr code. So we
* can safely tag the function body as "instrumentation ok", since
* the PV guest requirement is not of interest here (xen_get_vendor()
* calls noinstr functions, and static_call_update_early() might do
* so, too).
*/
instrumentation_begin();
if (!boot_cpu_has(X86_FEATURE_CPUID))
xen_get_vendor();
if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
boot_cpu_data.x86_vendor == X86_VENDOR_HYGON))
func = xen_hypercall_amd;
else
func = xen_hypercall_intel;
static_call_update_early(xen_hypercall, func);
instrumentation_end();
return func;
}
static int xen_cpu_up_online(unsigned int cpu) static int xen_cpu_up_online(unsigned int cpu)
{ {
xen_init_lock_cpu(cpu); xen_init_lock_cpu(cpu);

View File

@@ -108,15 +108,8 @@ static void __init init_hvm_pv_info(void)
/* PVH set up hypercall page in xen_prepare_pvh(). */ /* PVH set up hypercall page in xen_prepare_pvh(). */
if (xen_pvh_domain()) if (xen_pvh_domain())
pv_info.name = "Xen PVH"; pv_info.name = "Xen PVH";
else { else
u64 pfn;
uint32_t msr;
pv_info.name = "Xen HVM"; pv_info.name = "Xen HVM";
msr = cpuid_ebx(base + 2);
pfn = __pa(hypercall_page);
wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
}
xen_setup_features(); xen_setup_features();
@@ -299,6 +292,10 @@ static uint32_t __init xen_platform_hvm(void)
if (xen_pv_domain()) if (xen_pv_domain())
return 0; return 0;
/* Set correct hypercall function. */
if (xen_domain)
xen_hypercall_setfunc();
if (xen_pvh_domain() && nopv) { if (xen_pvh_domain() && nopv) {
/* Guest booting via the Xen-PVH boot entry goes here */ /* Guest booting via the Xen-PVH boot entry goes here */
pr_info("\"nopv\" parameter is ignored in PVH guest\n"); pr_info("\"nopv\" parameter is ignored in PVH guest\n");

View File

@@ -1248,6 +1248,9 @@ asmlinkage __visible void __init xen_start_kernel(struct start_info *si)
xen_domain_type = XEN_PV_DOMAIN; xen_domain_type = XEN_PV_DOMAIN;
xen_start_flags = xen_start_info->flags; xen_start_flags = xen_start_info->flags;
/* Interrupts are guaranteed to be off initially. */
early_boot_irqs_disabled = true;
static_call_update_early(xen_hypercall, xen_hypercall_pv);
xen_setup_features(); xen_setup_features();
@@ -1340,7 +1343,6 @@ asmlinkage __visible void __init xen_start_kernel(struct start_info *si)
WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_pv, xen_cpu_dead_pv)); WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_pv, xen_cpu_dead_pv));
local_irq_disable(); local_irq_disable();
early_boot_irqs_disabled = true;
xen_raw_console_write("mapping kernel into physical memory\n"); xen_raw_console_write("mapping kernel into physical memory\n");
xen_setup_kernel_pagetable((pgd_t *)xen_start_info->pt_base, xen_setup_kernel_pagetable((pgd_t *)xen_start_info->pt_base,

View File

@@ -27,17 +27,10 @@ EXPORT_SYMBOL_GPL(xen_pvh);
void __init xen_pvh_init(struct boot_params *boot_params) void __init xen_pvh_init(struct boot_params *boot_params)
{ {
u32 msr;
u64 pfn;
xen_pvh = 1; xen_pvh = 1;
xen_domain_type = XEN_HVM_DOMAIN; xen_domain_type = XEN_HVM_DOMAIN;
xen_start_flags = pvh_start_info.flags; xen_start_flags = pvh_start_info.flags;
msr = cpuid_ebx(xen_cpuid_base() + 2);
pfn = __pa(hypercall_page);
wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
if (xen_initial_domain()) if (xen_initial_domain())
x86_init.oem.arch_setup = xen_add_preferred_consoles; x86_init.oem.arch_setup = xen_add_preferred_consoles;
x86_init.oem.banner = xen_banner; x86_init.oem.banner = xen_banner;

View File

@@ -20,9 +20,32 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <linux/objtool.h>
#include <../entry/calling.h> #include <../entry/calling.h>
.pushsection .noinstr.text, "ax" .pushsection .noinstr.text, "ax"
/*
* PV hypercall interface to the hypervisor.
*
* Called via inline asm(), so better preserve %rcx and %r11.
*
* Input:
* %eax: hypercall number
* %rdi, %rsi, %rdx, %r10, %r8: args 1..5 for the hypercall
* Output: %rax
*/
SYM_FUNC_START(xen_hypercall_pv)
ANNOTATE_NOENDBR
push %rcx
push %r11
UNWIND_HINT_SAVE
syscall
UNWIND_HINT_RESTORE
pop %r11
pop %rcx
RET
SYM_FUNC_END(xen_hypercall_pv)
/* /*
* Disabling events is simply a matter of making the event mask * Disabling events is simply a matter of making the event mask
* non-zero. * non-zero.
@@ -176,7 +199,6 @@ SYM_CODE_START(xen_early_idt_handler_array)
SYM_CODE_END(xen_early_idt_handler_array) SYM_CODE_END(xen_early_idt_handler_array)
__FINIT __FINIT
hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
/* /*
* Xen64 iret frame: * Xen64 iret frame:
* *
@@ -186,17 +208,28 @@ hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
* cs * cs
* rip <-- standard iret frame * rip <-- standard iret frame
* *
* flags * flags <-- xen_iret must push from here on
* *
* rcx } * rcx
* r11 }<-- pushed by hypercall page * r11
* rsp->rax } * rsp->rax
*/ */
.macro xen_hypercall_iret
pushq $0 /* Flags */
push %rcx
push %r11
push %rax
mov $__HYPERVISOR_iret, %eax
syscall /* Do the IRET. */
#ifdef CONFIG_MITIGATION_SLS
int3
#endif
.endm
SYM_CODE_START(xen_iret) SYM_CODE_START(xen_iret)
UNWIND_HINT_EMPTY UNWIND_HINT_EMPTY
ANNOTATE_NOENDBR ANNOTATE_NOENDBR
pushq $0 xen_hypercall_iret
jmp hypercall_iret
SYM_CODE_END(xen_iret) SYM_CODE_END(xen_iret)
/* /*
@@ -301,8 +334,7 @@ SYM_CODE_START(xen_entry_SYSENTER_compat)
ENDBR ENDBR
lea 16(%rsp), %rsp /* strip %rcx, %r11 */ lea 16(%rsp), %rsp /* strip %rcx, %r11 */
mov $-ENOSYS, %rax mov $-ENOSYS, %rax
pushq $0 xen_hypercall_iret
jmp hypercall_iret
SYM_CODE_END(xen_entry_SYSENTER_compat) SYM_CODE_END(xen_entry_SYSENTER_compat)
SYM_CODE_END(xen_entry_SYSCALL_compat) SYM_CODE_END(xen_entry_SYSCALL_compat)

View File

@@ -6,9 +6,11 @@
#include <linux/elfnote.h> #include <linux/elfnote.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/instrumentation.h>
#include <asm/boot.h> #include <asm/boot.h>
#include <asm/asm.h> #include <asm/asm.h>
#include <asm/frame.h>
#include <asm/msr.h> #include <asm/msr.h>
#include <asm/page_types.h> #include <asm/page_types.h>
#include <asm/percpu.h> #include <asm/percpu.h>
@@ -20,28 +22,6 @@
#include <xen/interface/xen-mca.h> #include <xen/interface/xen-mca.h>
#include <asm/xen/interface.h> #include <asm/xen/interface.h>
.pushsection .noinstr.text, "ax"
.balign PAGE_SIZE
SYM_CODE_START(hypercall_page)
.rept (PAGE_SIZE / 32)
UNWIND_HINT_FUNC
ANNOTATE_NOENDBR
ANNOTATE_UNRET_SAFE
ret
/*
* Xen will write the hypercall page, and sort out ENDBR.
*/
.skip 31, 0xcc
.endr
#define HYPERCALL(n) \
.equ xen_hypercall_##n, hypercall_page + __HYPERVISOR_##n * 32; \
.type xen_hypercall_##n, @function; .size xen_hypercall_##n, 32
#include <asm/xen-hypercalls.h>
#undef HYPERCALL
SYM_CODE_END(hypercall_page)
.popsection
#ifdef CONFIG_XEN_PV #ifdef CONFIG_XEN_PV
__INIT __INIT
SYM_CODE_START(startup_xen) SYM_CODE_START(startup_xen)
@@ -80,6 +60,87 @@ SYM_CODE_END(asm_cpu_bringup_and_idle)
#endif #endif
#endif #endif
.pushsection .noinstr.text, "ax"
/*
* Xen hypercall interface to the hypervisor.
*
* Input:
* %eax: hypercall number
* 32-bit:
* %ebx, %ecx, %edx, %esi, %edi: args 1..5 for the hypercall
* 64-bit:
* %rdi, %rsi, %rdx, %r10, %r8: args 1..5 for the hypercall
* Output: %[er]ax
*/
SYM_FUNC_START(xen_hypercall_hvm)
ENDBR
FRAME_BEGIN
/* Save all relevant registers (caller save and arguments). */
#ifdef CONFIG_X86_32
push %eax
push %ebx
push %ecx
push %edx
push %esi
push %edi
#else
push %rax
push %rcx
push %rdx
push %rdi
push %rsi
push %r11
push %r10
push %r9
push %r8
#ifdef CONFIG_FRAME_POINTER
pushq $0 /* Dummy push for stack alignment. */
#endif
#endif
/* Set the vendor specific function. */
call __xen_hypercall_setfunc
/* Set ZF = 1 if AMD, Restore saved registers. */
#ifdef CONFIG_X86_32
lea xen_hypercall_amd, %ebx
cmp %eax, %ebx
pop %edi
pop %esi
pop %edx
pop %ecx
pop %ebx
pop %eax
#else
lea xen_hypercall_amd(%rip), %rbx
cmp %rax, %rbx
#ifdef CONFIG_FRAME_POINTER
pop %rax /* Dummy pop. */
#endif
pop %r8
pop %r9
pop %r10
pop %r11
pop %rsi
pop %rdi
pop %rdx
pop %rcx
pop %rax
#endif
/* Use correct hypercall function. */
jz xen_hypercall_amd
jmp xen_hypercall_intel
SYM_FUNC_END(xen_hypercall_hvm)
SYM_FUNC_START(xen_hypercall_amd)
vmmcall
RET
SYM_FUNC_END(xen_hypercall_amd)
SYM_FUNC_START(xen_hypercall_intel)
vmcall
RET
SYM_FUNC_END(xen_hypercall_intel)
.popsection
ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux") ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux")
ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz "2.6") ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz "2.6")
ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0") ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0")
@@ -93,7 +154,6 @@ SYM_CODE_END(asm_cpu_bringup_and_idle)
#ifdef CONFIG_XEN_PV #ifdef CONFIG_XEN_PV
ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, _ASM_PTR startup_xen) ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, _ASM_PTR startup_xen)
#endif #endif
ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page)
ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,
.ascii "!writable_page_tables|pae_pgdir_above_4gb") .ascii "!writable_page_tables|pae_pgdir_above_4gb")
ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES, ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES,

View File

@@ -162,4 +162,13 @@ void xen_hvm_post_suspend(int suspend_cancelled);
static inline void xen_hvm_post_suspend(int suspend_cancelled) {} static inline void xen_hvm_post_suspend(int suspend_cancelled) {}
#endif #endif
#ifdef CONFIG_XEN_PV
void xen_hypercall_pv(void);
#endif
void xen_hypercall_hvm(void);
void xen_hypercall_amd(void);
void xen_hypercall_intel(void);
void xen_hypercall_setfunc(void);
void *__xen_hypercall_setfunc(void);
#endif /* XEN_OPS_H */ #endif /* XEN_OPS_H */

View File

@@ -1110,10 +1110,14 @@ void blkcg_unpin_online(struct cgroup_subsys_state *blkcg_css)
struct blkcg *blkcg = css_to_blkcg(blkcg_css); struct blkcg *blkcg = css_to_blkcg(blkcg_css);
do { do {
struct blkcg *parent;
if (!refcount_dec_and_test(&blkcg->online_pin)) if (!refcount_dec_and_test(&blkcg->online_pin))
break; break;
parent = blkcg_parent(blkcg);
blkcg_destroy_blkgs(blkcg); blkcg_destroy_blkgs(blkcg);
blkcg = blkcg_parent(blkcg); blkcg = parent;
} while (blkcg); } while (blkcg);
} }

View File

@@ -1082,7 +1082,14 @@ static void __propagate_weights(struct ioc_gq *iocg, u32 active, u32 inuse,
inuse = DIV64_U64_ROUND_UP(active * iocg->child_inuse_sum, inuse = DIV64_U64_ROUND_UP(active * iocg->child_inuse_sum,
iocg->child_active_sum); iocg->child_active_sum);
} else { } else {
inuse = clamp_t(u32, inuse, 1, active); /*
* It may be tempting to turn this into a clamp expression with
* a lower limit of 1 but active may be 0, which cannot be used
* as an upper limit in that situation. This expression allows
* active to clamp inuse unless it is 0, in which case inuse
* becomes 1.
*/
inuse = min(inuse, active) ?: 1;
} }
iocg->last_inuse = iocg->inuse; iocg->last_inuse = iocg->inuse;

View File

@@ -201,8 +201,6 @@ acpi_remove_address_space_handler(acpi_handle device,
/* Now we can delete the handler object */ /* Now we can delete the handler object */
acpi_os_release_mutex(handler_obj->address_space.
context_mutex);
acpi_ut_remove_reference(handler_obj); acpi_ut_remove_reference(handler_obj);
goto unlock_and_exit; goto unlock_and_exit;
} }

View File

@@ -454,8 +454,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
if (cmd_rc) if (cmd_rc)
*cmd_rc = -EINVAL; *cmd_rc = -EINVAL;
if (cmd == ND_CMD_CALL) if (cmd == ND_CMD_CALL) {
if (!buf || buf_len < sizeof(*call_pkg))
return -EINVAL;
call_pkg = buf; call_pkg = buf;
}
func = cmd_to_func(nfit_mem, cmd, call_pkg, &family); func = cmd_to_func(nfit_mem, cmd, call_pkg, &family);
if (func < 0) if (func < 0)
return func; return func;

View File

@@ -250,6 +250,9 @@ static bool acpi_decode_space(struct resource_win *win,
switch (addr->resource_type) { switch (addr->resource_type) {
case ACPI_MEMORY_RANGE: case ACPI_MEMORY_RANGE:
acpi_dev_memresource_flags(res, len, wp); acpi_dev_memresource_flags(res, len, wp);
if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
res->flags |= IORESOURCE_PREFETCH;
break; break;
case ACPI_IO_RANGE: case ACPI_IO_RANGE:
acpi_dev_ioresource_flags(res, len, iodec, acpi_dev_ioresource_flags(res, len, iodec,
@@ -265,9 +268,6 @@ static bool acpi_decode_space(struct resource_win *win,
if (addr->producer_consumer == ACPI_PRODUCER) if (addr->producer_consumer == ACPI_PRODUCER)
res->flags |= IORESOURCE_WINDOW; res->flags |= IORESOURCE_WINDOW;
if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
res->flags |= IORESOURCE_PREFETCH;
return !(res->flags & IORESOURCE_DISABLED); return !(res->flags & IORESOURCE_DISABLED);
} }

View File

@@ -348,6 +348,7 @@ static int highbank_initialize_phys(struct device *dev, void __iomem *addr)
phy_nodes[phy] = phy_data.np; phy_nodes[phy] = phy_data.np;
cphy_base[phy] = of_iomap(phy_nodes[phy], 0); cphy_base[phy] = of_iomap(phy_nodes[phy], 0);
if (cphy_base[phy] == NULL) { if (cphy_base[phy] == NULL) {
of_node_put(phy_data.np);
return 0; return 0;
} }
phy_count += 1; phy_count += 1;

View File

@@ -1284,7 +1284,7 @@ static int uvd_v7_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
struct amdgpu_job *job, struct amdgpu_job *job,
struct amdgpu_ib *ib) struct amdgpu_ib *ib)
{ {
struct amdgpu_ring *ring = to_amdgpu_ring(job->base.sched); struct amdgpu_ring *ring = amdgpu_job_ring(job);
unsigned i; unsigned i;
/* No patching necessary for the first instance */ /* No patching necessary for the first instance */

View File

@@ -506,6 +506,6 @@ int __init i915_scheduler_module_init(void)
return 0; return 0;
err_priorities: err_priorities:
kmem_cache_destroy(slab_priorities); kmem_cache_destroy(slab_dependencies);
return -ENOMEM; return -ENOMEM;
} }

View File

@@ -1454,6 +1454,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
#define BOND_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \ #define BOND_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | \ NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | \
NETIF_F_GSO_ENCAP_ALL | \
NETIF_F_HIGHDMA | NETIF_F_LRO) NETIF_F_HIGHDMA | NETIF_F_LRO)
#define BOND_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \ #define BOND_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \

View File

@@ -22,7 +22,7 @@
#define VSC9959_NUM_PORTS 6 #define VSC9959_NUM_PORTS 6
#define VSC9959_TAS_GCL_ENTRY_MAX 63 #define VSC9959_TAS_GCL_ENTRY_MAX 63
#define VSC9959_TAS_MIN_GATE_LEN_NS 33 #define VSC9959_TAS_MIN_GATE_LEN_NS 35
#define VSC9959_VCAP_POLICER_BASE 63 #define VSC9959_VCAP_POLICER_BASE 63
#define VSC9959_VCAP_POLICER_MAX 383 #define VSC9959_VCAP_POLICER_MAX 383
#define VSC9959_SWITCH_PCI_BAR 4 #define VSC9959_SWITCH_PCI_BAR 4
@@ -1057,11 +1057,15 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
mdiobus_free(felix->imdio); mdiobus_free(felix->imdio);
} }
/* The switch considers any frame (regardless of size) as eligible for /* The switch considers any frame (regardless of size) as eligible
* transmission if the traffic class gate is open for at least 33 ns. * for transmission if the traffic class gate is open for at least
* VSC9959_TAS_MIN_GATE_LEN_NS.
*
* Overruns are prevented by cropping an interval at the end of the gate time * Overruns are prevented by cropping an interval at the end of the gate time
* slot for which egress scheduling is blocked, but we need to still keep 33 ns * slot for which egress scheduling is blocked, but we need to still keep
* available for one packet to be transmitted, otherwise the port tc will hang. * VSC9959_TAS_MIN_GATE_LEN_NS available for one packet to be transmitted,
* otherwise the port tc will hang.
*
* This function returns the size of a gate interval that remains available for * This function returns the size of a gate interval that remains available for
* setting the guard band, after reserving the space for one egress frame. * setting the guard band, after reserving the space for one egress frame.
*/ */
@@ -1293,7 +1297,8 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
* per-tc static guard band lengths, so it reduces the * per-tc static guard band lengths, so it reduces the
* useful gate interval length. Therefore, be careful * useful gate interval length. Therefore, be careful
* to calculate a guard band (and therefore max_sdu) * to calculate a guard band (and therefore max_sdu)
* that still leaves 33 ns available in the time slot. * that still leaves VSC9959_TAS_MIN_GATE_LEN_NS
* available in the time slot.
*/ */
max_sdu = div_u64(remaining_gate_len_ps, picos_per_byte); max_sdu = div_u64(remaining_gate_len_ps, picos_per_byte);
/* A TC gate may be completely closed, which is a /* A TC gate may be completely closed, which is a

View File

@@ -2084,7 +2084,7 @@ void t4_idma_monitor(struct adapter *adapter,
struct sge_idma_monitor_state *idma, struct sge_idma_monitor_state *idma,
int hz, int ticks); int hz, int ticks);
int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf, int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf,
unsigned int naddr, u8 *addr); u8 start, unsigned int naddr, u8 *addr);
void t4_tp_pio_read(struct adapter *adap, u32 *buff, u32 nregs, void t4_tp_pio_read(struct adapter *adap, u32 *buff, u32 nregs,
u32 start_index, bool sleep_ok); u32 start_index, bool sleep_ok);
void t4_tp_tm_pio_read(struct adapter *adap, u32 *buff, u32 nregs, void t4_tp_tm_pio_read(struct adapter *adap, u32 *buff, u32 nregs,

View File

@@ -3247,7 +3247,7 @@ static int cxgb4_mgmt_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
dev_info(pi->adapter->pdev_dev, dev_info(pi->adapter->pdev_dev,
"Setting MAC %pM on VF %d\n", mac, vf); "Setting MAC %pM on VF %d\n", mac, vf);
ret = t4_set_vf_mac_acl(adap, vf + 1, 1, mac); ret = t4_set_vf_mac_acl(adap, vf + 1, pi->lport, 1, mac);
if (!ret) if (!ret)
ether_addr_copy(adap->vfinfo[vf].vf_mac_addr, mac); ether_addr_copy(adap->vfinfo[vf].vf_mac_addr, mac);
return ret; return ret;

View File

@@ -10215,11 +10215,12 @@ out:
* t4_set_vf_mac_acl - Set MAC address for the specified VF * t4_set_vf_mac_acl - Set MAC address for the specified VF
* @adapter: The adapter * @adapter: The adapter
* @vf: one of the VFs instantiated by the specified PF * @vf: one of the VFs instantiated by the specified PF
* @start: The start port id associated with specified VF
* @naddr: the number of MAC addresses * @naddr: the number of MAC addresses
* @addr: the MAC address(es) to be set to the specified VF * @addr: the MAC address(es) to be set to the specified VF
*/ */
int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf, int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf,
unsigned int naddr, u8 *addr) u8 start, unsigned int naddr, u8 *addr)
{ {
struct fw_acl_mac_cmd cmd; struct fw_acl_mac_cmd cmd;
@@ -10234,7 +10235,7 @@ int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf,
cmd.en_to_len16 = cpu_to_be32((unsigned int)FW_LEN16(cmd)); cmd.en_to_len16 = cpu_to_be32((unsigned int)FW_LEN16(cmd));
cmd.nmac = naddr; cmd.nmac = naddr;
switch (adapter->pf) { switch (start) {
case 3: case 3:
memcpy(cmd.macaddr3, addr, sizeof(cmd.macaddr3)); memcpy(cmd.macaddr3, addr, sizeof(cmd.macaddr3));
break; break;

View File

@@ -195,7 +195,9 @@ dr_domain_add_vport_cap(struct mlx5dr_domain *dmn, u16 vport)
if (ret) { if (ret) {
mlx5dr_dbg(dmn, "Couldn't insert new vport into xarray (%d)\n", ret); mlx5dr_dbg(dmn, "Couldn't insert new vport into xarray (%d)\n", ret);
kvfree(vport_caps); kvfree(vport_caps);
return ERR_PTR(ret); if (ret == -EBUSY)
return ERR_PTR(-EBUSY);
return NULL;
} }
return vport_caps; return vport_caps;

View File

@@ -680,12 +680,11 @@ static int sparx5_start(struct sparx5 *sparx5)
err = -ENXIO; err = -ENXIO;
if (sparx5->fdma_irq >= 0) { if (sparx5->fdma_irq >= 0) {
if (GCB_CHIP_ID_REV_ID_GET(sparx5->chip_id) > 0) if (GCB_CHIP_ID_REV_ID_GET(sparx5->chip_id) > 0)
err = devm_request_threaded_irq(sparx5->dev, err = devm_request_irq(sparx5->dev,
sparx5->fdma_irq, sparx5->fdma_irq,
NULL, sparx5_fdma_handler,
sparx5_fdma_handler, 0,
IRQF_ONESHOT, "sparx5-fdma", sparx5);
"sparx5-fdma", sparx5);
if (!err) if (!err)
err = sparx5_fdma_start(sparx5); err = sparx5_fdma_start(sparx5);
if (err) if (err)

View File

@@ -1113,7 +1113,7 @@ int sparx5_port_init(struct sparx5 *sparx5,
spx5_inst_rmw(DEV10G_MAC_MAXLEN_CFG_MAX_LEN_SET(ETH_MAXLEN), spx5_inst_rmw(DEV10G_MAC_MAXLEN_CFG_MAX_LEN_SET(ETH_MAXLEN),
DEV10G_MAC_MAXLEN_CFG_MAX_LEN, DEV10G_MAC_MAXLEN_CFG_MAX_LEN,
devinst, devinst,
DEV10G_MAC_ENA_CFG(0)); DEV10G_MAC_MAXLEN_CFG(0));
/* Handle Signal Detect in 10G PCS */ /* Handle Signal Detect in 10G PCS */
spx5_inst_wr(PCS10G_BR_PCS_SD_CFG_SD_POL_SET(sd_pol) | spx5_inst_wr(PCS10G_BR_PCS_SD_CFG_SD_POL_SET(sd_pol) |

View File

@@ -14,6 +14,8 @@
#include <soc/mscc/ocelot.h> #include <soc/mscc/ocelot.h>
#include "ocelot.h" #include "ocelot.h"
#define OCELOT_PTP_TX_TSTAMP_TIMEOUT (5 * HZ)
int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts) int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
{ {
struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info); struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
@@ -495,6 +497,28 @@ static int ocelot_traps_to_ptp_rx_filter(unsigned int proto)
return HWTSTAMP_FILTER_NONE; return HWTSTAMP_FILTER_NONE;
} }
static int ocelot_ptp_tx_type_to_cmd(int tx_type, int *ptp_cmd)
{
switch (tx_type) {
case HWTSTAMP_TX_ON:
*ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
break;
case HWTSTAMP_TX_ONESTEP_SYNC:
/* IFH_REW_OP_ONE_STEP_PTP updates the correctionField,
* what we need to update is the originTimestamp.
*/
*ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
break;
case HWTSTAMP_TX_OFF:
*ptp_cmd = 0;
break;
default:
return -ERANGE;
}
return 0;
}
int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr) int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr)
{ {
struct ocelot_port *ocelot_port = ocelot->ports[port]; struct ocelot_port *ocelot_port = ocelot->ports[port];
@@ -521,30 +545,19 @@ EXPORT_SYMBOL(ocelot_hwstamp_get);
int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr) int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
{ {
struct ocelot_port *ocelot_port = ocelot->ports[port]; struct ocelot_port *ocelot_port = ocelot->ports[port];
int ptp_cmd, old_ptp_cmd = ocelot_port->ptp_cmd;
bool l2 = false, l4 = false; bool l2 = false, l4 = false;
struct hwtstamp_config cfg; struct hwtstamp_config cfg;
bool old_l2, old_l4;
int err; int err;
if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg))) if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
return -EFAULT; return -EFAULT;
/* Tx type sanity check */ /* Tx type sanity check */
switch (cfg.tx_type) { err = ocelot_ptp_tx_type_to_cmd(cfg.tx_type, &ptp_cmd);
case HWTSTAMP_TX_ON: if (err)
ocelot_port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP; return err;
break;
case HWTSTAMP_TX_ONESTEP_SYNC:
/* IFH_REW_OP_ONE_STEP_PTP updates the correctional field, we
* need to update the origin time.
*/
ocelot_port->ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
break;
case HWTSTAMP_TX_OFF:
ocelot_port->ptp_cmd = 0;
break;
default:
return -ERANGE;
}
switch (cfg.rx_filter) { switch (cfg.rx_filter) {
case HWTSTAMP_FILTER_NONE: case HWTSTAMP_FILTER_NONE:
@@ -569,13 +582,27 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
return -ERANGE; return -ERANGE;
} }
old_l2 = ocelot_port->trap_proto & OCELOT_PROTO_PTP_L2;
old_l4 = ocelot_port->trap_proto & OCELOT_PROTO_PTP_L4;
err = ocelot_setup_ptp_traps(ocelot, port, l2, l4); err = ocelot_setup_ptp_traps(ocelot, port, l2, l4);
if (err) if (err)
return err; return err;
ocelot_port->ptp_cmd = ptp_cmd;
cfg.rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto); cfg.rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto);
return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0; if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg))) {
err = -EFAULT;
goto out_restore_ptp_traps;
}
return 0;
out_restore_ptp_traps:
ocelot_setup_ptp_traps(ocelot, port, old_l2, old_l4);
ocelot_port->ptp_cmd = old_ptp_cmd;
return err;
} }
EXPORT_SYMBOL(ocelot_hwstamp_set); EXPORT_SYMBOL(ocelot_hwstamp_set);
@@ -607,34 +634,87 @@ int ocelot_get_ts_info(struct ocelot *ocelot, int port,
} }
EXPORT_SYMBOL(ocelot_get_ts_info); EXPORT_SYMBOL(ocelot_get_ts_info);
static int ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port, static struct sk_buff *ocelot_port_dequeue_ptp_tx_skb(struct ocelot *ocelot,
int port, u8 ts_id,
u32 seqid)
{
struct ocelot_port *ocelot_port = ocelot->ports[port];
struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
struct ptp_header *hdr;
spin_lock(&ocelot->ts_id_lock);
skb_queue_walk_safe(&ocelot_port->tx_skbs, skb, skb_tmp) {
if (OCELOT_SKB_CB(skb)->ts_id != ts_id)
continue;
/* Check that the timestamp ID is for the expected PTP
* sequenceId. We don't have to test ptp_parse_header() against
* NULL, because we've pre-validated the packet's ptp_class.
*/
hdr = ptp_parse_header(skb, OCELOT_SKB_CB(skb)->ptp_class);
if (seqid != ntohs(hdr->sequence_id))
continue;
__skb_unlink(skb, &ocelot_port->tx_skbs);
ocelot->ptp_skbs_in_flight--;
skb_match = skb;
break;
}
spin_unlock(&ocelot->ts_id_lock);
return skb_match;
}
static int ocelot_port_queue_ptp_tx_skb(struct ocelot *ocelot, int port,
struct sk_buff *clone) struct sk_buff *clone)
{ {
struct ocelot_port *ocelot_port = ocelot->ports[port]; struct ocelot_port *ocelot_port = ocelot->ports[port];
unsigned long flags; DECLARE_BITMAP(ts_id_in_flight, OCELOT_MAX_PTP_ID);
struct sk_buff *skb, *skb_tmp;
unsigned long n;
spin_lock_irqsave(&ocelot->ts_id_lock, flags); spin_lock(&ocelot->ts_id_lock);
if (ocelot_port->ptp_skbs_in_flight == OCELOT_MAX_PTP_ID || /* To get a better chance of acquiring a timestamp ID, first flush the
ocelot->ptp_skbs_in_flight == OCELOT_PTP_FIFO_SIZE) { * stale packets still waiting in the TX timestamping queue. They are
spin_unlock_irqrestore(&ocelot->ts_id_lock, flags); * probably lost.
*/
skb_queue_walk_safe(&ocelot_port->tx_skbs, skb, skb_tmp) {
if (time_before(OCELOT_SKB_CB(skb)->ptp_tx_time +
OCELOT_PTP_TX_TSTAMP_TIMEOUT, jiffies)) {
dev_warn_ratelimited(ocelot->dev,
"port %d invalidating stale timestamp ID %u which seems lost\n",
port, OCELOT_SKB_CB(skb)->ts_id);
__skb_unlink(skb, &ocelot_port->tx_skbs);
kfree_skb(skb);
ocelot->ptp_skbs_in_flight--;
} else {
__set_bit(OCELOT_SKB_CB(skb)->ts_id, ts_id_in_flight);
}
}
if (ocelot->ptp_skbs_in_flight == OCELOT_PTP_FIFO_SIZE) {
spin_unlock(&ocelot->ts_id_lock);
return -EBUSY; return -EBUSY;
} }
skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS; n = find_first_zero_bit(ts_id_in_flight, OCELOT_MAX_PTP_ID);
/* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */ if (n == OCELOT_MAX_PTP_ID) {
OCELOT_SKB_CB(clone)->ts_id = ocelot_port->ts_id; spin_unlock(&ocelot->ts_id_lock);
return -EBUSY;
}
ocelot_port->ts_id++; /* Found an available timestamp ID, use it */
if (ocelot_port->ts_id == OCELOT_MAX_PTP_ID) OCELOT_SKB_CB(clone)->ts_id = n;
ocelot_port->ts_id = 0; OCELOT_SKB_CB(clone)->ptp_tx_time = jiffies;
ocelot_port->ptp_skbs_in_flight++;
ocelot->ptp_skbs_in_flight++; ocelot->ptp_skbs_in_flight++;
__skb_queue_tail(&ocelot_port->tx_skbs, clone);
skb_queue_tail(&ocelot_port->tx_skbs, clone); spin_unlock(&ocelot->ts_id_lock);
spin_unlock_irqrestore(&ocelot->ts_id_lock, flags); dev_dbg_ratelimited(ocelot->dev, "port %d timestamp id %lu\n", port, n);
return 0; return 0;
} }
@@ -691,10 +771,14 @@ int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port,
if (!(*clone)) if (!(*clone))
return -ENOMEM; return -ENOMEM;
err = ocelot_port_add_txtstamp_skb(ocelot, port, *clone); /* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */
if (err) err = ocelot_port_queue_ptp_tx_skb(ocelot, port, *clone);
if (err) {
kfree_skb(*clone);
return err; return err;
}
skb_shinfo(*clone)->tx_flags |= SKBTX_IN_PROGRESS;
OCELOT_SKB_CB(skb)->ptp_cmd = ptp_cmd; OCELOT_SKB_CB(skb)->ptp_cmd = ptp_cmd;
OCELOT_SKB_CB(*clone)->ptp_class = ptp_class; OCELOT_SKB_CB(*clone)->ptp_class = ptp_class;
} }
@@ -730,28 +814,15 @@ static void ocelot_get_hwtimestamp(struct ocelot *ocelot,
spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags); spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
} }
static bool ocelot_validate_ptp_skb(struct sk_buff *clone, u16 seqid)
{
struct ptp_header *hdr;
hdr = ptp_parse_header(clone, OCELOT_SKB_CB(clone)->ptp_class);
if (WARN_ON(!hdr))
return false;
return seqid == ntohs(hdr->sequence_id);
}
void ocelot_get_txtstamp(struct ocelot *ocelot) void ocelot_get_txtstamp(struct ocelot *ocelot)
{ {
int budget = OCELOT_PTP_QUEUE_SZ; int budget = OCELOT_PTP_QUEUE_SZ;
while (budget--) { while (budget--) {
struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
struct skb_shared_hwtstamps shhwtstamps; struct skb_shared_hwtstamps shhwtstamps;
u32 val, id, seqid, txport; u32 val, id, seqid, txport;
struct ocelot_port *port; struct sk_buff *skb_match;
struct timespec64 ts; struct timespec64 ts;
unsigned long flags;
val = ocelot_read(ocelot, SYS_PTP_STATUS); val = ocelot_read(ocelot, SYS_PTP_STATUS);
@@ -766,36 +837,14 @@ void ocelot_get_txtstamp(struct ocelot *ocelot)
txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val); txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);
seqid = SYS_PTP_STATUS_PTP_MESS_SEQ_ID(val); seqid = SYS_PTP_STATUS_PTP_MESS_SEQ_ID(val);
port = ocelot->ports[txport];
spin_lock(&ocelot->ts_id_lock);
port->ptp_skbs_in_flight--;
ocelot->ptp_skbs_in_flight--;
spin_unlock(&ocelot->ts_id_lock);
/* Retrieve its associated skb */ /* Retrieve its associated skb */
try_again: skb_match = ocelot_port_dequeue_ptp_tx_skb(ocelot, txport, id,
spin_lock_irqsave(&port->tx_skbs.lock, flags); seqid);
if (!skb_match) {
skb_queue_walk_safe(&port->tx_skbs, skb, skb_tmp) { dev_warn_ratelimited(ocelot->dev,
if (OCELOT_SKB_CB(skb)->ts_id != id) "port %d received TX timestamp (seqid %d, ts id %u) for packet previously declared stale\n",
continue; txport, seqid, id);
__skb_unlink(skb, &port->tx_skbs); goto next_ts;
skb_match = skb;
break;
}
spin_unlock_irqrestore(&port->tx_skbs.lock, flags);
if (WARN_ON(!skb_match))
continue;
if (!ocelot_validate_ptp_skb(skb_match, seqid)) {
dev_err_ratelimited(ocelot->dev,
"port %d received stale TX timestamp for seqid %d, discarding\n",
txport, seqid);
dev_kfree_skb_any(skb);
goto try_again;
} }
/* Get the h/w timestamp */ /* Get the h/w timestamp */
@@ -806,7 +855,7 @@ try_again:
shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec); shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
skb_complete_tx_timestamp(skb_match, &shhwtstamps); skb_complete_tx_timestamp(skb_match, &shhwtstamps);
/* Next ts */ next_ts:
ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT); ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
} }
} }

View File

@@ -67,7 +67,7 @@ MODULE_PARM_DESC(qcaspi_burst_len, "Number of data bytes per burst. Use 1-5000."
#define QCASPI_PLUGGABLE_MIN 0 #define QCASPI_PLUGGABLE_MIN 0
#define QCASPI_PLUGGABLE_MAX 1 #define QCASPI_PLUGGABLE_MAX 1
static int qcaspi_pluggable = QCASPI_PLUGGABLE_MIN; static int qcaspi_pluggable = QCASPI_PLUGGABLE_MAX;
module_param(qcaspi_pluggable, int, 0); module_param(qcaspi_pluggable, int, 0);
MODULE_PARM_DESC(qcaspi_pluggable, "Pluggable SPI connection (yes/no)."); MODULE_PARM_DESC(qcaspi_pluggable, "Pluggable SPI connection (yes/no).");
@@ -829,7 +829,6 @@ qcaspi_netdev_init(struct net_device *dev)
dev->mtu = QCAFRM_MAX_MTU; dev->mtu = QCAFRM_MAX_MTU;
dev->type = ARPHRD_ETHER; dev->type = ARPHRD_ETHER;
qca->clkspeed = qcaspi_clkspeed;
qca->burst_len = qcaspi_burst_len; qca->burst_len = qcaspi_burst_len;
qca->spi_thread = NULL; qca->spi_thread = NULL;
qca->buffer_size = (dev->mtu + VLAN_ETH_HLEN + QCAFRM_HEADER_LEN + qca->buffer_size = (dev->mtu + VLAN_ETH_HLEN + QCAFRM_HEADER_LEN +
@@ -918,17 +917,15 @@ qca_spi_probe(struct spi_device *spi)
legacy_mode = of_property_read_bool(spi->dev.of_node, legacy_mode = of_property_read_bool(spi->dev.of_node,
"qca,legacy-mode"); "qca,legacy-mode");
if (qcaspi_clkspeed == 0) { if (qcaspi_clkspeed)
if (spi->max_speed_hz) spi->max_speed_hz = qcaspi_clkspeed;
qcaspi_clkspeed = spi->max_speed_hz; else if (!spi->max_speed_hz)
else spi->max_speed_hz = QCASPI_CLK_SPEED;
qcaspi_clkspeed = QCASPI_CLK_SPEED;
}
if ((qcaspi_clkspeed < QCASPI_CLK_SPEED_MIN) || if (spi->max_speed_hz < QCASPI_CLK_SPEED_MIN ||
(qcaspi_clkspeed > QCASPI_CLK_SPEED_MAX)) { spi->max_speed_hz > QCASPI_CLK_SPEED_MAX) {
dev_err(&spi->dev, "Invalid clkspeed: %d\n", dev_err(&spi->dev, "Invalid clkspeed: %u\n",
qcaspi_clkspeed); spi->max_speed_hz);
return -EINVAL; return -EINVAL;
} }
@@ -953,14 +950,13 @@ qca_spi_probe(struct spi_device *spi)
return -EINVAL; return -EINVAL;
} }
dev_info(&spi->dev, "ver=%s, clkspeed=%d, burst_len=%d, pluggable=%d\n", dev_info(&spi->dev, "ver=%s, clkspeed=%u, burst_len=%d, pluggable=%d\n",
QCASPI_DRV_VERSION, QCASPI_DRV_VERSION,
qcaspi_clkspeed, spi->max_speed_hz,
qcaspi_burst_len, qcaspi_burst_len,
qcaspi_pluggable); qcaspi_pluggable);
spi->mode = SPI_MODE_3; spi->mode = SPI_MODE_3;
spi->max_speed_hz = qcaspi_clkspeed;
if (spi_setup(spi) < 0) { if (spi_setup(spi) < 0) {
dev_err(&spi->dev, "Unable to setup SPI device\n"); dev_err(&spi->dev, "Unable to setup SPI device\n");
return -EFAULT; return -EFAULT;

View File

@@ -101,7 +101,6 @@ struct qcaspi {
#endif #endif
/* user configurable options */ /* user configurable options */
u32 clkspeed;
u8 legacy_mode; u8 legacy_mode;
u16 burst_len; u16 burst_len;
}; };

View File

@@ -984,7 +984,8 @@ static void team_port_disable(struct team *team,
#define TEAM_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \ #define TEAM_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | \ NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | \
NETIF_F_HIGHDMA | NETIF_F_LRO) NETIF_F_HIGHDMA | NETIF_F_LRO | \
NETIF_F_GSO_ENCAP_ALL)
#define TEAM_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \ #define TEAM_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
NETIF_F_RXCSUM | NETIF_F_GSO_SOFTWARE) NETIF_F_RXCSUM | NETIF_F_GSO_SOFTWARE)

View File

@@ -867,7 +867,7 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev
static int xennet_close(struct net_device *dev) static int xennet_close(struct net_device *dev)
{ {
struct netfront_info *np = netdev_priv(dev); struct netfront_info *np = netdev_priv(dev);
unsigned int num_queues = dev->real_num_tx_queues; unsigned int num_queues = np->queues ? dev->real_num_tx_queues : 0;
unsigned int i; unsigned int i;
struct netfront_queue *queue; struct netfront_queue *queue;
netif_tx_stop_all_queues(np->netdev); netif_tx_stop_all_queues(np->netdev);
@@ -882,6 +882,9 @@ static void xennet_destroy_queues(struct netfront_info *info)
{ {
unsigned int i; unsigned int i;
if (!info->queues)
return;
for (i = 0; i < info->netdev->real_num_tx_queues; i++) { for (i = 0; i < info->netdev->real_num_tx_queues; i++) {
struct netfront_queue *queue = &info->queues[i]; struct netfront_queue *queue = &info->queues[i];

View File

@@ -22,6 +22,10 @@ int kvm_arch_ptp_init(void)
return 0; return 0;
} }
void kvm_arch_ptp_exit(void)
{
}
int kvm_arch_ptp_get_clock(struct timespec64 *ts) int kvm_arch_ptp_get_clock(struct timespec64 *ts)
{ {
return kvm_arch_ptp_get_crosststamp(NULL, ts, NULL); return kvm_arch_ptp_get_crosststamp(NULL, ts, NULL);

View File

@@ -130,6 +130,7 @@ static struct kvm_ptp_clock kvm_ptp_clock;
static void __exit ptp_kvm_exit(void) static void __exit ptp_kvm_exit(void)
{ {
ptp_clock_unregister(kvm_ptp_clock.ptp_clock); ptp_clock_unregister(kvm_ptp_clock.ptp_clock);
kvm_arch_ptp_exit();
} }
static int __init ptp_kvm_init(void) static int __init ptp_kvm_init(void)

View File

@@ -14,27 +14,64 @@
#include <uapi/linux/kvm_para.h> #include <uapi/linux/kvm_para.h>
#include <linux/ptp_clock_kernel.h> #include <linux/ptp_clock_kernel.h>
#include <linux/ptp_kvm.h> #include <linux/ptp_kvm.h>
#include <linux/set_memory.h>
static phys_addr_t clock_pair_gpa; static phys_addr_t clock_pair_gpa;
static struct kvm_clock_pairing clock_pair; static struct kvm_clock_pairing clock_pair_glbl;
static struct kvm_clock_pairing *clock_pair;
int kvm_arch_ptp_init(void) int kvm_arch_ptp_init(void)
{ {
struct page *p;
long ret; long ret;
if (!kvm_para_available()) if (!kvm_para_available())
return -ENODEV; return -EOPNOTSUPP;
clock_pair_gpa = slow_virt_to_phys(&clock_pair); if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
if (!pvclock_get_pvti_cpu0_va()) p = alloc_page(GFP_KERNEL | __GFP_ZERO);
return -ENODEV; if (!p)
return -ENOMEM;
clock_pair = page_address(p);
ret = set_memory_decrypted((unsigned long)clock_pair, 1);
if (ret) {
__free_page(p);
clock_pair = NULL;
goto nofree;
}
} else {
clock_pair = &clock_pair_glbl;
}
clock_pair_gpa = slow_virt_to_phys(clock_pair);
if (!pvclock_get_pvti_cpu0_va()) {
ret = -EOPNOTSUPP;
goto err;
}
ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, clock_pair_gpa, ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, clock_pair_gpa,
KVM_CLOCK_PAIRING_WALLCLOCK); KVM_CLOCK_PAIRING_WALLCLOCK);
if (ret == -KVM_ENOSYS) if (ret == -KVM_ENOSYS) {
return -ENODEV; ret = -EOPNOTSUPP;
goto err;
}
return ret; return ret;
err:
kvm_arch_ptp_exit();
nofree:
return ret;
}
void kvm_arch_ptp_exit(void)
{
if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
WARN_ON(set_memory_encrypted((unsigned long)clock_pair, 1));
free_page((unsigned long)clock_pair);
clock_pair = NULL;
}
} }
int kvm_arch_ptp_get_clock(struct timespec64 *ts) int kvm_arch_ptp_get_clock(struct timespec64 *ts)
@@ -49,8 +86,8 @@ int kvm_arch_ptp_get_clock(struct timespec64 *ts)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
ts->tv_sec = clock_pair.sec; ts->tv_sec = clock_pair->sec;
ts->tv_nsec = clock_pair.nsec; ts->tv_nsec = clock_pair->nsec;
return 0; return 0;
} }
@@ -81,9 +118,9 @@ int kvm_arch_ptp_get_crosststamp(u64 *cycle, struct timespec64 *tspec,
pr_err_ratelimited("clock pairing hypercall ret %lu\n", ret); pr_err_ratelimited("clock pairing hypercall ret %lu\n", ret);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
tspec->tv_sec = clock_pair.sec; tspec->tv_sec = clock_pair->sec;
tspec->tv_nsec = clock_pair.nsec; tspec->tv_nsec = clock_pair->nsec;
*cycle = __pvclock_read_cycles(src, clock_pair.tsc); *cycle = __pvclock_read_cycles(src, clock_pair->tsc);
} while (pvclock_read_retry(src, version)); } while (pvclock_read_retry(src, version));
*cs = &kvm_clock; *cs = &kvm_clock;

View File

@@ -239,7 +239,7 @@ static ssize_t aspeed_spi_read_user(struct aspeed_spi_chip *chip,
ret = aspeed_spi_send_cmd_addr(chip, op->addr.nbytes, offset, op->cmd.opcode); ret = aspeed_spi_send_cmd_addr(chip, op->addr.nbytes, offset, op->cmd.opcode);
if (ret < 0) if (ret < 0)
return ret; goto stop_user;
if (op->dummy.buswidth && op->dummy.nbytes) { if (op->dummy.buswidth && op->dummy.nbytes) {
for (i = 0; i < op->dummy.nbytes / op->dummy.buswidth; i++) for (i = 0; i < op->dummy.nbytes / op->dummy.buswidth; i++)
@@ -249,8 +249,9 @@ static ssize_t aspeed_spi_read_user(struct aspeed_spi_chip *chip,
aspeed_spi_set_io_mode(chip, io_mode); aspeed_spi_set_io_mode(chip, io_mode);
aspeed_spi_read_from_ahb(buf, chip->ahb_base, len); aspeed_spi_read_from_ahb(buf, chip->ahb_base, len);
stop_user:
aspeed_spi_stop_user(chip); aspeed_spi_stop_user(chip);
return 0; return ret;
} }
static ssize_t aspeed_spi_write_user(struct aspeed_spi_chip *chip, static ssize_t aspeed_spi_write_user(struct aspeed_spi_chip *chip,
@@ -261,10 +262,11 @@ static ssize_t aspeed_spi_write_user(struct aspeed_spi_chip *chip,
aspeed_spi_start_user(chip); aspeed_spi_start_user(chip);
ret = aspeed_spi_send_cmd_addr(chip, op->addr.nbytes, op->addr.val, op->cmd.opcode); ret = aspeed_spi_send_cmd_addr(chip, op->addr.nbytes, op->addr.val, op->cmd.opcode);
if (ret < 0) if (ret < 0)
return ret; goto stop_user;
aspeed_spi_write_to_ahb(chip->ahb_base, op->data.buf.out, op->data.nbytes); aspeed_spi_write_to_ahb(chip->ahb_base, op->data.buf.out, op->data.nbytes);
stop_user:
aspeed_spi_stop_user(chip); aspeed_spi_stop_user(chip);
return 0; return ret;
} }
/* support for 1-1-1, 1-1-2 or 1-1-4 */ /* support for 1-1-1, 1-1-2 or 1-1-4 */

View File

@@ -3546,11 +3546,9 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
port_status |= USB_PORT_STAT_C_OVERCURRENT << 16; port_status |= USB_PORT_STAT_C_OVERCURRENT << 16;
} }
if (!hsotg->flags.b.port_connect_status) { if (dwc2_is_device_mode(hsotg)) {
/* /*
* The port is disconnected, which means the core is * Just return 0's for the remainder of the port status
* either in device mode or it soon will be. Just
* return 0's for the remainder of the port status
* since the port register can't be read if the core * since the port register can't be read if the core
* is in device mode. * is in device mode.
*/ */
@@ -3620,13 +3618,11 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1)) if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1))
goto error; goto error;
if (!hsotg->flags.b.port_connect_status) { if (dwc2_is_device_mode(hsotg)) {
/* /*
* The port is disconnected, which means the core is * Just return 0's for the remainder of the port status
* either in device mode or it soon will be. Just * since the port register can't be read if the core
* return without doing anything since the port * is in device mode.
* register can't be written if the core is in device
* mode.
*/ */
break; break;
} }
@@ -4349,7 +4345,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
if (hsotg->bus_suspended) if (hsotg->bus_suspended)
goto skip_power_saving; goto skip_power_saving;
if (hsotg->flags.b.port_connect_status == 0) if (!(dwc2_read_hprt0(hsotg) & HPRT0_CONNSTS))
goto skip_power_saving; goto skip_power_saving;
switch (hsotg->params.power_down) { switch (hsotg->params.power_down) {
@@ -4431,6 +4427,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
* Power Down mode. * Power Down mode.
*/ */
if (hprt0 & HPRT0_CONNSTS) { if (hprt0 & HPRT0_CONNSTS) {
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
hsotg->lx_state = DWC2_L0; hsotg->lx_state = DWC2_L0;
goto unlock; goto unlock;
} }

View File

@@ -122,8 +122,11 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
* in use but the usb3-phy entry is missing from the device tree. * in use but the usb3-phy entry is missing from the device tree.
* Therefore, skip these operations in this case. * Therefore, skip these operations in this case.
*/ */
if (!priv_data->usb3_phy) if (!priv_data->usb3_phy) {
/* Deselect the PIPE Clock Select bit in FPD PIPE Clock register */
writel(PIPE_CLK_DESELECT, priv_data->regs + XLNX_USB_FPD_PIPE_CLK);
goto skip_usb3_phy; goto skip_usb3_phy;
}
crst = devm_reset_control_get_exclusive(dev, "usb_crst"); crst = devm_reset_control_get_exclusive(dev, "usb_crst");
if (IS_ERR(crst)) { if (IS_ERR(crst)) {

View File

@@ -580,9 +580,12 @@ static int gs_start_io(struct gs_port *port)
tty_wakeup(port->port.tty); tty_wakeup(port->port.tty);
} else { } else {
out: out:
gs_free_requests(ep, head, &port->read_allocated); /* Free reqs only if we are still connected */
gs_free_requests(port->port_usb->in, &port->write_pool, if (port->port_usb) {
&port->write_allocated); gs_free_requests(ep, head, &port->read_allocated);
gs_free_requests(port->port_usb->in, &port->write_pool,
&port->write_allocated);
}
status = -EIO; status = -EIO;
} }

View File

@@ -120,8 +120,12 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
if (IS_ERR(priv->iclk)) if (IS_ERR(priv->iclk))
priv->iclk = NULL; priv->iclk = NULL;
clk_enable(priv->fclk); ret = clk_enable(priv->fclk);
clk_enable(priv->iclk); if (ret)
goto fail_request_resource;
ret = clk_enable(priv->iclk);
if (ret)
goto fail_iclk;
ret = usb_add_hcd(hcd, irq, IRQF_SHARED); ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (ret != 0) { if (ret != 0) {
@@ -137,6 +141,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
fail_add_hcd: fail_add_hcd:
clk_disable(priv->iclk); clk_disable(priv->iclk);
fail_iclk:
clk_disable(priv->fclk); clk_disable(priv->fclk);
fail_request_resource: fail_request_resource:

View File

@@ -785,11 +785,17 @@ max3421_check_unlink(struct usb_hcd *hcd)
retval = 1; retval = 1;
dev_dbg(&spi->dev, "%s: URB %p unlinked=%d", dev_dbg(&spi->dev, "%s: URB %p unlinked=%d",
__func__, urb, urb->unlinked); __func__, urb, urb->unlinked);
usb_hcd_unlink_urb_from_ep(hcd, urb); if (urb == max3421_hcd->curr_urb) {
spin_unlock_irqrestore(&max3421_hcd->lock, max3421_hcd->urb_done = 1;
flags); max3421_hcd->hien &= ~(BIT(MAX3421_HI_HXFRDN_BIT) |
usb_hcd_giveback_urb(hcd, urb, 0); BIT(MAX3421_HI_RCVDAV_BIT));
spin_lock_irqsave(&max3421_hcd->lock, flags); } else {
usb_hcd_unlink_urb_from_ep(hcd, urb);
spin_unlock_irqrestore(&max3421_hcd->lock,
flags);
usb_hcd_giveback_urb(hcd, urb, 0);
spin_lock_irqsave(&max3421_hcd->lock, flags);
}
} }
} }
} }

View File

@@ -289,6 +289,8 @@ struct anx7411_data {
struct power_supply *psy; struct power_supply *psy;
struct power_supply_desc psy_desc; struct power_supply_desc psy_desc;
struct device *dev; struct device *dev;
struct fwnode_handle *switch_node;
struct fwnode_handle *mux_node;
}; };
static u8 snk_identity[] = { static u8 snk_identity[] = {
@@ -1020,6 +1022,16 @@ static void anx7411_port_unregister_altmodes(struct typec_altmode **adev)
} }
} }
static void anx7411_port_unregister(struct typec_params *typecp)
{
fwnode_handle_put(typecp->caps.fwnode);
anx7411_port_unregister_altmodes(typecp->port_amode);
if (typecp->port)
typec_unregister_port(typecp->port);
if (typecp->role_sw)
usb_role_switch_put(typecp->role_sw);
}
static int anx7411_usb_mux_set(struct typec_mux_dev *mux, static int anx7411_usb_mux_set(struct typec_mux_dev *mux,
struct typec_mux_state *state) struct typec_mux_state *state)
{ {
@@ -1088,6 +1100,7 @@ static void anx7411_unregister_mux(struct anx7411_data *ctx)
if (ctx->typec.typec_mux) { if (ctx->typec.typec_mux) {
typec_mux_unregister(ctx->typec.typec_mux); typec_mux_unregister(ctx->typec.typec_mux);
ctx->typec.typec_mux = NULL; ctx->typec.typec_mux = NULL;
fwnode_handle_put(ctx->mux_node);
} }
} }
@@ -1096,6 +1109,7 @@ static void anx7411_unregister_switch(struct anx7411_data *ctx)
if (ctx->typec.typec_switch) { if (ctx->typec.typec_switch) {
typec_switch_unregister(ctx->typec.typec_switch); typec_switch_unregister(ctx->typec.typec_switch);
ctx->typec.typec_switch = NULL; ctx->typec.typec_switch = NULL;
fwnode_handle_put(ctx->switch_node);
} }
} }
@@ -1103,28 +1117,29 @@ static int anx7411_typec_switch_probe(struct anx7411_data *ctx,
struct device *dev) struct device *dev)
{ {
int ret; int ret;
struct device_node *node;
node = of_get_child_by_name(dev->of_node, "orientation_switch"); ctx->switch_node = device_get_named_child_node(dev, "orientation_switch");
if (!node) if (!ctx->switch_node)
return 0; return 0;
ret = anx7411_register_switch(ctx, dev, &node->fwnode); ret = anx7411_register_switch(ctx, dev, ctx->switch_node);
if (ret) { if (ret) {
dev_err(dev, "failed register switch"); dev_err(dev, "failed register switch");
fwnode_handle_put(ctx->switch_node);
return ret; return ret;
} }
node = of_get_child_by_name(dev->of_node, "mode_switch"); ctx->mux_node = device_get_named_child_node(dev, "mode_switch");
if (!node) { if (!ctx->mux_node) {
dev_err(dev, "no typec mux exist"); dev_err(dev, "no typec mux exist");
ret = -ENODEV; ret = -ENODEV;
goto unregister_switch; goto unregister_switch;
} }
ret = anx7411_register_mux(ctx, dev, &node->fwnode); ret = anx7411_register_mux(ctx, dev, ctx->mux_node);
if (ret) { if (ret) {
dev_err(dev, "failed register mode switch"); dev_err(dev, "failed register mode switch");
fwnode_handle_put(ctx->mux_node);
ret = -ENODEV; ret = -ENODEV;
goto unregister_switch; goto unregister_switch;
} }
@@ -1153,34 +1168,34 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
ret = fwnode_property_read_string(fwnode, "power-role", &buf); ret = fwnode_property_read_string(fwnode, "power-role", &buf);
if (ret) { if (ret) {
dev_err(dev, "power-role not found: %d\n", ret); dev_err(dev, "power-role not found: %d\n", ret);
return ret; goto put_fwnode;
} }
ret = typec_find_port_power_role(buf); ret = typec_find_port_power_role(buf);
if (ret < 0) if (ret < 0)
return ret; goto put_fwnode;
cap->type = ret; cap->type = ret;
ret = fwnode_property_read_string(fwnode, "data-role", &buf); ret = fwnode_property_read_string(fwnode, "data-role", &buf);
if (ret) { if (ret) {
dev_err(dev, "data-role not found: %d\n", ret); dev_err(dev, "data-role not found: %d\n", ret);
return ret; goto put_fwnode;
} }
ret = typec_find_port_data_role(buf); ret = typec_find_port_data_role(buf);
if (ret < 0) if (ret < 0)
return ret; goto put_fwnode;
cap->data = ret; cap->data = ret;
ret = fwnode_property_read_string(fwnode, "try-power-role", &buf); ret = fwnode_property_read_string(fwnode, "try-power-role", &buf);
if (ret) { if (ret) {
dev_err(dev, "try-power-role not found: %d\n", ret); dev_err(dev, "try-power-role not found: %d\n", ret);
return ret; goto put_fwnode;
} }
ret = typec_find_power_role(buf); ret = typec_find_power_role(buf);
if (ret < 0) if (ret < 0)
return ret; goto put_fwnode;
cap->prefer_role = ret; cap->prefer_role = ret;
/* Get source pdos */ /* Get source pdos */
@@ -1192,7 +1207,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
typecp->src_pdo_nr); typecp->src_pdo_nr);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "source cap validate failed: %d\n", ret); dev_err(dev, "source cap validate failed: %d\n", ret);
return -EINVAL; goto put_fwnode;
} }
typecp->caps_flags |= HAS_SOURCE_CAP; typecp->caps_flags |= HAS_SOURCE_CAP;
@@ -1206,7 +1221,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
typecp->sink_pdo_nr); typecp->sink_pdo_nr);
if (ret < 0) { if (ret < 0) {
dev_err(dev, "sink cap validate failed: %d\n", ret); dev_err(dev, "sink cap validate failed: %d\n", ret);
return -EINVAL; goto put_fwnode;
} }
for (i = 0; i < typecp->sink_pdo_nr; i++) { for (i = 0; i < typecp->sink_pdo_nr; i++) {
@@ -1250,13 +1265,21 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
ret = PTR_ERR(ctx->typec.port); ret = PTR_ERR(ctx->typec.port);
ctx->typec.port = NULL; ctx->typec.port = NULL;
dev_err(dev, "Failed to register type c port %d\n", ret); dev_err(dev, "Failed to register type c port %d\n", ret);
return ret; goto put_usb_role_switch;
} }
typec_port_register_altmodes(ctx->typec.port, NULL, ctx, typec_port_register_altmodes(ctx->typec.port, NULL, ctx,
ctx->typec.port_amode, ctx->typec.port_amode,
MAX_ALTMODE); MAX_ALTMODE);
return 0; return 0;
put_usb_role_switch:
if (ctx->typec.role_sw)
usb_role_switch_put(ctx->typec.role_sw);
put_fwnode:
fwnode_handle_put(fwnode);
return ret;
} }
static int anx7411_typec_check_connection(struct anx7411_data *ctx) static int anx7411_typec_check_connection(struct anx7411_data *ctx)
@@ -1528,8 +1551,7 @@ free_wq:
destroy_workqueue(plat->workqueue); destroy_workqueue(plat->workqueue);
free_typec_port: free_typec_port:
typec_unregister_port(plat->typec.port); anx7411_port_unregister(&plat->typec);
anx7411_port_unregister_altmodes(plat->typec.port_amode);
free_typec_switch: free_typec_switch:
anx7411_unregister_switch(plat); anx7411_unregister_switch(plat);
@@ -1554,17 +1576,11 @@ static void anx7411_i2c_remove(struct i2c_client *client)
if (plat->spi_client) if (plat->spi_client)
i2c_unregister_device(plat->spi_client); i2c_unregister_device(plat->spi_client);
if (plat->typec.role_sw)
usb_role_switch_put(plat->typec.role_sw);
anx7411_unregister_mux(plat); anx7411_unregister_mux(plat);
anx7411_unregister_switch(plat); anx7411_unregister_switch(plat);
if (plat->typec.port) anx7411_port_unregister(&plat->typec);
typec_unregister_port(plat->typec.port);
anx7411_port_unregister_altmodes(plat->typec.port_amode);
} }
static const struct i2c_device_id anx7411_id[] = { static const struct i2c_device_id anx7411_id[] = {

View File

@@ -613,6 +613,10 @@ int exfat_free_dentry_set(struct exfat_entry_set_cache *es, int sync)
bforget(es->bh[i]); bforget(es->bh[i]);
else else
brelse(es->bh[i]); brelse(es->bh[i]);
if (IS_DYNAMIC_ES(es))
kfree(es->bh);
kfree(es); kfree(es);
return err; return err;
} }
@@ -845,6 +849,7 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
/* byte offset in sector */ /* byte offset in sector */
off = EXFAT_BLK_OFFSET(byte_offset, sb); off = EXFAT_BLK_OFFSET(byte_offset, sb);
es->start_off = off; es->start_off = off;
es->bh = es->__bh;
/* sector offset in cluster */ /* sector offset in cluster */
sec = EXFAT_B_TO_BLK(byte_offset, sb); sec = EXFAT_B_TO_BLK(byte_offset, sb);
@@ -864,6 +869,16 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
es->num_entries = num_entries; es->num_entries = num_entries;
num_bh = EXFAT_B_TO_BLK_ROUND_UP(off + num_entries * DENTRY_SIZE, sb); num_bh = EXFAT_B_TO_BLK_ROUND_UP(off + num_entries * DENTRY_SIZE, sb);
if (num_bh > ARRAY_SIZE(es->__bh)) {
es->bh = kmalloc_array(num_bh, sizeof(*es->bh), GFP_NOFS);
if (!es->bh) {
brelse(bh);
kfree(es);
return NULL;
}
es->bh[0] = bh;
}
for (i = 1; i < num_bh; i++) { for (i = 1; i < num_bh; i++) {
/* get the next sector */ /* get the next sector */
if (exfat_is_last_sector_in_cluster(sbi, sec)) { if (exfat_is_last_sector_in_cluster(sbi, sec)) {

View File

@@ -169,10 +169,13 @@ struct exfat_entry_set_cache {
bool modified; bool modified;
unsigned int start_off; unsigned int start_off;
int num_bh; int num_bh;
struct buffer_head *bh[DIR_CACHE_SIZE]; struct buffer_head *__bh[DIR_CACHE_SIZE];
struct buffer_head **bh;
unsigned int num_entries; unsigned int num_entries;
}; };
#define IS_DYNAMIC_ES(es) ((es)->__bh != (es)->bh)
struct exfat_dir_entry { struct exfat_dir_entry {
struct exfat_chain dir; struct exfat_chain dir;
int entry; int entry;

View File

@@ -259,7 +259,13 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry_safe(ses, nses, &pserver->smb_ses_list, smb_ses_list) { list_for_each_entry_safe(ses, nses, &pserver->smb_ses_list, smb_ses_list) {
/* check if iface is still active */ spin_lock(&ses->ses_lock);
if (ses->ses_status == SES_EXITING) {
spin_unlock(&ses->ses_lock);
continue;
}
spin_unlock(&ses->ses_lock);
spin_lock(&ses->chan_lock); spin_lock(&ses->chan_lock);
if (!cifs_chan_is_iface_active(ses, server)) { if (!cifs_chan_is_iface_active(ses, server)) {
spin_unlock(&ses->chan_lock); spin_unlock(&ses->chan_lock);
@@ -1977,31 +1983,6 @@ out:
return rc; return rc;
} }
/**
* cifs_free_ipc - helper to release the session IPC tcon
* @ses: smb session to unmount the IPC from
*
* Needs to be called everytime a session is destroyed.
*
* On session close, the IPC is closed and the server must release all tcons of the session.
* No need to send a tree disconnect here.
*
* Besides, it will make the server to not close durable and resilient files on session close, as
* specified in MS-SMB2 3.3.5.6 Receiving an SMB2 LOGOFF Request.
*/
static int
cifs_free_ipc(struct cifs_ses *ses)
{
struct cifs_tcon *tcon = ses->tcon_ipc;
if (tcon == NULL)
return 0;
tconInfoFree(tcon);
ses->tcon_ipc = NULL;
return 0;
}
static struct cifs_ses * static struct cifs_ses *
cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
{ {
@@ -2035,35 +2016,44 @@ void cifs_put_smb_ses(struct cifs_ses *ses)
{ {
unsigned int rc, xid; unsigned int rc, xid;
unsigned int chan_count; unsigned int chan_count;
bool do_logoff;
struct cifs_tcon *tcon;
struct TCP_Server_Info *server = ses->server; struct TCP_Server_Info *server = ses->server;
spin_lock(&ses->ses_lock);
if (ses->ses_status == SES_EXITING) {
spin_unlock(&ses->ses_lock);
return;
}
spin_unlock(&ses->ses_lock);
cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
cifs_dbg(FYI,
"%s: ses ipc: %s\n", __func__, ses->tcon_ipc ? ses->tcon_ipc->tree_name : "NONE");
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
if (--ses->ses_count > 0) { spin_lock(&ses->ses_lock);
cifs_dbg(FYI, "%s: id=0x%llx ses_count=%d ses_status=%u ipc=%s\n",
__func__, ses->Suid, ses->ses_count, ses->ses_status,
ses->tcon_ipc ? ses->tcon_ipc->tree_name : "none");
if (ses->ses_status == SES_EXITING || --ses->ses_count > 0) {
spin_unlock(&ses->ses_lock);
spin_unlock(&cifs_tcp_ses_lock); spin_unlock(&cifs_tcp_ses_lock);
return; return;
} }
spin_unlock(&cifs_tcp_ses_lock);
/* ses_count can never go negative */ /* ses_count can never go negative */
WARN_ON(ses->ses_count < 0); WARN_ON(ses->ses_count < 0);
if (ses->ses_status == SES_GOOD) spin_lock(&ses->chan_lock);
ses->ses_status = SES_EXITING; cifs_chan_clear_need_reconnect(ses, server);
spin_unlock(&ses->chan_lock);
cifs_free_ipc(ses); do_logoff = ses->ses_status == SES_GOOD && server->ops->logoff;
ses->ses_status = SES_EXITING;
tcon = ses->tcon_ipc;
ses->tcon_ipc = NULL;
spin_unlock(&ses->ses_lock);
spin_unlock(&cifs_tcp_ses_lock);
if (ses->ses_status == SES_EXITING && server->ops->logoff) { /*
* On session close, the IPC is closed and the server must release all
* tcons of the session. No need to send a tree disconnect here.
*
* Besides, it will make the server to not close durable and resilient
* files on session close, as specified in MS-SMB2 3.3.5.6 Receiving an
* SMB2 LOGOFF Request.
*/
tconInfoFree(tcon);
if (do_logoff) {
xid = get_xid(); xid = get_xid();
rc = server->ops->logoff(xid, ses); rc = server->ops->logoff(xid, ses);
if (rc) if (rc)

View File

@@ -1010,6 +1010,8 @@ static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
ses_enc_key = enc ? sess->smb3encryptionkey : ses_enc_key = enc ? sess->smb3encryptionkey :
sess->smb3decryptionkey; sess->smb3decryptionkey;
if (enc)
ksmbd_user_session_get(sess);
memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE); memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
return 0; return 0;

View File

@@ -262,8 +262,10 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
down_read(&conn->session_lock); down_read(&conn->session_lock);
sess = xa_load(&conn->sessions, id); sess = xa_load(&conn->sessions, id);
if (sess) if (sess) {
sess->last_active = jiffies; sess->last_active = jiffies;
ksmbd_user_session_get(sess);
}
up_read(&conn->session_lock); up_read(&conn->session_lock);
return sess; return sess;
} }
@@ -274,6 +276,8 @@ struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
down_read(&sessions_table_lock); down_read(&sessions_table_lock);
sess = __session_lookup(id); sess = __session_lookup(id);
if (sess)
ksmbd_user_session_get(sess);
up_read(&sessions_table_lock); up_read(&sessions_table_lock);
return sess; return sess;

View File

@@ -241,14 +241,14 @@ send:
if (work->tcon) if (work->tcon)
ksmbd_tree_connect_put(work->tcon); ksmbd_tree_connect_put(work->tcon);
smb3_preauth_hash_rsp(work); smb3_preauth_hash_rsp(work);
if (work->sess)
ksmbd_user_session_put(work->sess);
if (work->sess && work->sess->enc && work->encrypted && if (work->sess && work->sess->enc && work->encrypted &&
conn->ops->encrypt_resp) { conn->ops->encrypt_resp) {
rc = conn->ops->encrypt_resp(work); rc = conn->ops->encrypt_resp(work);
if (rc < 0) if (rc < 0)
conn->ops->set_rsp_status(work, STATUS_DATA_ERROR); conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
} }
if (work->sess)
ksmbd_user_session_put(work->sess);
ksmbd_conn_write(work); ksmbd_conn_write(work);
} }

View File

@@ -66,8 +66,10 @@ static inline bool check_session_id(struct ksmbd_conn *conn, u64 id)
return false; return false;
sess = ksmbd_session_lookup_all(conn, id); sess = ksmbd_session_lookup_all(conn, id);
if (sess) if (sess) {
ksmbd_user_session_put(sess);
return true; return true;
}
pr_err("Invalid user session id: %llu\n", id); pr_err("Invalid user session id: %llu\n", id);
return false; return false;
} }
@@ -604,10 +606,8 @@ int smb2_check_user_session(struct ksmbd_work *work)
/* Check for validity of user session */ /* Check for validity of user session */
work->sess = ksmbd_session_lookup_all(conn, sess_id); work->sess = ksmbd_session_lookup_all(conn, sess_id);
if (work->sess) { if (work->sess)
ksmbd_user_session_get(work->sess);
return 1; return 1;
}
ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id); ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
return -ENOENT; return -ENOENT;
} }
@@ -1720,29 +1720,35 @@ int smb2_sess_setup(struct ksmbd_work *work)
if (conn->dialect != sess->dialect) { if (conn->dialect != sess->dialect) {
rc = -EINVAL; rc = -EINVAL;
ksmbd_user_session_put(sess);
goto out_err; goto out_err;
} }
if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) { if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
rc = -EINVAL; rc = -EINVAL;
ksmbd_user_session_put(sess);
goto out_err; goto out_err;
} }
if (strncmp(conn->ClientGUID, sess->ClientGUID, if (strncmp(conn->ClientGUID, sess->ClientGUID,
SMB2_CLIENT_GUID_SIZE)) { SMB2_CLIENT_GUID_SIZE)) {
rc = -ENOENT; rc = -ENOENT;
ksmbd_user_session_put(sess);
goto out_err; goto out_err;
} }
if (sess->state == SMB2_SESSION_IN_PROGRESS) { if (sess->state == SMB2_SESSION_IN_PROGRESS) {
rc = -EACCES; rc = -EACCES;
ksmbd_user_session_put(sess);
goto out_err; goto out_err;
} }
if (sess->state == SMB2_SESSION_EXPIRED) { if (sess->state == SMB2_SESSION_EXPIRED) {
rc = -EFAULT; rc = -EFAULT;
ksmbd_user_session_put(sess);
goto out_err; goto out_err;
} }
ksmbd_user_session_put(sess);
if (ksmbd_conn_need_reconnect(conn)) { if (ksmbd_conn_need_reconnect(conn)) {
rc = -EFAULT; rc = -EFAULT;
@@ -1750,7 +1756,8 @@ int smb2_sess_setup(struct ksmbd_work *work)
goto out_err; goto out_err;
} }
if (ksmbd_session_lookup(conn, sess_id)) { sess = ksmbd_session_lookup(conn, sess_id);
if (!sess) {
rc = -EACCES; rc = -EACCES;
goto out_err; goto out_err;
} }
@@ -1761,7 +1768,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
} }
conn->binding = true; conn->binding = true;
ksmbd_user_session_get(sess);
} else if ((conn->dialect < SMB30_PROT_ID || } else if ((conn->dialect < SMB30_PROT_ID ||
server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) && server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) { (req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
@@ -1788,7 +1794,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
} }
conn->binding = false; conn->binding = false;
ksmbd_user_session_get(sess);
} }
work->sess = sess; work->sess = sess;
@@ -2207,9 +2212,9 @@ err_out:
int smb2_session_logoff(struct ksmbd_work *work) int smb2_session_logoff(struct ksmbd_work *work)
{ {
struct ksmbd_conn *conn = work->conn; struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
struct smb2_logoff_req *req; struct smb2_logoff_req *req;
struct smb2_logoff_rsp *rsp; struct smb2_logoff_rsp *rsp;
struct ksmbd_session *sess;
u64 sess_id; u64 sess_id;
int err; int err;
@@ -2231,11 +2236,6 @@ int smb2_session_logoff(struct ksmbd_work *work)
ksmbd_close_session_fds(work); ksmbd_close_session_fds(work);
ksmbd_conn_wait_idle(conn, sess_id); ksmbd_conn_wait_idle(conn, sess_id);
/*
* Re-lookup session to validate if session is deleted
* while waiting request complete
*/
sess = ksmbd_session_lookup_all(conn, sess_id);
if (ksmbd_tree_conn_session_logoff(sess)) { if (ksmbd_tree_conn_session_logoff(sess)) {
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId); ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED; rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
@@ -8682,6 +8682,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
le64_to_cpu(tr_hdr->SessionId)); le64_to_cpu(tr_hdr->SessionId));
return -ECONNABORTED; return -ECONNABORTED;
} }
ksmbd_user_session_put(sess);
iov[0].iov_base = buf; iov[0].iov_base = buf;
iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4; iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;

View File

@@ -3430,14 +3430,31 @@ xfs_btree_insrec(
xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS); xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS);
/* /*
* If we just inserted into a new tree block, we have to * Update btree keys to reflect the newly added record or keyptr.
* recalculate nkey here because nkey is out of date. * There are three cases here to be aware of. Normally, all we have to
* do is walk towards the root, updating keys as necessary.
* *
* Otherwise we're just updating an existing block (having shoved * If the caller had us target a full block for the insertion, we dealt
* some records into the new tree block), so use the regular key * with that by calling the _make_block_unfull function. If the
* update mechanism. * "make unfull" function splits the block, it'll hand us back the key
* and pointer of the new block. We haven't yet added the new block to
* the next level up, so if we decide to add the new record to the new
* block (bp->b_bn != old_bn), we have to update the caller's pointer
* so that the caller adds the new block with the correct key.
*
* However, there is a third possibility-- if the selected block is the
* root block of an inode-rooted btree and cannot be expanded further,
* the "make unfull" function moves the root block contents to a new
* block and updates the root block to point to the new block. In this
* case, no block pointer is passed back because the block has already
* been added to the btree. In this case, we need to use the regular
* key update function, just like the first case. This is critical for
* overlapping btrees, because the high key must be updated to reflect
* the entire tree, not just the subtree accessible through the first
* child of the root (which is now two levels down from the root).
*/ */
if (bp && xfs_buf_daddr(bp) != old_bn) { if (!xfs_btree_ptr_is_null(cur, &nptr) &&
bp && xfs_buf_daddr(bp) != old_bn) {
xfs_btree_get_keys(cur, block, lkey); xfs_btree_get_keys(cur, block, lkey);
} else if (xfs_btree_needs_key_update(cur, optr)) { } else if (xfs_btree_needs_key_update(cur, optr)) {
error = xfs_btree_update_keys(cur, level); error = xfs_btree_update_keys(cur, level);

View File

@@ -89,8 +89,10 @@ xfs_symlink_verify(
struct xfs_mount *mp = bp->b_mount; struct xfs_mount *mp = bp->b_mount;
struct xfs_dsymlink_hdr *dsl = bp->b_addr; struct xfs_dsymlink_hdr *dsl = bp->b_addr;
/* no verification of non-crc buffers */
if (!xfs_has_crc(mp)) if (!xfs_has_crc(mp))
return __this_address; return NULL;
if (!xfs_verify_magic(bp, dsl->sl_magic)) if (!xfs_verify_magic(bp, dsl->sl_magic))
return __this_address; return __this_address;
if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid)) if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid))

View File

@@ -464,7 +464,7 @@ TRACE_EVENT(xchk_ifork_btree_error,
TP_fast_assign( TP_fast_assign(
xfs_fsblock_t fsbno = xchk_btree_cur_fsbno(cur, level); xfs_fsblock_t fsbno = xchk_btree_cur_fsbno(cur, level);
__entry->dev = sc->mp->m_super->s_dev; __entry->dev = sc->mp->m_super->s_dev;
__entry->ino = sc->ip->i_ino; __entry->ino = cur->bc_ino.ip->i_ino;
__entry->whichfork = cur->bc_ino.whichfork; __entry->whichfork = cur->bc_ino.whichfork;
__entry->type = sc->sm->sm_type; __entry->type = sc->sm->sm_type;
__entry->btnum = cur->bc_btnum; __entry->btnum = cur->bc_btnum;

View File

@@ -1161,6 +1161,14 @@ out_unlock:
xfs_iunlock2_io_mmap(src, dest); xfs_iunlock2_io_mmap(src, dest);
if (ret) if (ret)
trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_); trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
/*
* If the caller did not set CAN_SHORTEN, then it is not prepared to
* handle partial results -- either the whole remap succeeds, or we
* must say why it did not. In this case, any error should be returned
* to the caller.
*/
if (ret && remapped < len && !(remap_flags & REMAP_FILE_CAN_SHORTEN))
return ret;
return remapped > 0 ? remapped : ret; return remapped > 0 ? remapped : ret;
} }

View File

@@ -955,13 +955,6 @@ __xfs_trans_commit(
trace_xfs_trans_commit(tp, _RET_IP_); trace_xfs_trans_commit(tp, _RET_IP_);
error = xfs_trans_run_precommits(tp);
if (error) {
if (tp->t_flags & XFS_TRANS_PERM_LOG_RES)
xfs_defer_cancel(tp);
goto out_unreserve;
}
/* /*
* Finish deferred items on final commit. Only permanent transactions * Finish deferred items on final commit. Only permanent transactions
* should ever have deferred ops. * should ever have deferred ops.
@@ -972,13 +965,12 @@ __xfs_trans_commit(
error = xfs_defer_finish_noroll(&tp); error = xfs_defer_finish_noroll(&tp);
if (error) if (error)
goto out_unreserve; goto out_unreserve;
/* Run precommits from final tx in defer chain. */
error = xfs_trans_run_precommits(tp);
if (error)
goto out_unreserve;
} }
error = xfs_trans_run_precommits(tp);
if (error)
goto out_unreserve;
/* /*
* If there is nothing to be logged by the transaction, * If there is nothing to be logged by the transaction,
* then unlock all of the items associated with the * then unlock all of the items associated with the

View File

@@ -205,18 +205,6 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
/*
* Force the compiler to emit 'sym' as a symbol, so that we can reference
* it from inline assembler. Necessary in case 'sym' could be inlined
* otherwise, or eliminated entirely due to lack of references that are
* visible to the compiler.
*/
#define ___ADDRESSABLE(sym, __attrs) \
static void * __used __attrs \
__UNIQUE_ID(__PASTE(__addressable_,sym)) = (void *)&sym;
#define __ADDRESSABLE(sym) \
___ADDRESSABLE(sym, __section(".discard.addressable"))
/** /**
* offset_to_ptr - convert a relative memory offset to an absolute pointer * offset_to_ptr - convert a relative memory offset to an absolute pointer
* @off: the address of the 32-bit offset value * @off: the address of the 32-bit offset value
@@ -228,6 +216,33 @@ static inline void *offset_to_ptr(const int *off)
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#ifdef CONFIG_64BIT
#define ARCH_SEL(a,b) a
#else
#define ARCH_SEL(a,b) b
#endif
/*
* Force the compiler to emit 'sym' as a symbol, so that we can reference
* it from inline assembler. Necessary in case 'sym' could be inlined
* otherwise, or eliminated entirely due to lack of references that are
* visible to the compiler.
*/
#define ___ADDRESSABLE(sym, __attrs) \
static void * __used __attrs \
__UNIQUE_ID(__PASTE(__addressable_,sym)) = (void *)&sym;
#define __ADDRESSABLE(sym) \
___ADDRESSABLE(sym, __section(".discard.addressable"))
#define __ADDRESSABLE_ASM(sym) \
.pushsection .discard.addressable,"aw"; \
.align ARCH_SEL(8,4); \
ARCH_SEL(.quad, .long) __stringify(sym); \
.popsection;
#define __ADDRESSABLE_ASM_STR(sym) __stringify(__ADDRESSABLE_ASM(sym))
/* &a[0] degrades to a pointer: a different type from an array */ /* &a[0] degrades to a pointer: a different type from an array */
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))

View File

@@ -15,6 +15,7 @@
struct ocelot_skb_cb { struct ocelot_skb_cb {
struct sk_buff *clone; struct sk_buff *clone;
unsigned int ptp_class; /* valid only for clones */ unsigned int ptp_class; /* valid only for clones */
unsigned long ptp_tx_time; /* valid only for clones */
u32 tstamp_lo; u32 tstamp_lo;
u8 ptp_cmd; u8 ptp_cmd;
u8 ts_id; u8 ts_id;

View File

@@ -14,6 +14,7 @@ struct timespec64;
struct clocksource; struct clocksource;
int kvm_arch_ptp_init(void); int kvm_arch_ptp_init(void);
void kvm_arch_ptp_exit(void);
int kvm_arch_ptp_get_clock(struct timespec64 *ts); int kvm_arch_ptp_get_clock(struct timespec64 *ts);
int kvm_arch_ptp_get_crosststamp(u64 *cycle, int kvm_arch_ptp_get_crosststamp(u64 *cycle,
struct timespec64 *tspec, struct clocksource **cs); struct timespec64 *tspec, struct clocksource **cs);

View File

@@ -160,6 +160,8 @@ extern void arch_static_call_transform(void *site, void *tramp, void *func, bool
#ifdef CONFIG_HAVE_STATIC_CALL_INLINE #ifdef CONFIG_HAVE_STATIC_CALL_INLINE
extern bool static_call_initialized;
extern int __init static_call_init(void); extern int __init static_call_init(void);
struct static_call_mod { struct static_call_mod {
@@ -223,6 +225,8 @@ extern long __static_call_return0(void);
#elif defined(CONFIG_HAVE_STATIC_CALL) #elif defined(CONFIG_HAVE_STATIC_CALL)
#define static_call_initialized 0
static inline int static_call_init(void) { return 0; } static inline int static_call_init(void) { return 0; }
#define DEFINE_STATIC_CALL(name, _func) \ #define DEFINE_STATIC_CALL(name, _func) \
@@ -279,6 +283,8 @@ extern long __static_call_return0(void);
#else /* Generic implementation */ #else /* Generic implementation */
#define static_call_initialized 0
static inline int static_call_init(void) { return 0; } static inline int static_call_init(void) { return 0; }
static inline long __static_call_return0(void) static inline long __static_call_return0(void)

View File

@@ -122,6 +122,7 @@ struct bt_voice {
#define BT_VOICE_TRANSPARENT 0x0003 #define BT_VOICE_TRANSPARENT 0x0003
#define BT_VOICE_CVSD_16BIT 0x0060 #define BT_VOICE_CVSD_16BIT 0x0060
#define BT_VOICE_TRANSPARENT_16BIT 0x0063
#define BT_SNDMTU 12 #define BT_SNDMTU 12
#define BT_RCVMTU 13 #define BT_RCVMTU 13

View File

@@ -4,7 +4,7 @@
#include <linux/lapb.h> #include <linux/lapb.h>
#include <linux/refcount.h> #include <linux/refcount.h>
#define LAPB_HEADER_LEN 20 /* LAPB over Ethernet + a bit more */ #define LAPB_HEADER_LEN MAX_HEADER /* LAPB over Ethernet + a bit more */
#define LAPB_ACK_PENDING_CONDITION 0x01 #define LAPB_ACK_PENDING_CONDITION 0x01
#define LAPB_REJECT_CONDITION 0x02 #define LAPB_REJECT_CONDITION 0x02

View File

@@ -81,6 +81,7 @@ struct net {
* or to unregister pernet ops * or to unregister pernet ops
* (pernet_ops_rwsem write locked). * (pernet_ops_rwsem write locked).
*/ */
struct llist_node defer_free_list;
struct llist_node cleanup_list; /* namespaces on death row */ struct llist_node cleanup_list; /* namespaces on death row */
#ifdef CONFIG_KEYS #ifdef CONFIG_KEYS

View File

@@ -941,7 +941,6 @@ struct ocelot_port {
phy_interface_t phy_mode; phy_interface_t phy_mode;
unsigned int ptp_skbs_in_flight;
struct sk_buff_head tx_skbs; struct sk_buff_head tx_skbs;
unsigned int trap_proto; unsigned int trap_proto;
@@ -949,7 +948,6 @@ struct ocelot_port {
u16 mrp_ring_id; u16 mrp_ring_id;
u8 ptp_cmd; u8 ptp_cmd;
u8 ts_id;
u8 index; u8 index;

View File

@@ -10364,8 +10364,11 @@ static void find_equal_scalars(struct bpf_verifier_state *vstate,
struct bpf_reg_state *reg; struct bpf_reg_state *reg;
bpf_for_each_reg_in_vstate(vstate, state, reg, ({ bpf_for_each_reg_in_vstate(vstate, state, reg, ({
if (reg->type == SCALAR_VALUE && reg->id == known_reg->id) if (reg->type == SCALAR_VALUE && reg->id == known_reg->id) {
s32 saved_subreg_def = reg->subreg_def;
copy_register_state(reg, known_reg); copy_register_state(reg, known_reg);
reg->subreg_def = saved_subreg_def;
}
})); }));
} }

View File

@@ -15,7 +15,7 @@ extern struct static_call_site __start_static_call_sites[],
extern struct static_call_tramp_key __start_static_call_tramp_key[], extern struct static_call_tramp_key __start_static_call_tramp_key[],
__stop_static_call_tramp_key[]; __stop_static_call_tramp_key[];
static bool static_call_initialized; bool static_call_initialized;
/* mutex to protect key modules/sites */ /* mutex to protect key modules/sites */
static DEFINE_MUTEX(static_call_mutex); static DEFINE_MUTEX(static_call_mutex);

View File

@@ -2178,6 +2178,9 @@ void perf_event_detach_bpf_prog(struct perf_event *event)
goto unlock; goto unlock;
old_array = bpf_event_rcu_dereference(event->tp_event->prog_array); old_array = bpf_event_rcu_dereference(event->tp_event->prog_array);
if (!old_array)
goto put;
ret = bpf_prog_array_copy(old_array, event->prog, NULL, 0, &new_array); ret = bpf_prog_array_copy(old_array, event->prog, NULL, 0, &new_array);
if (ret < 0) { if (ret < 0) {
bpf_prog_array_delete_safe(old_array, event->prog); bpf_prog_array_delete_safe(old_array, event->prog);
@@ -2186,6 +2189,14 @@ void perf_event_detach_bpf_prog(struct perf_event *event)
bpf_prog_array_free_sleepable(old_array); bpf_prog_array_free_sleepable(old_array);
} }
put:
/*
* It could be that the bpf_prog is not sleepable (and will be freed
* via normal RCU), but is called from a point that supports sleepable
* programs and uses tasks-trace-RCU.
*/
synchronize_rcu_tasks_trace();
bpf_prog_put(event->prog); bpf_prog_put(event->prog);
event->prog = NULL; event->prog = NULL;

View File

@@ -1816,7 +1816,7 @@ create_local_trace_kprobe(char *func, void *addr, unsigned long offs,
int ret; int ret;
char *event; char *event;
if (func) { if (func && !strchr(func, ':')) {
unsigned int count; unsigned int count;
count = number_of_same_symbols(func); count = number_of_same_symbols(func);

View File

@@ -990,16 +990,25 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
int tt_diff_len, tt_change_len = 0; int tt_diff_len, tt_change_len = 0;
int tt_diff_entries_num = 0; int tt_diff_entries_num = 0;
int tt_diff_entries_count = 0; int tt_diff_entries_count = 0;
bool drop_changes = false;
size_t tt_extra_len = 0;
u16 tvlv_len; u16 tvlv_len;
tt_diff_entries_num = atomic_read(&bat_priv->tt.local_changes); tt_diff_entries_num = atomic_read(&bat_priv->tt.local_changes);
tt_diff_len = batadv_tt_len(tt_diff_entries_num); tt_diff_len = batadv_tt_len(tt_diff_entries_num);
/* if we have too many changes for one packet don't send any /* if we have too many changes for one packet don't send any
* and wait for the tt table request which will be fragmented * and wait for the tt table request so we can reply with the full
* (fragmented) table.
*
* The local change history should still be cleaned up so the next
* TT round can start again with a clean state.
*/ */
if (tt_diff_len > bat_priv->soft_iface->mtu) if (tt_diff_len > bat_priv->soft_iface->mtu) {
tt_diff_len = 0; tt_diff_len = 0;
tt_diff_entries_num = 0;
drop_changes = true;
}
tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv, &tt_data, tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv, &tt_data,
&tt_change, &tt_diff_len); &tt_change, &tt_diff_len);
@@ -1008,7 +1017,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
tt_data->flags = BATADV_TT_OGM_DIFF; tt_data->flags = BATADV_TT_OGM_DIFF;
if (tt_diff_len == 0) if (!drop_changes && tt_diff_len == 0)
goto container_register; goto container_register;
spin_lock_bh(&bat_priv->tt.changes_list_lock); spin_lock_bh(&bat_priv->tt.changes_list_lock);
@@ -1027,6 +1036,9 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
} }
spin_unlock_bh(&bat_priv->tt.changes_list_lock); spin_unlock_bh(&bat_priv->tt.changes_list_lock);
tt_extra_len = batadv_tt_len(tt_diff_entries_num -
tt_diff_entries_count);
/* Keep the buffer for possible tt_request */ /* Keep the buffer for possible tt_request */
spin_lock_bh(&bat_priv->tt.last_changeset_lock); spin_lock_bh(&bat_priv->tt.last_changeset_lock);
kfree(bat_priv->tt.last_changeset); kfree(bat_priv->tt.last_changeset);
@@ -1035,6 +1047,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
tt_change_len = batadv_tt_len(tt_diff_entries_count); tt_change_len = batadv_tt_len(tt_diff_entries_count);
/* check whether this new OGM has no changes due to size problems */ /* check whether this new OGM has no changes due to size problems */
if (tt_diff_entries_count > 0) { if (tt_diff_entries_count > 0) {
tt_diff_len -= tt_extra_len;
/* if kmalloc() fails we will reply with the full table /* if kmalloc() fails we will reply with the full table
* instead of providing the diff * instead of providing the diff
*/ */
@@ -1047,6 +1060,8 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
} }
spin_unlock_bh(&bat_priv->tt.last_changeset_lock); spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
/* Remove extra packet space for OGM */
tvlv_len -= tt_extra_len;
container_register: container_register:
batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data, batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data,
tvlv_len); tvlv_len);
@@ -2747,14 +2762,16 @@ static bool batadv_tt_global_valid(const void *entry_ptr,
* *
* Fills the tvlv buff with the tt entries from the specified hash. If valid_cb * Fills the tvlv buff with the tt entries from the specified hash. If valid_cb
* is not provided then this becomes a no-op. * is not provided then this becomes a no-op.
*
* Return: Remaining unused length in tvlv_buff.
*/ */
static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv, static u16 batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
struct batadv_hashtable *hash, struct batadv_hashtable *hash,
void *tvlv_buff, u16 tt_len, void *tvlv_buff, u16 tt_len,
bool (*valid_cb)(const void *, bool (*valid_cb)(const void *,
const void *, const void *,
u8 *flags), u8 *flags),
void *cb_data) void *cb_data)
{ {
struct batadv_tt_common_entry *tt_common_entry; struct batadv_tt_common_entry *tt_common_entry;
struct batadv_tvlv_tt_change *tt_change; struct batadv_tvlv_tt_change *tt_change;
@@ -2768,7 +2785,7 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
tt_change = tvlv_buff; tt_change = tvlv_buff;
if (!valid_cb) if (!valid_cb)
return; return tt_len;
rcu_read_lock(); rcu_read_lock();
for (i = 0; i < hash->size; i++) { for (i = 0; i < hash->size; i++) {
@@ -2794,6 +2811,8 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
} }
} }
rcu_read_unlock(); rcu_read_unlock();
return batadv_tt_len(tt_tot - tt_num_entries);
} }
/** /**
@@ -3069,10 +3088,11 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
goto out; goto out;
/* fill the rest of the tvlv with the real TT entries */ /* fill the rest of the tvlv with the real TT entries */
batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.global_hash, tvlv_len -= batadv_tt_tvlv_generate(bat_priv,
tt_change, tt_len, bat_priv->tt.global_hash,
batadv_tt_global_valid, tt_change, tt_len,
req_dst_orig_node); batadv_tt_global_valid,
req_dst_orig_node);
} }
/* Don't send the response, if larger than fragmented packet. */ /* Don't send the response, if larger than fragmented packet. */
@@ -3196,9 +3216,11 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
goto out; goto out;
/* fill the rest of the tvlv with the real TT entries */ /* fill the rest of the tvlv with the real TT entries */
batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.local_hash, tvlv_len -= batadv_tt_tvlv_generate(bat_priv,
tt_change, tt_len, bat_priv->tt.local_hash,
batadv_tt_local_valid, NULL); tt_change, tt_len,
batadv_tt_local_valid,
NULL);
} }
tvlv_tt_data->flags = BATADV_TT_RESPONSE; tvlv_tt_data->flags = BATADV_TT_RESPONSE;

View File

@@ -964,7 +964,11 @@ static int iso_sock_accept(struct socket *sock, struct socket *newsock,
long timeo; long timeo;
int err = 0; int err = 0;
lock_sock(sk); /* Use explicit nested locking to avoid lockdep warnings generated
* because the parent socket and the child socket are locked on the
* same thread.
*/
lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
@@ -995,7 +999,7 @@ static int iso_sock_accept(struct socket *sock, struct socket *newsock,
release_sock(sk); release_sock(sk);
timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo); timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
lock_sock(sk); lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
} }
remove_wait_queue(sk_sleep(sk), &wait); remove_wait_queue(sk_sleep(sk), &wait);

View File

@@ -268,10 +268,13 @@ static int sco_connect(struct sock *sk)
else else
type = SCO_LINK; type = SCO_LINK;
if (sco_pi(sk)->setting == BT_VOICE_TRANSPARENT && switch (sco_pi(sk)->setting & SCO_AIRMODE_MASK) {
(!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev))) { case SCO_AIRMODE_TRANSP:
err = -EOPNOTSUPP; if (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev)) {
goto unlock; err = -EOPNOTSUPP;
goto unlock;
}
break;
} }
hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst, hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst,
@@ -888,13 +891,6 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
if (err) if (err)
break; break;
/* Explicitly check for these values */
if (voice.setting != BT_VOICE_TRANSPARENT &&
voice.setting != BT_VOICE_CVSD_16BIT) {
err = -EINVAL;
break;
}
sco_pi(sk)->setting = voice.setting; sco_pi(sk)->setting = voice.setting;
hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src,
BDADDR_BREDR); BDADDR_BREDR);
@@ -902,9 +898,14 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
err = -EBADFD; err = -EBADFD;
break; break;
} }
if (enhanced_sync_conn_capable(hdev) &&
voice.setting == BT_VOICE_TRANSPARENT) switch (sco_pi(sk)->setting & SCO_AIRMODE_MASK) {
sco_pi(sk)->codec.id = BT_CODEC_TRANSPARENT; case SCO_AIRMODE_TRANSP:
if (enhanced_sync_conn_capable(hdev))
sco_pi(sk)->codec.id = BT_CODEC_TRANSPARENT;
break;
}
hci_dev_put(hdev); hci_dev_put(hdev);
break; break;

View File

@@ -435,11 +435,28 @@ out_free:
goto out; goto out;
} }
static LLIST_HEAD(defer_free_list);
static void net_complete_free(void)
{
struct llist_node *kill_list;
struct net *net, *next;
/* Get the list of namespaces to free from last round. */
kill_list = llist_del_all(&defer_free_list);
llist_for_each_entry_safe(net, next, kill_list, defer_free_list)
kmem_cache_free(net_cachep, net);
}
static void net_free(struct net *net) static void net_free(struct net *net)
{ {
if (refcount_dec_and_test(&net->passive)) { if (refcount_dec_and_test(&net->passive)) {
kfree(rcu_access_pointer(net->gen)); kfree(rcu_access_pointer(net->gen));
kmem_cache_free(net_cachep, net);
/* Wait for an extra rcu_barrier() before final free. */
llist_add(&net->defer_free_list, &defer_free_list);
} }
} }
@@ -614,6 +631,8 @@ static void cleanup_net(struct work_struct *work)
*/ */
rcu_barrier(); rcu_barrier();
net_complete_free();
/* Finally it is safe to free my network namespace structure */ /* Finally it is safe to free my network namespace structure */
list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) { list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) {
list_del_init(&net->exit_list); list_del_init(&net->exit_list);

View File

@@ -158,6 +158,7 @@ static void sock_map_del_link(struct sock *sk,
verdict_stop = true; verdict_stop = true;
list_del(&link->list); list_del(&link->list);
sk_psock_free_link(link); sk_psock_free_link(link);
break;
} }
} }
spin_unlock_bh(&psock->link_lock); spin_unlock_bh(&psock->link_lock);

View File

@@ -825,8 +825,10 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
unsigned int size; unsigned int size;
if (mptcp_syn_options(sk, skb, &size, &opts->mptcp)) { if (mptcp_syn_options(sk, skb, &size, &opts->mptcp)) {
opts->options |= OPTION_MPTCP; if (remaining >= size) {
remaining -= size; opts->options |= OPTION_MPTCP;
remaining -= size;
}
} }
} }

View File

@@ -1683,7 +1683,6 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
struct sta_info *sta, bool new_link, struct sta_info *sta, bool new_link,
struct link_station_parameters *params) struct link_station_parameters *params)
{ {
int ret = 0;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_sub_if_data *sdata = sta->sdata;
u32 link_id = params->link_id < 0 ? 0 : params->link_id; u32 link_id = params->link_id < 0 ? 0 : params->link_id;
@@ -1725,6 +1724,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
} }
if (params->txpwr_set) { if (params->txpwr_set) {
int ret;
link_sta->pub->txpwr.type = params->txpwr.type; link_sta->pub->txpwr.type = params->txpwr.type;
if (params->txpwr.type == NL80211_TX_POWER_LIMITED) if (params->txpwr.type == NL80211_TX_POWER_LIMITED)
link_sta->pub->txpwr.power = params->txpwr.power; link_sta->pub->txpwr.power = params->txpwr.power;
@@ -1766,6 +1767,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
params->eht_capa_len, params->eht_capa_len,
link_sta); link_sta);
ieee80211_sta_init_nss(link_sta);
if (params->opmode_notif_used) { if (params->opmode_notif_used) {
/* returned value is only needed for rc update, but the /* returned value is only needed for rc update, but the
* rc isn't initialized here yet, so ignore it * rc isn't initialized here yet, so ignore it
@@ -1775,9 +1778,7 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
sband->band); sband->band);
} }
ieee80211_sta_init_nss(link_sta); return 0;
return ret;
} }
static int sta_apply_parameters(struct ieee80211_local *local, static int sta_apply_parameters(struct ieee80211_local *local,

View File

@@ -77,6 +77,8 @@ struct netem_sched_data {
struct sk_buff *t_head; struct sk_buff *t_head;
struct sk_buff *t_tail; struct sk_buff *t_tail;
u32 t_len;
/* optional qdisc for classful handling (NULL at netem init) */ /* optional qdisc for classful handling (NULL at netem init) */
struct Qdisc *qdisc; struct Qdisc *qdisc;
@@ -373,6 +375,7 @@ static void tfifo_reset(struct Qdisc *sch)
rtnl_kfree_skbs(q->t_head, q->t_tail); rtnl_kfree_skbs(q->t_head, q->t_tail);
q->t_head = NULL; q->t_head = NULL;
q->t_tail = NULL; q->t_tail = NULL;
q->t_len = 0;
} }
static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
@@ -402,6 +405,7 @@ static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
rb_link_node(&nskb->rbnode, parent, p); rb_link_node(&nskb->rbnode, parent, p);
rb_insert_color(&nskb->rbnode, &q->t_root); rb_insert_color(&nskb->rbnode, &q->t_root);
} }
q->t_len++;
sch->q.qlen++; sch->q.qlen++;
} }
@@ -508,7 +512,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
1<<prandom_u32_max(8); 1<<prandom_u32_max(8);
} }
if (unlikely(sch->q.qlen >= sch->limit)) { if (unlikely(q->t_len >= sch->limit)) {
/* re-link segs, so that qdisc_drop_all() frees them all */ /* re-link segs, so that qdisc_drop_all() frees them all */
skb->next = segs; skb->next = segs;
qdisc_drop_all(skb, sch, to_free); qdisc_drop_all(skb, sch, to_free);
@@ -692,8 +696,8 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
tfifo_dequeue: tfifo_dequeue:
skb = __qdisc_dequeue_head(&sch->q); skb = __qdisc_dequeue_head(&sch->q);
if (skb) { if (skb) {
qdisc_qstats_backlog_dec(sch, skb);
deliver: deliver:
qdisc_qstats_backlog_dec(sch, skb);
qdisc_bstats_update(sch, skb); qdisc_bstats_update(sch, skb);
return skb; return skb;
} }
@@ -709,8 +713,7 @@ deliver:
if (time_to_send <= now && q->slot.slot_next <= now) { if (time_to_send <= now && q->slot.slot_next <= now) {
netem_erase_head(q, skb); netem_erase_head(q, skb);
sch->q.qlen--; q->t_len--;
qdisc_qstats_backlog_dec(sch, skb);
skb->next = NULL; skb->next = NULL;
skb->prev = NULL; skb->prev = NULL;
/* skb->dev shares skb->rbnode area, /* skb->dev shares skb->rbnode area,
@@ -737,16 +740,21 @@ deliver:
if (net_xmit_drop_count(err)) if (net_xmit_drop_count(err))
qdisc_qstats_drop(sch); qdisc_qstats_drop(sch);
qdisc_tree_reduce_backlog(sch, 1, pkt_len); qdisc_tree_reduce_backlog(sch, 1, pkt_len);
sch->qstats.backlog -= pkt_len;
sch->q.qlen--;
} }
goto tfifo_dequeue; goto tfifo_dequeue;
} }
sch->q.qlen--;
goto deliver; goto deliver;
} }
if (q->qdisc) { if (q->qdisc) {
skb = q->qdisc->ops->dequeue(q->qdisc); skb = q->qdisc->ops->dequeue(q->qdisc);
if (skb) if (skb) {
sch->q.qlen--;
goto deliver; goto deliver;
}
} }
qdisc_watchdog_schedule_ns(&q->watchdog, qdisc_watchdog_schedule_ns(&q->watchdog,
@@ -756,8 +764,10 @@ deliver:
if (q->qdisc) { if (q->qdisc) {
skb = q->qdisc->ops->dequeue(q->qdisc); skb = q->qdisc->ops->dequeue(q->qdisc);
if (skb) if (skb) {
sch->q.qlen--;
goto deliver; goto deliver;
}
} }
return NULL; return NULL;
} }

View File

@@ -811,6 +811,7 @@ static void cleanup_bearer(struct work_struct *work)
{ {
struct udp_bearer *ub = container_of(work, struct udp_bearer, work); struct udp_bearer *ub = container_of(work, struct udp_bearer, work);
struct udp_replicast *rcast, *tmp; struct udp_replicast *rcast, *tmp;
struct tipc_net *tn;
list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) { list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) {
dst_cache_destroy(&rcast->dst_cache); dst_cache_destroy(&rcast->dst_cache);
@@ -818,10 +819,14 @@ static void cleanup_bearer(struct work_struct *work)
kfree_rcu(rcast, rcu); kfree_rcu(rcast, rcu);
} }
tn = tipc_net(sock_net(ub->ubsock->sk));
dst_cache_destroy(&ub->rcast.dst_cache); dst_cache_destroy(&ub->rcast.dst_cache);
udp_tunnel_sock_release(ub->ubsock); udp_tunnel_sock_release(ub->ubsock);
/* Note: could use a call_rcu() to avoid another synchronize_net() */
synchronize_net(); synchronize_net();
atomic_dec(&tipc_net(sock_net(ub->ubsock->sk))->wq_count); atomic_dec(&tn->wq_count);
kfree(ub); kfree(ub);
} }

View File

@@ -811,7 +811,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_MLO_LINKS] = [NL80211_ATTR_MLO_LINKS] =
NLA_POLICY_NESTED_ARRAY(nl80211_policy), NLA_POLICY_NESTED_ARRAY(nl80211_policy),
[NL80211_ATTR_MLO_LINK_ID] = [NL80211_ATTR_MLO_LINK_ID] =
NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS), NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS - 1),
[NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN), [NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
[NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG }, [NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
[NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT }, [NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },

View File

@@ -473,14 +473,19 @@ static int acp6x_probe(struct platform_device *pdev)
handle = ACPI_HANDLE(pdev->dev.parent); handle = ACPI_HANDLE(pdev->dev.parent);
ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status); ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status);
if (!ACPI_FAILURE(ret)) if (!ACPI_FAILURE(ret)) {
wov_en = dmic_status; wov_en = dmic_status;
if (!wov_en)
return -ENODEV;
} else {
/* Incase of ACPI method read failure then jump to check_dmi_entry */
goto check_dmi_entry;
}
if (is_dmic_enable && wov_en) if (is_dmic_enable)
platform_set_drvdata(pdev, &acp6x_card); platform_set_drvdata(pdev, &acp6x_card);
else
return 0;
check_dmi_entry:
/* check for any DMI overrides */ /* check for any DMI overrides */
dmi_id = dmi_first_match(yc_acp_quirk_table); dmi_id = dmi_first_match(yc_acp_quirk_table);
if (dmi_id) if (dmi_id)

View File

@@ -553,7 +553,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interface *intf) static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interface *intf)
{ {
struct usb_host_config *config = dev->actconfig; struct usb_host_config *config = dev->actconfig;
struct usb_device_descriptor new_device_descriptor; struct usb_device_descriptor *new_device_descriptor __free(kfree) = NULL;
int err; int err;
if (le16_to_cpu(get_cfg_desc(config)->wTotalLength) == EXTIGY_FIRMWARE_SIZE_OLD || if (le16_to_cpu(get_cfg_desc(config)->wTotalLength) == EXTIGY_FIRMWARE_SIZE_OLD ||
@@ -564,15 +564,19 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
0x10, 0x43, 0x0001, 0x000a, NULL, 0); 0x10, 0x43, 0x0001, 0x000a, NULL, 0);
if (err < 0) if (err < 0)
dev_dbg(&dev->dev, "error sending boot message: %d\n", err); dev_dbg(&dev->dev, "error sending boot message: %d\n", err);
new_device_descriptor = kmalloc(sizeof(*new_device_descriptor), GFP_KERNEL);
if (!new_device_descriptor)
return -ENOMEM;
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
&new_device_descriptor, sizeof(new_device_descriptor)); new_device_descriptor, sizeof(*new_device_descriptor));
if (err < 0) if (err < 0)
dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err); dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
if (new_device_descriptor.bNumConfigurations > dev->descriptor.bNumConfigurations) if (new_device_descriptor->bNumConfigurations > dev->descriptor.bNumConfigurations)
dev_dbg(&dev->dev, "error too large bNumConfigurations: %d\n", dev_dbg(&dev->dev, "error too large bNumConfigurations: %d\n",
new_device_descriptor.bNumConfigurations); new_device_descriptor->bNumConfigurations);
else else
memcpy(&dev->descriptor, &new_device_descriptor, sizeof(dev->descriptor)); memcpy(&dev->descriptor, new_device_descriptor, sizeof(dev->descriptor));
err = usb_reset_configuration(dev); err = usb_reset_configuration(dev);
if (err < 0) if (err < 0)
dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err); dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
@@ -904,7 +908,7 @@ static void mbox2_setup_48_24_magic(struct usb_device *dev)
static int snd_usb_mbox2_boot_quirk(struct usb_device *dev) static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
{ {
struct usb_host_config *config = dev->actconfig; struct usb_host_config *config = dev->actconfig;
struct usb_device_descriptor new_device_descriptor; struct usb_device_descriptor *new_device_descriptor __free(kfree) = NULL;
int err; int err;
u8 bootresponse[0x12]; u8 bootresponse[0x12];
int fwsize; int fwsize;
@@ -939,15 +943,19 @@ static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
dev_dbg(&dev->dev, "device initialised!\n"); dev_dbg(&dev->dev, "device initialised!\n");
new_device_descriptor = kmalloc(sizeof(*new_device_descriptor), GFP_KERNEL);
if (!new_device_descriptor)
return -ENOMEM;
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
&new_device_descriptor, sizeof(new_device_descriptor)); new_device_descriptor, sizeof(*new_device_descriptor));
if (err < 0) if (err < 0)
dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err); dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
if (new_device_descriptor.bNumConfigurations > dev->descriptor.bNumConfigurations) if (new_device_descriptor->bNumConfigurations > dev->descriptor.bNumConfigurations)
dev_dbg(&dev->dev, "error too large bNumConfigurations: %d\n", dev_dbg(&dev->dev, "error too large bNumConfigurations: %d\n",
new_device_descriptor.bNumConfigurations); new_device_descriptor->bNumConfigurations);
else else
memcpy(&dev->descriptor, &new_device_descriptor, sizeof(dev->descriptor)); memcpy(&dev->descriptor, new_device_descriptor, sizeof(dev->descriptor));
err = usb_reset_configuration(dev); err = usb_reset_configuration(dev);
if (err < 0) if (err < 0)
@@ -1261,7 +1269,7 @@ static void mbox3_setup_48_24_magic(struct usb_device *dev)
static int snd_usb_mbox3_boot_quirk(struct usb_device *dev) static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
{ {
struct usb_host_config *config = dev->actconfig; struct usb_host_config *config = dev->actconfig;
struct usb_device_descriptor new_device_descriptor; struct usb_device_descriptor *new_device_descriptor __free(kfree) = NULL;
int err; int err;
int descriptor_size; int descriptor_size;
@@ -1274,15 +1282,19 @@ static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
dev_dbg(&dev->dev, "device initialised!\n"); dev_dbg(&dev->dev, "device initialised!\n");
new_device_descriptor = kmalloc(sizeof(*new_device_descriptor), GFP_KERNEL);
if (!new_device_descriptor)
return -ENOMEM;
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
&new_device_descriptor, sizeof(new_device_descriptor)); new_device_descriptor, sizeof(*new_device_descriptor));
if (err < 0) if (err < 0)
dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err); dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
if (new_device_descriptor.bNumConfigurations > dev->descriptor.bNumConfigurations) if (new_device_descriptor->bNumConfigurations > dev->descriptor.bNumConfigurations)
dev_dbg(&dev->dev, "error too large bNumConfigurations: %d\n", dev_dbg(&dev->dev, "error too large bNumConfigurations: %d\n",
new_device_descriptor.bNumConfigurations); new_device_descriptor->bNumConfigurations);
else else
memcpy(&dev->descriptor, &new_device_descriptor, sizeof(dev->descriptor)); memcpy(&dev->descriptor, new_device_descriptor, sizeof(dev->descriptor));
err = usb_reset_configuration(dev); err = usb_reset_configuration(dev);
if (err < 0) if (err < 0)
@@ -2065,6 +2077,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384), QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
DEVICE_FLG(0x046d, 0x09a4, /* Logitech QuickCam E 3500 */ DEVICE_FLG(0x046d, 0x09a4, /* Logitech QuickCam E 3500 */
QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR), QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x0499, 0x1506, /* Yamaha THR5 */
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */ DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */
QUIRK_FLAG_GENERIC_IMPLICIT_FB), QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x0499, 0x3108, /* Yamaha YIT-W12TX */ DEVICE_FLG(0x0499, 0x3108, /* Yamaha YIT-W12TX */

View File

@@ -3521,10 +3521,13 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
break; break;
case INSN_CONTEXT_SWITCH: case INSN_CONTEXT_SWITCH:
if (func && (!next_insn || !next_insn->hint)) { if (func) {
WARN_FUNC("unsupported instruction in callable function", if (!next_insn || !next_insn->hint) {
sec, insn->offset); WARN_FUNC("unsupported instruction in callable function",
return 1; sec, insn->offset);
return 1;
}
break;
} }
return 0; return 0;

View File

@@ -22,20 +22,34 @@ SB_ITC=0
h1_create() h1_create()
{ {
simple_if_init $h1 192.0.1.1/24 simple_if_init $h1 192.0.1.1/24
tc qdisc add dev $h1 clsact
# Add egress filter on $h1 that will guarantee that the packet sent,
# will be the only packet being passed to the device.
tc filter add dev $h1 egress pref 2 handle 102 matchall action drop
} }
h1_destroy() h1_destroy()
{ {
tc filter del dev $h1 egress pref 2 handle 102 matchall action drop
tc qdisc del dev $h1 clsact
simple_if_fini $h1 192.0.1.1/24 simple_if_fini $h1 192.0.1.1/24
} }
h2_create() h2_create()
{ {
simple_if_init $h2 192.0.1.2/24 simple_if_init $h2 192.0.1.2/24
tc qdisc add dev $h2 clsact
# Add egress filter on $h2 that will guarantee that the packet sent,
# will be the only packet being passed to the device.
tc filter add dev $h2 egress pref 1 handle 101 matchall action drop
} }
h2_destroy() h2_destroy()
{ {
tc filter del dev $h2 egress pref 1 handle 101 matchall action drop
tc qdisc del dev $h2 clsact
simple_if_fini $h2 192.0.1.2/24 simple_if_fini $h2 192.0.1.2/24
} }
@@ -101,6 +115,11 @@ port_pool_test()
local exp_max_occ=$(devlink_cell_size_get) local exp_max_occ=$(devlink_cell_size_get)
local max_occ local max_occ
tc filter add dev $h1 egress protocol ip pref 1 handle 101 flower \
src_mac $h1mac dst_mac $h2mac \
src_ip 192.0.1.1 dst_ip 192.0.1.2 \
action pass
devlink sb occupancy clearmax $DEVLINK_DEV devlink sb occupancy clearmax $DEVLINK_DEV
$MZ $h1 -c 1 -p 10 -a $h1mac -b $h2mac -A 192.0.1.1 -B 192.0.1.2 \ $MZ $h1 -c 1 -p 10 -a $h1mac -b $h2mac -A 192.0.1.1 -B 192.0.1.2 \
@@ -108,11 +127,6 @@ port_pool_test()
devlink sb occupancy snapshot $DEVLINK_DEV devlink sb occupancy snapshot $DEVLINK_DEV
RET=0
max_occ=$(sb_occ_pool_check $dl_port1 $SB_POOL_ING $exp_max_occ)
check_err $? "Expected iPool($SB_POOL_ING) max occupancy to be $exp_max_occ, but got $max_occ"
log_test "physical port's($h1) ingress pool"
RET=0 RET=0
max_occ=$(sb_occ_pool_check $dl_port2 $SB_POOL_ING $exp_max_occ) max_occ=$(sb_occ_pool_check $dl_port2 $SB_POOL_ING $exp_max_occ)
check_err $? "Expected iPool($SB_POOL_ING) max occupancy to be $exp_max_occ, but got $max_occ" check_err $? "Expected iPool($SB_POOL_ING) max occupancy to be $exp_max_occ, but got $max_occ"
@@ -122,6 +136,11 @@ port_pool_test()
max_occ=$(sb_occ_pool_check $cpu_dl_port $SB_POOL_EGR_CPU $exp_max_occ) max_occ=$(sb_occ_pool_check $cpu_dl_port $SB_POOL_EGR_CPU $exp_max_occ)
check_err $? "Expected ePool($SB_POOL_EGR_CPU) max occupancy to be $exp_max_occ, but got $max_occ" check_err $? "Expected ePool($SB_POOL_EGR_CPU) max occupancy to be $exp_max_occ, but got $max_occ"
log_test "CPU port's egress pool" log_test "CPU port's egress pool"
tc filter del dev $h1 egress protocol ip pref 1 handle 101 flower \
src_mac $h1mac dst_mac $h2mac \
src_ip 192.0.1.1 dst_ip 192.0.1.2 \
action pass
} }
port_tc_ip_test() port_tc_ip_test()
@@ -129,6 +148,11 @@ port_tc_ip_test()
local exp_max_occ=$(devlink_cell_size_get) local exp_max_occ=$(devlink_cell_size_get)
local max_occ local max_occ
tc filter add dev $h1 egress protocol ip pref 1 handle 101 flower \
src_mac $h1mac dst_mac $h2mac \
src_ip 192.0.1.1 dst_ip 192.0.1.2 \
action pass
devlink sb occupancy clearmax $DEVLINK_DEV devlink sb occupancy clearmax $DEVLINK_DEV
$MZ $h1 -c 1 -p 10 -a $h1mac -b $h2mac -A 192.0.1.1 -B 192.0.1.2 \ $MZ $h1 -c 1 -p 10 -a $h1mac -b $h2mac -A 192.0.1.1 -B 192.0.1.2 \
@@ -136,11 +160,6 @@ port_tc_ip_test()
devlink sb occupancy snapshot $DEVLINK_DEV devlink sb occupancy snapshot $DEVLINK_DEV
RET=0
max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ)
check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ"
log_test "physical port's($h1) ingress TC - IP packet"
RET=0 RET=0
max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ) max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ)
check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ" check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ"
@@ -150,6 +169,11 @@ port_tc_ip_test()
max_occ=$(sb_occ_etc_check $cpu_dl_port $SB_ITC_CPU_IP $exp_max_occ) max_occ=$(sb_occ_etc_check $cpu_dl_port $SB_ITC_CPU_IP $exp_max_occ)
check_err $? "Expected egress TC($SB_ITC_CPU_IP) max occupancy to be $exp_max_occ, but got $max_occ" check_err $? "Expected egress TC($SB_ITC_CPU_IP) max occupancy to be $exp_max_occ, but got $max_occ"
log_test "CPU port's egress TC - IP packet" log_test "CPU port's egress TC - IP packet"
tc filter del dev $h1 egress protocol ip pref 1 handle 101 flower \
src_mac $h1mac dst_mac $h2mac \
src_ip 192.0.1.1 dst_ip 192.0.1.2 \
action pass
} }
port_tc_arp_test() port_tc_arp_test()
@@ -157,17 +181,15 @@ port_tc_arp_test()
local exp_max_occ=$(devlink_cell_size_get) local exp_max_occ=$(devlink_cell_size_get)
local max_occ local max_occ
tc filter add dev $h1 egress protocol arp pref 1 handle 101 flower \
src_mac $h1mac action pass
devlink sb occupancy clearmax $DEVLINK_DEV devlink sb occupancy clearmax $DEVLINK_DEV
$MZ $h1 -c 1 -p 10 -a $h1mac -A 192.0.1.1 -t arp -q $MZ $h1 -c 1 -p 10 -a $h1mac -A 192.0.1.1 -t arp -q
devlink sb occupancy snapshot $DEVLINK_DEV devlink sb occupancy snapshot $DEVLINK_DEV
RET=0
max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ)
check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ"
log_test "physical port's($h1) ingress TC - ARP packet"
RET=0 RET=0
max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ) max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ)
check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ" check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ"
@@ -177,6 +199,9 @@ port_tc_arp_test()
max_occ=$(sb_occ_etc_check $cpu_dl_port $SB_ITC_CPU_ARP $exp_max_occ) max_occ=$(sb_occ_etc_check $cpu_dl_port $SB_ITC_CPU_ARP $exp_max_occ)
check_err $? "Expected egress TC($SB_ITC_IP2ME) max occupancy to be $exp_max_occ, but got $max_occ" check_err $? "Expected egress TC($SB_ITC_IP2ME) max occupancy to be $exp_max_occ, but got $max_occ"
log_test "CPU port's egress TC - ARP packet" log_test "CPU port's egress TC - ARP packet"
tc filter del dev $h1 egress protocol arp pref 1 handle 101 flower \
src_mac $h1mac action pass
} }
setup_prepare() setup_prepare()