mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
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:
@@ -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
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 6
|
||||
PATCHLEVEL = 1
|
||||
SUBLEVEL = 120
|
||||
SUBLEVEL = 121
|
||||
EXTRAVERSION =
|
||||
NAME = Curry Ramen
|
||||
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 | \
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) |
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -101,7 +101,6 @@ struct qcaspi {
|
||||
#endif
|
||||
|
||||
/* user configurable options */
|
||||
u32 clkspeed;
|
||||
u8 legacy_mode;
|
||||
u16 burst_len;
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]))
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user