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);`
- 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);`
- submit a request to execute the subsystem-level idle callback for the

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
PATCHLEVEL = 1
SUBLEVEL = 120
SUBLEVEL = 121
EXTRAVERSION =
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);
}
void init_cpu_devs(void);
void get_cpu_vendor(struct cpuinfo_x86 *c);
extern void early_cpu_init(void);
extern void identify_boot_cpu(void);
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 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 */

View File

@@ -8,7 +8,7 @@
#include <asm/special_insns.h>
#ifdef CONFIG_X86_32
static inline void iret_to_self(void)
static __always_inline void iret_to_self(void)
{
asm volatile (
"pushfl\n\t"
@@ -19,7 +19,7 @@ static inline void iret_to_self(void)
: ASM_CALL_CONSTRAINT : : "memory");
}
#else
static inline void iret_to_self(void)
static __always_inline void iret_to_self(void)
{
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
* 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

View File

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

View File

@@ -906,7 +906,7 @@ void detect_ht(struct cpuinfo_x86 *c)
#endif
}
static void get_cpu_vendor(struct cpuinfo_x86 *c)
void get_cpu_vendor(struct cpuinfo_x86 *c)
{
char *v = c->x86_vendor_id;
int i;
@@ -1672,15 +1672,11 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
detect_nopl();
}
void __init early_cpu_init(void)
void __init init_cpu_devs(void)
{
const struct cpu_dev *const *cdev;
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++) {
const struct cpu_dev *cpudev = *cdev;
@@ -1688,20 +1684,30 @@ void __init early_cpu_init(void)
break;
cpu_devs[count] = cpudev;
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
{
unsigned int j;
for (j = 0; j < 2; j++) {
if (!cpudev->c_ident[j])
continue;
pr_info(" %s %s\n", cpudev->c_vendor,
cpudev->c_ident[j]);
}
for (i = 0; i < X86_VENDOR_NUM && cpu_devs[i]; i++) {
for (j = 0; j < 2; j++) {
if (!cpu_devs[i]->c_ident[j])
continue;
pr_info(" %s %s\n", cpu_devs[i]->c_vendor,
cpu_devs[i]->c_ident[j]);
}
#endif
}
#endif
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);
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
/*
* This is called by apply_returns() to fix up static call trampolines,

View File

@@ -5,6 +5,7 @@
#endif
#include <linux/console.h>
#include <linux/cpu.h>
#include <linux/instrumentation.h>
#include <linux/kexec.h>
#include <linux/slab.h>
#include <linux/panic_notifier.h>
@@ -25,7 +26,8 @@
#include "smp.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
@@ -72,6 +74,67 @@ EXPORT_SYMBOL(xen_start_flags);
*/
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)
{
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(). */
if (xen_pvh_domain())
pv_info.name = "Xen PVH";
else {
u64 pfn;
uint32_t msr;
else
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();
@@ -299,6 +292,10 @@ static uint32_t __init xen_platform_hvm(void)
if (xen_pv_domain())
return 0;
/* Set correct hypercall function. */
if (xen_domain)
xen_hypercall_setfunc();
if (xen_pvh_domain() && nopv) {
/* Guest booting via the Xen-PVH boot entry goes here */
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_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();
@@ -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));
local_irq_disable();
early_boot_irqs_disabled = true;
xen_raw_console_write("mapping kernel into physical memory\n");
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)
{
u32 msr;
u64 pfn;
xen_pvh = 1;
xen_domain_type = XEN_HVM_DOMAIN;
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())
x86_init.oem.arch_setup = xen_add_preferred_consoles;
x86_init.oem.banner = xen_banner;

View File

@@ -20,9 +20,32 @@
#include <linux/init.h>
#include <linux/linkage.h>
#include <linux/objtool.h>
#include <../entry/calling.h>
.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
* non-zero.
@@ -176,7 +199,6 @@ SYM_CODE_START(xen_early_idt_handler_array)
SYM_CODE_END(xen_early_idt_handler_array)
__FINIT
hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
/*
* Xen64 iret frame:
*
@@ -186,17 +208,28 @@ hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
* cs
* rip <-- standard iret frame
*
* flags
* flags <-- xen_iret must push from here on
*
* rcx }
* r11 }<-- pushed by hypercall page
* rsp->rax }
* rcx
* r11
* 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)
UNWIND_HINT_EMPTY
ANNOTATE_NOENDBR
pushq $0
jmp hypercall_iret
xen_hypercall_iret
SYM_CODE_END(xen_iret)
/*
@@ -301,8 +334,7 @@ SYM_CODE_START(xen_entry_SYSENTER_compat)
ENDBR
lea 16(%rsp), %rsp /* strip %rcx, %r11 */
mov $-ENOSYS, %rax
pushq $0
jmp hypercall_iret
xen_hypercall_iret
SYM_CODE_END(xen_entry_SYSENTER_compat)
SYM_CODE_END(xen_entry_SYSCALL_compat)

View File

@@ -6,9 +6,11 @@
#include <linux/elfnote.h>
#include <linux/init.h>
#include <linux/instrumentation.h>
#include <asm/boot.h>
#include <asm/asm.h>
#include <asm/frame.h>
#include <asm/msr.h>
#include <asm/page_types.h>
#include <asm/percpu.h>
@@ -20,28 +22,6 @@
#include <xen/interface/xen-mca.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
__INIT
SYM_CODE_START(startup_xen)
@@ -80,6 +60,87 @@ SYM_CODE_END(asm_cpu_bringup_and_idle)
#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_VERSION, .asciz "2.6")
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
ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, _ASM_PTR startup_xen)
#endif
ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page)
ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,
.ascii "!writable_page_tables|pae_pgdir_above_4gb")
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) {}
#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 */

View File

@@ -1110,10 +1110,14 @@ void blkcg_unpin_online(struct cgroup_subsys_state *blkcg_css)
struct blkcg *blkcg = css_to_blkcg(blkcg_css);
do {
struct blkcg *parent;
if (!refcount_dec_and_test(&blkcg->online_pin))
break;
parent = blkcg_parent(blkcg);
blkcg_destroy_blkgs(blkcg);
blkcg = blkcg_parent(blkcg);
blkcg = parent;
} 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,
iocg->child_active_sum);
} 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;

View File

@@ -201,8 +201,6 @@ acpi_remove_address_space_handler(acpi_handle device,
/* Now we can delete the handler object */
acpi_os_release_mutex(handler_obj->address_space.
context_mutex);
acpi_ut_remove_reference(handler_obj);
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)
*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;
}
func = cmd_to_func(nfit_mem, cmd, call_pkg, &family);
if (func < 0)
return func;

View File

@@ -250,6 +250,9 @@ static bool acpi_decode_space(struct resource_win *win,
switch (addr->resource_type) {
case ACPI_MEMORY_RANGE:
acpi_dev_memresource_flags(res, len, wp);
if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
res->flags |= IORESOURCE_PREFETCH;
break;
case ACPI_IO_RANGE:
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)
res->flags |= IORESOURCE_WINDOW;
if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
res->flags |= IORESOURCE_PREFETCH;
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;
cphy_base[phy] = of_iomap(phy_nodes[phy], 0);
if (cphy_base[phy] == NULL) {
of_node_put(phy_data.np);
return 0;
}
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_ib *ib)
{
struct amdgpu_ring *ring = to_amdgpu_ring(job->base.sched);
struct amdgpu_ring *ring = amdgpu_job_ring(job);
unsigned i;
/* No patching necessary for the first instance */

View File

@@ -506,6 +506,6 @@ int __init i915_scheduler_module_init(void)
return 0;
err_priorities:
kmem_cache_destroy(slab_priorities);
kmem_cache_destroy(slab_dependencies);
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 | \
NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | \
NETIF_F_GSO_ENCAP_ALL | \
NETIF_F_HIGHDMA | NETIF_F_LRO)
#define BOND_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \

View File

@@ -22,7 +22,7 @@
#define VSC9959_NUM_PORTS 6
#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_MAX 383
#define VSC9959_SWITCH_PCI_BAR 4
@@ -1057,11 +1057,15 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
mdiobus_free(felix->imdio);
}
/* The switch considers any frame (regardless of size) as eligible for
* transmission if the traffic class gate is open for at least 33 ns.
/* The switch considers any frame (regardless of size) as eligible
* 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
* slot for which egress scheduling is blocked, but we need to still keep 33 ns
* available for one packet to be transmitted, otherwise the port tc will hang.
* slot for which egress scheduling is blocked, but we need to still keep
* 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
* 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
* useful gate interval length. Therefore, be careful
* 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);
/* 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,
int hz, int ticks);
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,
u32 start_index, bool sleep_ok);
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,
"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)
ether_addr_copy(adap->vfinfo[vf].vf_mac_addr, mac);
return ret;

View File

@@ -10215,11 +10215,12 @@ out:
* t4_set_vf_mac_acl - Set MAC address for the specified VF
* @adapter: The adapter
* @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
* @addr: the MAC address(es) to be set to the specified 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;
@@ -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.nmac = naddr;
switch (adapter->pf) {
switch (start) {
case 3:
memcpy(cmd.macaddr3, addr, sizeof(cmd.macaddr3));
break;

View File

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

View File

@@ -680,12 +680,11 @@ static int sparx5_start(struct sparx5 *sparx5)
err = -ENXIO;
if (sparx5->fdma_irq >= 0) {
if (GCB_CHIP_ID_REV_ID_GET(sparx5->chip_id) > 0)
err = devm_request_threaded_irq(sparx5->dev,
sparx5->fdma_irq,
NULL,
sparx5_fdma_handler,
IRQF_ONESHOT,
"sparx5-fdma", sparx5);
err = devm_request_irq(sparx5->dev,
sparx5->fdma_irq,
sparx5_fdma_handler,
0,
"sparx5-fdma", sparx5);
if (!err)
err = sparx5_fdma_start(sparx5);
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),
DEV10G_MAC_MAXLEN_CFG_MAX_LEN,
devinst,
DEV10G_MAC_ENA_CFG(0));
DEV10G_MAC_MAXLEN_CFG(0));
/* Handle Signal Detect in 10G PCS */
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 "ocelot.h"
#define OCELOT_PTP_TX_TSTAMP_TIMEOUT (5 * HZ)
int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
{
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;
}
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)
{
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)
{
struct ocelot_port *ocelot_port = ocelot->ports[port];
int ptp_cmd, old_ptp_cmd = ocelot_port->ptp_cmd;
bool l2 = false, l4 = false;
struct hwtstamp_config cfg;
bool old_l2, old_l4;
int err;
if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
return -EFAULT;
/* Tx type sanity check */
switch (cfg.tx_type) {
case HWTSTAMP_TX_ON:
ocelot_port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
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;
}
err = ocelot_ptp_tx_type_to_cmd(cfg.tx_type, &ptp_cmd);
if (err)
return err;
switch (cfg.rx_filter) {
case HWTSTAMP_FILTER_NONE:
@@ -569,13 +582,27 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
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);
if (err)
return err;
ocelot_port->ptp_cmd = ptp_cmd;
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);
@@ -607,34 +634,87 @@ int ocelot_get_ts_info(struct ocelot *ocelot, int port,
}
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 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 ||
ocelot->ptp_skbs_in_flight == OCELOT_PTP_FIFO_SIZE) {
spin_unlock_irqrestore(&ocelot->ts_id_lock, flags);
/* To get a better chance of acquiring a timestamp ID, first flush the
* stale packets still waiting in the TX timestamping queue. They are
* 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;
}
skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS;
/* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */
OCELOT_SKB_CB(clone)->ts_id = ocelot_port->ts_id;
n = find_first_zero_bit(ts_id_in_flight, OCELOT_MAX_PTP_ID);
if (n == OCELOT_MAX_PTP_ID) {
spin_unlock(&ocelot->ts_id_lock);
return -EBUSY;
}
ocelot_port->ts_id++;
if (ocelot_port->ts_id == OCELOT_MAX_PTP_ID)
ocelot_port->ts_id = 0;
ocelot_port->ptp_skbs_in_flight++;
/* Found an available timestamp ID, use it */
OCELOT_SKB_CB(clone)->ts_id = n;
OCELOT_SKB_CB(clone)->ptp_tx_time = jiffies;
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;
}
@@ -691,10 +771,14 @@ int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port,
if (!(*clone))
return -ENOMEM;
err = ocelot_port_add_txtstamp_skb(ocelot, port, *clone);
if (err)
/* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */
err = ocelot_port_queue_ptp_tx_skb(ocelot, port, *clone);
if (err) {
kfree_skb(*clone);
return err;
}
skb_shinfo(*clone)->tx_flags |= SKBTX_IN_PROGRESS;
OCELOT_SKB_CB(skb)->ptp_cmd = ptp_cmd;
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);
}
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)
{
int budget = OCELOT_PTP_QUEUE_SZ;
while (budget--) {
struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
struct skb_shared_hwtstamps shhwtstamps;
u32 val, id, seqid, txport;
struct ocelot_port *port;
struct sk_buff *skb_match;
struct timespec64 ts;
unsigned long flags;
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);
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 */
try_again:
spin_lock_irqsave(&port->tx_skbs.lock, flags);
skb_queue_walk_safe(&port->tx_skbs, skb, skb_tmp) {
if (OCELOT_SKB_CB(skb)->ts_id != id)
continue;
__skb_unlink(skb, &port->tx_skbs);
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;
skb_match = ocelot_port_dequeue_ptp_tx_skb(ocelot, txport, id,
seqid);
if (!skb_match) {
dev_warn_ratelimited(ocelot->dev,
"port %d received TX timestamp (seqid %d, ts id %u) for packet previously declared stale\n",
txport, seqid, id);
goto next_ts;
}
/* Get the h/w timestamp */
@@ -806,7 +855,7 @@ try_again:
shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
skb_complete_tx_timestamp(skb_match, &shhwtstamps);
/* Next ts */
next_ts:
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_MAX 1
static int qcaspi_pluggable = QCASPI_PLUGGABLE_MIN;
static int qcaspi_pluggable = QCASPI_PLUGGABLE_MAX;
module_param(qcaspi_pluggable, int, 0);
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->type = ARPHRD_ETHER;
qca->clkspeed = qcaspi_clkspeed;
qca->burst_len = qcaspi_burst_len;
qca->spi_thread = NULL;
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,
"qca,legacy-mode");
if (qcaspi_clkspeed == 0) {
if (spi->max_speed_hz)
qcaspi_clkspeed = spi->max_speed_hz;
else
qcaspi_clkspeed = QCASPI_CLK_SPEED;
}
if (qcaspi_clkspeed)
spi->max_speed_hz = qcaspi_clkspeed;
else if (!spi->max_speed_hz)
spi->max_speed_hz = QCASPI_CLK_SPEED;
if ((qcaspi_clkspeed < QCASPI_CLK_SPEED_MIN) ||
(qcaspi_clkspeed > QCASPI_CLK_SPEED_MAX)) {
dev_err(&spi->dev, "Invalid clkspeed: %d\n",
qcaspi_clkspeed);
if (spi->max_speed_hz < QCASPI_CLK_SPEED_MIN ||
spi->max_speed_hz > QCASPI_CLK_SPEED_MAX) {
dev_err(&spi->dev, "Invalid clkspeed: %u\n",
spi->max_speed_hz);
return -EINVAL;
}
@@ -953,14 +950,13 @@ qca_spi_probe(struct spi_device *spi)
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_clkspeed,
spi->max_speed_hz,
qcaspi_burst_len,
qcaspi_pluggable);
spi->mode = SPI_MODE_3;
spi->max_speed_hz = qcaspi_clkspeed;
if (spi_setup(spi) < 0) {
dev_err(&spi->dev, "Unable to setup SPI device\n");
return -EFAULT;

View File

@@ -101,7 +101,6 @@ struct qcaspi {
#endif
/* user configurable options */
u32 clkspeed;
u8 legacy_mode;
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 | \
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 | \
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)
{
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;
struct netfront_queue *queue;
netif_tx_stop_all_queues(np->netdev);
@@ -882,6 +882,9 @@ static void xennet_destroy_queues(struct netfront_info *info)
{
unsigned int i;
if (!info->queues)
return;
for (i = 0; i < info->netdev->real_num_tx_queues; i++) {
struct netfront_queue *queue = &info->queues[i];

View File

@@ -22,6 +22,10 @@ int kvm_arch_ptp_init(void)
return 0;
}
void kvm_arch_ptp_exit(void)
{
}
int kvm_arch_ptp_get_clock(struct timespec64 *ts)
{
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)
{
ptp_clock_unregister(kvm_ptp_clock.ptp_clock);
kvm_arch_ptp_exit();
}
static int __init ptp_kvm_init(void)

View File

@@ -14,27 +14,64 @@
#include <uapi/linux/kvm_para.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/ptp_kvm.h>
#include <linux/set_memory.h>
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)
{
struct page *p;
long ret;
if (!kvm_para_available())
return -ENODEV;
return -EOPNOTSUPP;
clock_pair_gpa = slow_virt_to_phys(&clock_pair);
if (!pvclock_get_pvti_cpu0_va())
return -ENODEV;
if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
p = alloc_page(GFP_KERNEL | __GFP_ZERO);
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,
KVM_CLOCK_PAIRING_WALLCLOCK);
if (ret == -KVM_ENOSYS)
return -ENODEV;
if (ret == -KVM_ENOSYS) {
ret = -EOPNOTSUPP;
goto err;
}
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)
@@ -49,8 +86,8 @@ int kvm_arch_ptp_get_clock(struct timespec64 *ts)
return -EOPNOTSUPP;
}
ts->tv_sec = clock_pair.sec;
ts->tv_nsec = clock_pair.nsec;
ts->tv_sec = clock_pair->sec;
ts->tv_nsec = clock_pair->nsec;
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);
return -EOPNOTSUPP;
}
tspec->tv_sec = clock_pair.sec;
tspec->tv_nsec = clock_pair.nsec;
*cycle = __pvclock_read_cycles(src, clock_pair.tsc);
tspec->tv_sec = clock_pair->sec;
tspec->tv_nsec = clock_pair->nsec;
*cycle = __pvclock_read_cycles(src, clock_pair->tsc);
} while (pvclock_read_retry(src, version));
*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);
if (ret < 0)
return ret;
goto stop_user;
if (op->dummy.buswidth && op->dummy.nbytes) {
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_read_from_ahb(buf, chip->ahb_base, len);
stop_user:
aspeed_spi_stop_user(chip);
return 0;
return ret;
}
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);
ret = aspeed_spi_send_cmd_addr(chip, op->addr.nbytes, op->addr.val, op->cmd.opcode);
if (ret < 0)
return ret;
goto stop_user;
aspeed_spi_write_to_ahb(chip->ahb_base, op->data.buf.out, op->data.nbytes);
stop_user:
aspeed_spi_stop_user(chip);
return 0;
return ret;
}
/* 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;
}
if (!hsotg->flags.b.port_connect_status) {
if (dwc2_is_device_mode(hsotg)) {
/*
* The port is disconnected, which means the core is
* either in device mode or it soon will be. Just
* return 0's for the remainder of the port status
* Just return 0's for the remainder of the port status
* since the port register can't be read if the core
* 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))
goto error;
if (!hsotg->flags.b.port_connect_status) {
if (dwc2_is_device_mode(hsotg)) {
/*
* The port is disconnected, which means the core is
* either in device mode or it soon will be. Just
* return without doing anything since the port
* register can't be written if the core is in device
* mode.
* Just return 0's for the remainder of the port status
* since the port register can't be read if the core
* is in device mode.
*/
break;
}
@@ -4349,7 +4345,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
if (hsotg->bus_suspended)
goto skip_power_saving;
if (hsotg->flags.b.port_connect_status == 0)
if (!(dwc2_read_hprt0(hsotg) & HPRT0_CONNSTS))
goto skip_power_saving;
switch (hsotg->params.power_down) {
@@ -4431,6 +4427,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
* Power Down mode.
*/
if (hprt0 & HPRT0_CONNSTS) {
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
hsotg->lx_state = DWC2_L0;
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.
* 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;
}
crst = devm_reset_control_get_exclusive(dev, "usb_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);
} else {
out:
gs_free_requests(ep, head, &port->read_allocated);
gs_free_requests(port->port_usb->in, &port->write_pool,
&port->write_allocated);
/* Free reqs only if we are still connected */
if (port->port_usb) {
gs_free_requests(ep, head, &port->read_allocated);
gs_free_requests(port->port_usb->in, &port->write_pool,
&port->write_allocated);
}
status = -EIO;
}

View File

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

View File

@@ -785,11 +785,17 @@ max3421_check_unlink(struct usb_hcd *hcd)
retval = 1;
dev_dbg(&spi->dev, "%s: URB %p unlinked=%d",
__func__, urb, urb->unlinked);
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);
if (urb == max3421_hcd->curr_urb) {
max3421_hcd->urb_done = 1;
max3421_hcd->hien &= ~(BIT(MAX3421_HI_HXFRDN_BIT) |
BIT(MAX3421_HI_RCVDAV_BIT));
} 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_desc psy_desc;
struct device *dev;
struct fwnode_handle *switch_node;
struct fwnode_handle *mux_node;
};
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,
struct typec_mux_state *state)
{
@@ -1088,6 +1100,7 @@ static void anx7411_unregister_mux(struct anx7411_data *ctx)
if (ctx->typec.typec_mux) {
typec_mux_unregister(ctx->typec.typec_mux);
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) {
typec_switch_unregister(ctx->typec.typec_switch);
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)
{
int ret;
struct device_node *node;
node = of_get_child_by_name(dev->of_node, "orientation_switch");
if (!node)
ctx->switch_node = device_get_named_child_node(dev, "orientation_switch");
if (!ctx->switch_node)
return 0;
ret = anx7411_register_switch(ctx, dev, &node->fwnode);
ret = anx7411_register_switch(ctx, dev, ctx->switch_node);
if (ret) {
dev_err(dev, "failed register switch");
fwnode_handle_put(ctx->switch_node);
return ret;
}
node = of_get_child_by_name(dev->of_node, "mode_switch");
if (!node) {
ctx->mux_node = device_get_named_child_node(dev, "mode_switch");
if (!ctx->mux_node) {
dev_err(dev, "no typec mux exist");
ret = -ENODEV;
goto unregister_switch;
}
ret = anx7411_register_mux(ctx, dev, &node->fwnode);
ret = anx7411_register_mux(ctx, dev, ctx->mux_node);
if (ret) {
dev_err(dev, "failed register mode switch");
fwnode_handle_put(ctx->mux_node);
ret = -ENODEV;
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);
if (ret) {
dev_err(dev, "power-role not found: %d\n", ret);
return ret;
goto put_fwnode;
}
ret = typec_find_port_power_role(buf);
if (ret < 0)
return ret;
goto put_fwnode;
cap->type = ret;
ret = fwnode_property_read_string(fwnode, "data-role", &buf);
if (ret) {
dev_err(dev, "data-role not found: %d\n", ret);
return ret;
goto put_fwnode;
}
ret = typec_find_port_data_role(buf);
if (ret < 0)
return ret;
goto put_fwnode;
cap->data = ret;
ret = fwnode_property_read_string(fwnode, "try-power-role", &buf);
if (ret) {
dev_err(dev, "try-power-role not found: %d\n", ret);
return ret;
goto put_fwnode;
}
ret = typec_find_power_role(buf);
if (ret < 0)
return ret;
goto put_fwnode;
cap->prefer_role = ret;
/* Get source pdos */
@@ -1192,7 +1207,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
typecp->src_pdo_nr);
if (ret < 0) {
dev_err(dev, "source cap validate failed: %d\n", ret);
return -EINVAL;
goto put_fwnode;
}
typecp->caps_flags |= HAS_SOURCE_CAP;
@@ -1206,7 +1221,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
typecp->sink_pdo_nr);
if (ret < 0) {
dev_err(dev, "sink cap validate failed: %d\n", ret);
return -EINVAL;
goto put_fwnode;
}
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);
ctx->typec.port = NULL;
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,
ctx->typec.port_amode,
MAX_ALTMODE);
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)
@@ -1528,8 +1551,7 @@ free_wq:
destroy_workqueue(plat->workqueue);
free_typec_port:
typec_unregister_port(plat->typec.port);
anx7411_port_unregister_altmodes(plat->typec.port_amode);
anx7411_port_unregister(&plat->typec);
free_typec_switch:
anx7411_unregister_switch(plat);
@@ -1554,17 +1576,11 @@ static void anx7411_i2c_remove(struct i2c_client *client)
if (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_switch(plat);
if (plat->typec.port)
typec_unregister_port(plat->typec.port);
anx7411_port_unregister_altmodes(plat->typec.port_amode);
anx7411_port_unregister(&plat->typec);
}
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]);
else
brelse(es->bh[i]);
if (IS_DYNAMIC_ES(es))
kfree(es->bh);
kfree(es);
return err;
}
@@ -845,6 +849,7 @@ struct exfat_entry_set_cache *exfat_get_dentry_set(struct super_block *sb,
/* byte offset in sector */
off = EXFAT_BLK_OFFSET(byte_offset, sb);
es->start_off = off;
es->bh = es->__bh;
/* sector offset in cluster */
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;
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++) {
/* get the next sector */
if (exfat_is_last_sector_in_cluster(sbi, sec)) {

View File

@@ -169,10 +169,13 @@ struct exfat_entry_set_cache {
bool modified;
unsigned int start_off;
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;
};
#define IS_DYNAMIC_ES(es) ((es)->__bh != (es)->bh)
struct exfat_dir_entry {
struct exfat_chain dir;
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);
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);
if (!cifs_chan_is_iface_active(ses, server)) {
spin_unlock(&ses->chan_lock);
@@ -1977,31 +1983,6 @@ out:
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 *
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 chan_count;
bool do_logoff;
struct cifs_tcon *tcon;
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);
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);
return;
}
spin_unlock(&cifs_tcp_ses_lock);
/* ses_count can never go negative */
WARN_ON(ses->ses_count < 0);
if (ses->ses_status == SES_GOOD)
ses->ses_status = SES_EXITING;
spin_lock(&ses->chan_lock);
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();
rc = server->ops->logoff(xid, ses);
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 :
sess->smb3decryptionkey;
if (enc)
ksmbd_user_session_get(sess);
memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
return 0;

View File

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

View File

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

View File

@@ -66,8 +66,10 @@ static inline bool check_session_id(struct ksmbd_conn *conn, u64 id)
return false;
sess = ksmbd_session_lookup_all(conn, id);
if (sess)
if (sess) {
ksmbd_user_session_put(sess);
return true;
}
pr_err("Invalid user session id: %llu\n", id);
return false;
}
@@ -604,10 +606,8 @@ int smb2_check_user_session(struct ksmbd_work *work)
/* Check for validity of user session */
work->sess = ksmbd_session_lookup_all(conn, sess_id);
if (work->sess) {
ksmbd_user_session_get(work->sess);
if (work->sess)
return 1;
}
ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
return -ENOENT;
}
@@ -1720,29 +1720,35 @@ int smb2_sess_setup(struct ksmbd_work *work)
if (conn->dialect != sess->dialect) {
rc = -EINVAL;
ksmbd_user_session_put(sess);
goto out_err;
}
if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
rc = -EINVAL;
ksmbd_user_session_put(sess);
goto out_err;
}
if (strncmp(conn->ClientGUID, sess->ClientGUID,
SMB2_CLIENT_GUID_SIZE)) {
rc = -ENOENT;
ksmbd_user_session_put(sess);
goto out_err;
}
if (sess->state == SMB2_SESSION_IN_PROGRESS) {
rc = -EACCES;
ksmbd_user_session_put(sess);
goto out_err;
}
if (sess->state == SMB2_SESSION_EXPIRED) {
rc = -EFAULT;
ksmbd_user_session_put(sess);
goto out_err;
}
ksmbd_user_session_put(sess);
if (ksmbd_conn_need_reconnect(conn)) {
rc = -EFAULT;
@@ -1750,7 +1756,8 @@ int smb2_sess_setup(struct ksmbd_work *work)
goto out_err;
}
if (ksmbd_session_lookup(conn, sess_id)) {
sess = ksmbd_session_lookup(conn, sess_id);
if (!sess) {
rc = -EACCES;
goto out_err;
}
@@ -1761,7 +1768,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
}
conn->binding = true;
ksmbd_user_session_get(sess);
} else if ((conn->dialect < SMB30_PROT_ID ||
server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
@@ -1788,7 +1794,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
}
conn->binding = false;
ksmbd_user_session_get(sess);
}
work->sess = sess;
@@ -2207,9 +2212,9 @@ err_out:
int smb2_session_logoff(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
struct smb2_logoff_req *req;
struct smb2_logoff_rsp *rsp;
struct ksmbd_session *sess;
u64 sess_id;
int err;
@@ -2231,11 +2236,6 @@ int smb2_session_logoff(struct ksmbd_work *work)
ksmbd_close_session_fds(work);
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)) {
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
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));
return -ECONNABORTED;
}
ksmbd_user_session_put(sess);
iov[0].iov_base = buf;
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);
/*
* If we just inserted into a new tree block, we have to
* recalculate nkey here because nkey is out of date.
* Update btree keys to reflect the newly added record or keyptr.
* 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
* some records into the new tree block), so use the regular key
* update mechanism.
* If the caller had us target a full block for the insertion, we dealt
* with that by calling the _make_block_unfull function. If the
* "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);
} else if (xfs_btree_needs_key_update(cur, optr)) {
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_dsymlink_hdr *dsl = bp->b_addr;
/* no verification of non-crc buffers */
if (!xfs_has_crc(mp))
return __this_address;
return NULL;
if (!xfs_verify_magic(bp, dsl->sl_magic))
return __this_address;
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(
xfs_fsblock_t fsbno = xchk_btree_cur_fsbno(cur, level);
__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->type = sc->sm->sm_type;
__entry->btnum = cur->bc_btnum;

View File

@@ -1161,6 +1161,14 @@ out_unlock:
xfs_iunlock2_io_mmap(src, dest);
if (ret)
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;
}

View File

@@ -955,13 +955,6 @@ __xfs_trans_commit(
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
* should ever have deferred ops.
@@ -972,13 +965,12 @@ __xfs_trans_commit(
error = xfs_defer_finish_noroll(&tp);
if (error)
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,
* 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__ */
/*
* 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
* @off: the address of the 32-bit offset value
@@ -228,6 +216,33 @@ static inline void *offset_to_ptr(const int *off)
#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 */
#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 sk_buff *clone;
unsigned int ptp_class; /* valid only for clones */
unsigned long ptp_tx_time; /* valid only for clones */
u32 tstamp_lo;
u8 ptp_cmd;
u8 ts_id;

View File

@@ -14,6 +14,7 @@ struct timespec64;
struct clocksource;
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_crosststamp(u64 *cycle,
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
extern bool static_call_initialized;
extern int __init static_call_init(void);
struct static_call_mod {
@@ -223,6 +225,8 @@ extern long __static_call_return0(void);
#elif defined(CONFIG_HAVE_STATIC_CALL)
#define static_call_initialized 0
static inline int static_call_init(void) { return 0; }
#define DEFINE_STATIC_CALL(name, _func) \
@@ -279,6 +283,8 @@ extern long __static_call_return0(void);
#else /* Generic implementation */
#define static_call_initialized 0
static inline int static_call_init(void) { return 0; }
static inline long __static_call_return0(void)

View File

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

View File

@@ -4,7 +4,7 @@
#include <linux/lapb.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_REJECT_CONDITION 0x02

View File

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

View File

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

View File

@@ -10364,8 +10364,11 @@ static void find_equal_scalars(struct bpf_verifier_state *vstate,
struct bpf_reg_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);
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[],
__stop_static_call_tramp_key[];
static bool static_call_initialized;
bool static_call_initialized;
/* mutex to protect key modules/sites */
static DEFINE_MUTEX(static_call_mutex);

View File

@@ -2178,6 +2178,9 @@ void perf_event_detach_bpf_prog(struct perf_event *event)
goto unlock;
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);
if (ret < 0) {
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);
}
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);
event->prog = NULL;

View File

@@ -1816,7 +1816,7 @@ create_local_trace_kprobe(char *func, void *addr, unsigned long offs,
int ret;
char *event;
if (func) {
if (func && !strchr(func, ':')) {
unsigned int count;
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_entries_num = 0;
int tt_diff_entries_count = 0;
bool drop_changes = false;
size_t tt_extra_len = 0;
u16 tvlv_len;
tt_diff_entries_num = atomic_read(&bat_priv->tt.local_changes);
tt_diff_len = batadv_tt_len(tt_diff_entries_num);
/* 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_entries_num = 0;
drop_changes = true;
}
tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv, &tt_data,
&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;
if (tt_diff_len == 0)
if (!drop_changes && tt_diff_len == 0)
goto container_register;
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);
tt_extra_len = batadv_tt_len(tt_diff_entries_num -
tt_diff_entries_count);
/* Keep the buffer for possible tt_request */
spin_lock_bh(&bat_priv->tt.last_changeset_lock);
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);
/* check whether this new OGM has no changes due to size problems */
if (tt_diff_entries_count > 0) {
tt_diff_len -= tt_extra_len;
/* if kmalloc() fails we will reply with the full table
* 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);
/* Remove extra packet space for OGM */
tvlv_len -= tt_extra_len;
container_register:
batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data,
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
* 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,
struct batadv_hashtable *hash,
void *tvlv_buff, u16 tt_len,
bool (*valid_cb)(const void *,
const void *,
u8 *flags),
void *cb_data)
static u16 batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
struct batadv_hashtable *hash,
void *tvlv_buff, u16 tt_len,
bool (*valid_cb)(const void *,
const void *,
u8 *flags),
void *cb_data)
{
struct batadv_tt_common_entry *tt_common_entry;
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;
if (!valid_cb)
return;
return tt_len;
rcu_read_lock();
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();
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;
/* fill the rest of the tvlv with the real TT entries */
batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.global_hash,
tt_change, tt_len,
batadv_tt_global_valid,
req_dst_orig_node);
tvlv_len -= batadv_tt_tvlv_generate(bat_priv,
bat_priv->tt.global_hash,
tt_change, tt_len,
batadv_tt_global_valid,
req_dst_orig_node);
}
/* 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;
/* fill the rest of the tvlv with the real TT entries */
batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.local_hash,
tt_change, tt_len,
batadv_tt_local_valid, NULL);
tvlv_len -= batadv_tt_tvlv_generate(bat_priv,
bat_priv->tt.local_hash,
tt_change, tt_len,
batadv_tt_local_valid,
NULL);
}
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;
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);
@@ -995,7 +999,7 @@ static int iso_sock_accept(struct socket *sock, struct socket *newsock,
release_sock(sk);
timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
lock_sock(sk);
lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
}
remove_wait_queue(sk_sleep(sk), &wait);

View File

@@ -268,10 +268,13 @@ static int sco_connect(struct sock *sk)
else
type = SCO_LINK;
if (sco_pi(sk)->setting == BT_VOICE_TRANSPARENT &&
(!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev))) {
err = -EOPNOTSUPP;
goto unlock;
switch (sco_pi(sk)->setting & SCO_AIRMODE_MASK) {
case SCO_AIRMODE_TRANSP:
if (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev)) {
err = -EOPNOTSUPP;
goto unlock;
}
break;
}
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)
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;
hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src,
BDADDR_BREDR);
@@ -902,9 +898,14 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
err = -EBADFD;
break;
}
if (enhanced_sync_conn_capable(hdev) &&
voice.setting == BT_VOICE_TRANSPARENT)
sco_pi(sk)->codec.id = BT_CODEC_TRANSPARENT;
switch (sco_pi(sk)->setting & SCO_AIRMODE_MASK) {
case SCO_AIRMODE_TRANSP:
if (enhanced_sync_conn_capable(hdev))
sco_pi(sk)->codec.id = BT_CODEC_TRANSPARENT;
break;
}
hci_dev_put(hdev);
break;

View File

@@ -435,11 +435,28 @@ out_free:
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)
{
if (refcount_dec_and_test(&net->passive)) {
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();
net_complete_free();
/* Finally it is safe to free my network namespace structure */
list_for_each_entry_safe(net, tmp, &net_exit_list, 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;
list_del(&link->list);
sk_psock_free_link(link);
break;
}
}
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;
if (mptcp_syn_options(sk, skb, &size, &opts->mptcp)) {
opts->options |= OPTION_MPTCP;
remaining -= size;
if (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 link_station_parameters *params)
{
int ret = 0;
struct ieee80211_supported_band *sband;
struct ieee80211_sub_if_data *sdata = sta->sdata;
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) {
int ret;
link_sta->pub->txpwr.type = params->txpwr.type;
if (params->txpwr.type == NL80211_TX_POWER_LIMITED)
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,
link_sta);
ieee80211_sta_init_nss(link_sta);
if (params->opmode_notif_used) {
/* returned value is only needed for rc update, but the
* 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);
}
ieee80211_sta_init_nss(link_sta);
return ret;
return 0;
}
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_tail;
u32 t_len;
/* optional qdisc for classful handling (NULL at netem init) */
struct Qdisc *qdisc;
@@ -373,6 +375,7 @@ static void tfifo_reset(struct Qdisc *sch)
rtnl_kfree_skbs(q->t_head, q->t_tail);
q->t_head = NULL;
q->t_tail = NULL;
q->t_len = 0;
}
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_insert_color(&nskb->rbnode, &q->t_root);
}
q->t_len++;
sch->q.qlen++;
}
@@ -508,7 +512,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
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 */
skb->next = segs;
qdisc_drop_all(skb, sch, to_free);
@@ -692,8 +696,8 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
tfifo_dequeue:
skb = __qdisc_dequeue_head(&sch->q);
if (skb) {
qdisc_qstats_backlog_dec(sch, skb);
deliver:
qdisc_qstats_backlog_dec(sch, skb);
qdisc_bstats_update(sch, skb);
return skb;
}
@@ -709,8 +713,7 @@ deliver:
if (time_to_send <= now && q->slot.slot_next <= now) {
netem_erase_head(q, skb);
sch->q.qlen--;
qdisc_qstats_backlog_dec(sch, skb);
q->t_len--;
skb->next = NULL;
skb->prev = NULL;
/* skb->dev shares skb->rbnode area,
@@ -737,16 +740,21 @@ deliver:
if (net_xmit_drop_count(err))
qdisc_qstats_drop(sch);
qdisc_tree_reduce_backlog(sch, 1, pkt_len);
sch->qstats.backlog -= pkt_len;
sch->q.qlen--;
}
goto tfifo_dequeue;
}
sch->q.qlen--;
goto deliver;
}
if (q->qdisc) {
skb = q->qdisc->ops->dequeue(q->qdisc);
if (skb)
if (skb) {
sch->q.qlen--;
goto deliver;
}
}
qdisc_watchdog_schedule_ns(&q->watchdog,
@@ -756,8 +764,10 @@ deliver:
if (q->qdisc) {
skb = q->qdisc->ops->dequeue(q->qdisc);
if (skb)
if (skb) {
sch->q.qlen--;
goto deliver;
}
}
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_replicast *rcast, *tmp;
struct tipc_net *tn;
list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) {
dst_cache_destroy(&rcast->dst_cache);
@@ -818,10 +819,14 @@ static void cleanup_bearer(struct work_struct *work)
kfree_rcu(rcast, rcu);
}
tn = tipc_net(sock_net(ub->ubsock->sk));
dst_cache_destroy(&ub->rcast.dst_cache);
udp_tunnel_sock_release(ub->ubsock);
/* Note: could use a call_rcu() to avoid another synchronize_net() */
synchronize_net();
atomic_dec(&tipc_net(sock_net(ub->ubsock->sk))->wq_count);
atomic_dec(&tn->wq_count);
kfree(ub);
}

View File

@@ -811,7 +811,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_MLO_LINKS] =
NLA_POLICY_NESTED_ARRAY(nl80211_policy),
[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_MLO_SUPPORT] = { .type = NLA_FLAG },
[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);
ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status);
if (!ACPI_FAILURE(ret))
if (!ACPI_FAILURE(ret)) {
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);
else
return 0;
check_dmi_entry:
/* check for any DMI overrides */
dmi_id = dmi_first_match(yc_acp_quirk_table);
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)
{
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;
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);
if (err < 0)
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,
&new_device_descriptor, sizeof(new_device_descriptor));
new_device_descriptor, sizeof(*new_device_descriptor));
if (err < 0)
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",
new_device_descriptor.bNumConfigurations);
new_device_descriptor->bNumConfigurations);
else
memcpy(&dev->descriptor, &new_device_descriptor, sizeof(dev->descriptor));
memcpy(&dev->descriptor, new_device_descriptor, sizeof(dev->descriptor));
err = usb_reset_configuration(dev);
if (err < 0)
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)
{
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;
u8 bootresponse[0x12];
int fwsize;
@@ -939,15 +943,19 @@ static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
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,
&new_device_descriptor, sizeof(new_device_descriptor));
new_device_descriptor, sizeof(*new_device_descriptor));
if (err < 0)
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",
new_device_descriptor.bNumConfigurations);
new_device_descriptor->bNumConfigurations);
else
memcpy(&dev->descriptor, &new_device_descriptor, sizeof(dev->descriptor));
memcpy(&dev->descriptor, new_device_descriptor, sizeof(dev->descriptor));
err = usb_reset_configuration(dev);
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)
{
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 descriptor_size;
@@ -1274,15 +1282,19 @@ static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
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,
&new_device_descriptor, sizeof(new_device_descriptor));
new_device_descriptor, sizeof(*new_device_descriptor));
if (err < 0)
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",
new_device_descriptor.bNumConfigurations);
new_device_descriptor->bNumConfigurations);
else
memcpy(&dev->descriptor, &new_device_descriptor, sizeof(dev->descriptor));
memcpy(&dev->descriptor, new_device_descriptor, sizeof(dev->descriptor));
err = usb_reset_configuration(dev);
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),
DEVICE_FLG(0x046d, 0x09a4, /* Logitech QuickCam E 3500 */
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 */
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
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;
case INSN_CONTEXT_SWITCH:
if (func && (!next_insn || !next_insn->hint)) {
WARN_FUNC("unsupported instruction in callable function",
sec, insn->offset);
return 1;
if (func) {
if (!next_insn || !next_insn->hint) {
WARN_FUNC("unsupported instruction in callable function",
sec, insn->offset);
return 1;
}
break;
}
return 0;

View File

@@ -22,20 +22,34 @@ SB_ITC=0
h1_create()
{
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()
{
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
}
h2_create()
{
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()
{
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
}
@@ -101,6 +115,11 @@ port_pool_test()
local exp_max_occ=$(devlink_cell_size_get)
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
$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
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
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"
@@ -122,6 +136,11 @@ port_pool_test()
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"
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()
@@ -129,6 +148,11 @@ port_tc_ip_test()
local exp_max_occ=$(devlink_cell_size_get)
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
$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
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
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"
@@ -150,6 +169,11 @@ port_tc_ip_test()
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"
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()
@@ -157,17 +181,15 @@ port_tc_arp_test()
local exp_max_occ=$(devlink_cell_size_get)
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
$MZ $h1 -c 1 -p 10 -a $h1mac -A 192.0.1.1 -t arp -q
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
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"
@@ -177,6 +199,9 @@ port_tc_arp_test()
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"
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()