Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
b1513c3531
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 11
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc7
|
||||
EXTRAVERSION = -rc8
|
||||
NAME = Fearless Coyote
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -406,6 +406,14 @@ config ARC_HAS_DIV_REM
|
|||
bool "Insn: div, divu, rem, remu"
|
||||
default y
|
||||
|
||||
config ARC_HAS_ACCL_REGS
|
||||
bool "Reg Pair ACCL:ACCH (FPU and/or MPY > 6)"
|
||||
default n
|
||||
help
|
||||
Depending on the configuration, CPU can contain accumulator reg-pair
|
||||
(also referred to as r58:r59). These can also be used by gcc as GPR so
|
||||
kernel needs to save/restore per process
|
||||
|
||||
endif # ISA_ARCV2
|
||||
|
||||
endmenu # "ARC CPU Configuration"
|
||||
|
|
|
@ -17,10 +17,11 @@
|
|||
#include <asm/barrier.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
#define ATOMIC_INIT(i) { (i) }
|
||||
|
||||
#ifndef CONFIG_ARC_PLAT_EZNPS
|
||||
|
||||
#define atomic_read(v) READ_ONCE((v)->counter)
|
||||
#define ATOMIC_INIT(i) { (i) }
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_LLSC
|
||||
|
||||
|
|
|
@ -16,6 +16,11 @@
|
|||
;
|
||||
; Now manually save: r12, sp, fp, gp, r25
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_ACCL_REGS
|
||||
PUSH r59
|
||||
PUSH r58
|
||||
#endif
|
||||
|
||||
PUSH r30
|
||||
PUSH r12
|
||||
|
||||
|
@ -75,6 +80,11 @@
|
|||
POP r12
|
||||
POP r30
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_ACCL_REGS
|
||||
POP r58
|
||||
POP r59
|
||||
#endif
|
||||
|
||||
.endm
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
|
|
@ -86,6 +86,10 @@ struct pt_regs {
|
|||
|
||||
unsigned long r12, r30;
|
||||
|
||||
#ifdef CONFIG_ARC_HAS_ACCL_REGS
|
||||
unsigned long r58, r59; /* ACCL/ACCH used by FPU / DSP MPY */
|
||||
#endif
|
||||
|
||||
/*------- Below list auto saved by h/w -----------*/
|
||||
unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
|
||||
|
||||
|
|
|
@ -319,7 +319,8 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
|
|||
static void arc_chk_core_config(void)
|
||||
{
|
||||
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
|
||||
int fpu_enabled;
|
||||
int saved = 0, present = 0;
|
||||
char *opt_nm = NULL;;
|
||||
|
||||
if (!cpu->extn.timer0)
|
||||
panic("Timer0 is not present!\n");
|
||||
|
@ -346,17 +347,28 @@ static void arc_chk_core_config(void)
|
|||
|
||||
/*
|
||||
* FP hardware/software config sanity
|
||||
* -If hardware contains DPFP, kernel needs to save/restore FPU state
|
||||
* -If hardware present, kernel needs to save/restore FPU state
|
||||
* -If not, it will crash trying to save/restore the non-existant regs
|
||||
*
|
||||
* (only DPDP checked since SP has no arch visible regs)
|
||||
*/
|
||||
fpu_enabled = IS_ENABLED(CONFIG_ARC_FPU_SAVE_RESTORE);
|
||||
|
||||
if (cpu->extn.fpu_dp && !fpu_enabled)
|
||||
pr_warn("CONFIG_ARC_FPU_SAVE_RESTORE needed for working apps\n");
|
||||
else if (!cpu->extn.fpu_dp && fpu_enabled)
|
||||
panic("FPU non-existent, disable CONFIG_ARC_FPU_SAVE_RESTORE\n");
|
||||
if (is_isa_arcompact()) {
|
||||
opt_nm = "CONFIG_ARC_FPU_SAVE_RESTORE";
|
||||
saved = IS_ENABLED(CONFIG_ARC_FPU_SAVE_RESTORE);
|
||||
|
||||
/* only DPDP checked since SP has no arch visible regs */
|
||||
present = cpu->extn.fpu_dp;
|
||||
} else {
|
||||
opt_nm = "CONFIG_ARC_HAS_ACCL_REGS";
|
||||
saved = IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS);
|
||||
|
||||
/* Accumulator Low:High pair (r58:59) present if DSP MPY or FPU */
|
||||
present = cpu->extn_mpy.dsp | cpu->extn.fpu_sp | cpu->extn.fpu_dp;
|
||||
}
|
||||
|
||||
if (present && !saved)
|
||||
pr_warn("Enable %s for working apps\n", opt_nm);
|
||||
else if (!present && saved)
|
||||
panic("Disable %s, hardware NOT present\n", opt_nm);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -489,7 +489,7 @@ $(generic_defconfigs):
|
|||
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh \
|
||||
-m -O $(objtree) $(srctree)/arch/$(ARCH)/configs/generic_defconfig $^ \
|
||||
$(foreach board,$(BOARDS),$(generic_config_dir)/board-$(board).config)
|
||||
$(Q)$(MAKE) olddefconfig
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile olddefconfig
|
||||
|
||||
#
|
||||
# Prevent generic merge_config rules attempting to merge single fragments
|
||||
|
@ -503,8 +503,8 @@ $(generic_config_dir)/%.config: ;
|
|||
#
|
||||
.PHONY: sead3_defconfig
|
||||
sead3_defconfig:
|
||||
$(Q)$(MAKE) 32r2el_defconfig BOARDS=sead-3
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile 32r2el_defconfig BOARDS=sead-3
|
||||
|
||||
.PHONY: sead3micro_defconfig
|
||||
sead3micro_defconfig:
|
||||
$(Q)$(MAKE) micro32r2el_defconfig BOARDS=sead-3
|
||||
$(Q)$(MAKE) -f $(srctree)/Makefile micro32r2el_defconfig BOARDS=sead-3
|
||||
|
|
|
@ -3,3 +3,4 @@
|
|||
#include <asm/fpu.h>
|
||||
#include <asm-generic/asm-prototypes.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/ftrace.h>
|
||||
|
|
|
@ -80,7 +80,7 @@ static unsigned int calculate_min_delta(void)
|
|||
}
|
||||
|
||||
/* Sorted insert of 75th percentile into buf2 */
|
||||
for (k = 0; k < i; ++k) {
|
||||
for (k = 0; k < i && k < ARRAY_SIZE(buf2); ++k) {
|
||||
if (buf1[ARRAY_SIZE(buf1) - 1] < buf2[k]) {
|
||||
l = min_t(unsigned int,
|
||||
i, ARRAY_SIZE(buf2) - 1);
|
||||
|
|
|
@ -257,7 +257,7 @@ int arch_check_elf(void *_ehdr, bool has_interpreter, void *_interp_ehdr,
|
|||
else if ((prog_req.fr1 && prog_req.frdefault) ||
|
||||
(prog_req.single && !prog_req.frdefault))
|
||||
/* Make sure 64-bit MIPS III/IV/64R1 will not pick FR1 */
|
||||
state->overall_fp_mode = ((current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
|
||||
state->overall_fp_mode = ((raw_current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
|
||||
cpu_has_mips_r2_r6) ?
|
||||
FP_FR1 : FP_FR0;
|
||||
else if (prog_req.fr1)
|
||||
|
|
|
@ -244,9 +244,6 @@ static int compute_signal(int tt)
|
|||
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
|
||||
{
|
||||
int reg;
|
||||
struct thread_info *ti = task_thread_info(p);
|
||||
unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32;
|
||||
struct pt_regs *regs = (struct pt_regs *)ksp - 1;
|
||||
#if (KGDB_GDB_REG_SIZE == 32)
|
||||
u32 *ptr = (u32 *)gdb_regs;
|
||||
#else
|
||||
|
@ -254,25 +251,46 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
|
|||
#endif
|
||||
|
||||
for (reg = 0; reg < 16; reg++)
|
||||
*(ptr++) = regs->regs[reg];
|
||||
*(ptr++) = 0;
|
||||
|
||||
/* S0 - S7 */
|
||||
for (reg = 16; reg < 24; reg++)
|
||||
*(ptr++) = regs->regs[reg];
|
||||
*(ptr++) = p->thread.reg16;
|
||||
*(ptr++) = p->thread.reg17;
|
||||
*(ptr++) = p->thread.reg18;
|
||||
*(ptr++) = p->thread.reg19;
|
||||
*(ptr++) = p->thread.reg20;
|
||||
*(ptr++) = p->thread.reg21;
|
||||
*(ptr++) = p->thread.reg22;
|
||||
*(ptr++) = p->thread.reg23;
|
||||
|
||||
for (reg = 24; reg < 28; reg++)
|
||||
*(ptr++) = 0;
|
||||
|
||||
/* GP, SP, FP, RA */
|
||||
for (reg = 28; reg < 32; reg++)
|
||||
*(ptr++) = regs->regs[reg];
|
||||
*(ptr++) = (long)p;
|
||||
*(ptr++) = p->thread.reg29;
|
||||
*(ptr++) = p->thread.reg30;
|
||||
*(ptr++) = p->thread.reg31;
|
||||
|
||||
*(ptr++) = regs->cp0_status;
|
||||
*(ptr++) = regs->lo;
|
||||
*(ptr++) = regs->hi;
|
||||
*(ptr++) = regs->cp0_badvaddr;
|
||||
*(ptr++) = regs->cp0_cause;
|
||||
*(ptr++) = regs->cp0_epc;
|
||||
*(ptr++) = p->thread.cp0_status;
|
||||
|
||||
/* lo, hi */
|
||||
*(ptr++) = 0;
|
||||
*(ptr++) = 0;
|
||||
|
||||
/*
|
||||
* BadVAddr, Cause
|
||||
* Ideally these would come from the last exception frame up the stack
|
||||
* but that requires unwinding, otherwise we can't know much for sure.
|
||||
*/
|
||||
*(ptr++) = 0;
|
||||
*(ptr++) = 0;
|
||||
|
||||
/*
|
||||
* PC
|
||||
* use return address (RA), i.e. the moment after return from resume()
|
||||
*/
|
||||
*(ptr++) = p->thread.reg31;
|
||||
}
|
||||
|
||||
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
|
||||
|
|
|
@ -1446,6 +1446,11 @@ static int mipsxx_pmu_handle_shared_irq(void)
|
|||
HANDLE_COUNTER(0)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
|
||||
read_unlock(&pmuint_rwlock);
|
||||
#endif
|
||||
resume_local_counters();
|
||||
|
||||
/*
|
||||
* Do all the work for the pending perf events. We can do this
|
||||
* in here because the performance counter interrupt is a regular
|
||||
|
@ -1454,10 +1459,6 @@ static int mipsxx_pmu_handle_shared_irq(void)
|
|||
if (handled == IRQ_HANDLED)
|
||||
irq_work_run();
|
||||
|
||||
#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
|
||||
read_unlock(&pmuint_rwlock);
|
||||
#endif
|
||||
resume_local_counters();
|
||||
return handled;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/task.h>
|
||||
#include <linux/start_kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/printk.h>
|
||||
|
|
|
@ -422,13 +422,12 @@ void play_dead(void)
|
|||
local_irq_disable();
|
||||
idle_task_exit();
|
||||
cpu = smp_processor_id();
|
||||
core = cpu_data[cpu].core;
|
||||
cpu_death = CPU_DEATH_POWER;
|
||||
|
||||
pr_debug("CPU%d going offline\n", cpu);
|
||||
|
||||
if (cpu_has_mipsmt || cpu_has_vp) {
|
||||
core = cpu_data[cpu].core;
|
||||
|
||||
/* Look for another online VPE within the core */
|
||||
for_each_online_cpu(cpu_death_sibling) {
|
||||
if (cpu_data[cpu_death_sibling].core != core)
|
||||
|
|
|
@ -232,6 +232,17 @@ void __init arch_init_irq(void)
|
|||
{
|
||||
int corehi_irq;
|
||||
|
||||
/*
|
||||
* Preallocate the i8259's expected virq's here. Since irqchip_init()
|
||||
* will probe the irqchips in hierarchial order, i8259 is probed last.
|
||||
* If anything allocates a virq before the i8259 is probed, it will
|
||||
* be given one of the i8259's expected range and consequently setup
|
||||
* of the i8259 will fail.
|
||||
*/
|
||||
WARN(irq_alloc_descs(I8259A_IRQ_BASE, I8259A_IRQ_BASE,
|
||||
16, numa_node_id()) < 0,
|
||||
"Cannot reserve i8259 virqs at IRQ%d\n", I8259A_IRQ_BASE);
|
||||
|
||||
i8259_set_poll(mips_pcibios_iack);
|
||||
irqchip_init();
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ void register_pci_controller(struct pci_controller *hose)
|
|||
}
|
||||
|
||||
INIT_LIST_HEAD(&hose->list);
|
||||
list_add(&hose->list, &controllers);
|
||||
list_add_tail(&hose->list, &controllers);
|
||||
|
||||
/*
|
||||
* Do not panic here but later - this might happen before console init.
|
||||
|
|
|
@ -83,6 +83,7 @@ config SPARC64
|
|||
select HAVE_ARCH_AUDITSYSCALL
|
||||
select ARCH_SUPPORTS_ATOMIC_RMW
|
||||
select HAVE_NMI
|
||||
select HAVE_REGS_AND_STACK_ACCESS_API
|
||||
|
||||
config ARCH_DEFCONFIG
|
||||
string
|
||||
|
|
|
@ -83,7 +83,8 @@ unsigned long profile_pc(struct pt_regs *);
|
|||
|
||||
#define MAX_REG_OFFSET (offsetof(struct pt_regs, magic))
|
||||
|
||||
extern int regs_query_register_offset(const char *name);
|
||||
int regs_query_register_offset(const char *name);
|
||||
unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n);
|
||||
|
||||
/**
|
||||
* regs_get_register() - get register value from its offset
|
||||
|
|
|
@ -425,8 +425,9 @@
|
|||
#define __NR_copy_file_range 357
|
||||
#define __NR_preadv2 358
|
||||
#define __NR_pwritev2 359
|
||||
#define __NR_statx 360
|
||||
|
||||
#define NR_syscalls 360
|
||||
#define NR_syscalls 361
|
||||
|
||||
/* Bitmask values returned from kern_features system call. */
|
||||
#define KERN_FEATURE_MIXED_MODE_STACK 0x00000001
|
||||
|
@ -442,4 +443,9 @@
|
|||
#define __IGNORE_getresgid
|
||||
#endif
|
||||
|
||||
/* Sparc doesn't have protection keys. */
|
||||
#define __IGNORE_pkey_mprotect
|
||||
#define __IGNORE_pkey_alloc
|
||||
#define __IGNORE_pkey_free
|
||||
|
||||
#endif /* _UAPI_SPARC_UNISTD_H */
|
||||
|
|
|
@ -1162,3 +1162,39 @@ int regs_query_register_offset(const char *name)
|
|||
return roff->offset;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* regs_within_kernel_stack() - check the address in the stack
|
||||
* @regs: pt_regs which contains kernel stack pointer.
|
||||
* @addr: address which is checked.
|
||||
*
|
||||
* regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
|
||||
* If @addr is within the kernel stack, it returns true. If not, returns false.
|
||||
*/
|
||||
static inline int regs_within_kernel_stack(struct pt_regs *regs,
|
||||
unsigned long addr)
|
||||
{
|
||||
unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS;
|
||||
return ((addr & ~(THREAD_SIZE - 1)) ==
|
||||
(ksp & ~(THREAD_SIZE - 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* regs_get_kernel_stack_nth() - get Nth entry of the stack
|
||||
* @regs: pt_regs which contains kernel stack pointer.
|
||||
* @n: stack entry number.
|
||||
*
|
||||
* regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
|
||||
* is specified by @regs. If the @n th entry is NOT in the kernel stack,
|
||||
* this returns 0.
|
||||
*/
|
||||
unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
|
||||
{
|
||||
unsigned long ksp = kernel_stack_pointer(regs) + STACK_BIAS;
|
||||
unsigned long *addr = (unsigned long *)ksp;
|
||||
addr += n;
|
||||
if (regs_within_kernel_stack(regs, (unsigned long)addr))
|
||||
return *addr;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -89,3 +89,4 @@ sys_call_table:
|
|||
/*345*/ .long sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
|
||||
/*350*/ .long sys_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
|
||||
/*355*/ .long sys_setsockopt, sys_mlock2, sys_copy_file_range, sys_preadv2, sys_pwritev2
|
||||
/*360*/ .long sys_statx
|
||||
|
|
|
@ -90,6 +90,7 @@ sys_call_table32:
|
|||
.word sys32_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
|
||||
/*350*/ .word sys32_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
|
||||
.word compat_sys_setsockopt, sys_mlock2, sys_copy_file_range, compat_sys_preadv2, compat_sys_pwritev2
|
||||
/*360*/ .word sys_statx
|
||||
|
||||
#endif /* CONFIG_COMPAT */
|
||||
|
||||
|
@ -171,3 +172,4 @@ sys_call_table:
|
|||
.word sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
|
||||
/*350*/ .word sys64_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
|
||||
.word sys_setsockopt, sys_mlock2, sys_copy_file_range, sys_preadv2, sys_pwritev2
|
||||
/*360*/ .word sys_statx
|
||||
|
|
|
@ -85,7 +85,7 @@ void mce_gen_pool_process(struct work_struct *__unused)
|
|||
head = llist_reverse_order(head);
|
||||
llist_for_each_entry_safe(node, tmp, head, llnode) {
|
||||
mce = &node->mce;
|
||||
atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, mce);
|
||||
blocking_notifier_call_chain(&x86_mce_decoder_chain, 0, mce);
|
||||
gen_pool_free(mce_evt_pool, (unsigned long)node, sizeof(*node));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ enum severity_level {
|
|||
MCE_PANIC_SEVERITY,
|
||||
};
|
||||
|
||||
extern struct atomic_notifier_head x86_mce_decoder_chain;
|
||||
extern struct blocking_notifier_head x86_mce_decoder_chain;
|
||||
|
||||
#define ATTR_LEN 16
|
||||
#define INITIAL_CHECK_INTERVAL 5 * 60 /* 5 minutes */
|
||||
|
|
|
@ -123,7 +123,7 @@ static void (*quirk_no_way_out)(int bank, struct mce *m, struct pt_regs *regs);
|
|||
* CPU/chipset specific EDAC code can register a notifier call here to print
|
||||
* MCE errors in a human-readable form.
|
||||
*/
|
||||
ATOMIC_NOTIFIER_HEAD(x86_mce_decoder_chain);
|
||||
BLOCKING_NOTIFIER_HEAD(x86_mce_decoder_chain);
|
||||
|
||||
/* Do initial initialization of a struct mce */
|
||||
void mce_setup(struct mce *m)
|
||||
|
@ -220,7 +220,7 @@ void mce_register_decode_chain(struct notifier_block *nb)
|
|||
|
||||
WARN_ON(nb->priority > MCE_PRIO_LOWEST && nb->priority < MCE_PRIO_EDAC);
|
||||
|
||||
atomic_notifier_chain_register(&x86_mce_decoder_chain, nb);
|
||||
blocking_notifier_chain_register(&x86_mce_decoder_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mce_register_decode_chain);
|
||||
|
||||
|
@ -228,7 +228,7 @@ void mce_unregister_decode_chain(struct notifier_block *nb)
|
|||
{
|
||||
atomic_dec(&num_notifiers);
|
||||
|
||||
atomic_notifier_chain_unregister(&x86_mce_decoder_chain, nb);
|
||||
blocking_notifier_chain_unregister(&x86_mce_decoder_chain, nb);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mce_unregister_decode_chain);
|
||||
|
||||
|
@ -321,18 +321,7 @@ static void __print_mce(struct mce *m)
|
|||
|
||||
static void print_mce(struct mce *m)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
__print_mce(m);
|
||||
|
||||
/*
|
||||
* Print out human-readable details about the MCE error,
|
||||
* (if the CPU has an implementation for that)
|
||||
*/
|
||||
ret = atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, m);
|
||||
if (ret == NOTIFY_STOP)
|
||||
return;
|
||||
|
||||
pr_emerg_ratelimited(HW_ERR "Run the above through 'mcelog --ascii'\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -148,11 +148,11 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol,
|
|||
return err;
|
||||
}
|
||||
|
||||
if (bytes == 0) {
|
||||
err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (bytes == 0) {
|
||||
err = clear_update_marker(ubi, vol, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
|
|
@ -72,6 +72,8 @@ config CAN_PEAK_USB
|
|||
PCAN-USB Pro dual CAN 2.0b channels USB adapter
|
||||
PCAN-USB FD single CAN-FD channel USB adapter
|
||||
PCAN-USB Pro FD dual CAN-FD channels USB adapter
|
||||
PCAN-Chip USB CAN-FD to USB stamp module
|
||||
PCAN-USB X6 6 CAN-FD channels USB adapter
|
||||
|
||||
(see also http://www.peak-system.com).
|
||||
|
||||
|
|
|
@ -739,13 +739,18 @@ static const struct net_device_ops gs_usb_netdev_ops = {
|
|||
static int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
|
||||
{
|
||||
struct gs_can *dev = netdev_priv(netdev);
|
||||
struct gs_identify_mode imode;
|
||||
struct gs_identify_mode *imode;
|
||||
int rc;
|
||||
|
||||
imode = kmalloc(sizeof(*imode), GFP_KERNEL);
|
||||
|
||||
if (!imode)
|
||||
return -ENOMEM;
|
||||
|
||||
if (do_identify)
|
||||
imode.mode = GS_CAN_IDENTIFY_ON;
|
||||
imode->mode = GS_CAN_IDENTIFY_ON;
|
||||
else
|
||||
imode.mode = GS_CAN_IDENTIFY_OFF;
|
||||
imode->mode = GS_CAN_IDENTIFY_OFF;
|
||||
|
||||
rc = usb_control_msg(interface_to_usbdev(dev->iface),
|
||||
usb_sndctrlpipe(interface_to_usbdev(dev->iface),
|
||||
|
@ -755,10 +760,12 @@ static int gs_usb_set_identify(struct net_device *netdev, bool do_identify)
|
|||
USB_RECIP_INTERFACE,
|
||||
dev->channel,
|
||||
0,
|
||||
&imode,
|
||||
sizeof(imode),
|
||||
imode,
|
||||
sizeof(*imode),
|
||||
100);
|
||||
|
||||
kfree(imode);
|
||||
|
||||
return (rc > 0) ? 0 : rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ static struct usb_device_id peak_usb_table[] = {
|
|||
{USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USBPRO_PRODUCT_ID)},
|
||||
{USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USBFD_PRODUCT_ID)},
|
||||
{USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USBPROFD_PRODUCT_ID)},
|
||||
{USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USBCHIP_PRODUCT_ID)},
|
||||
{USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USBX6_PRODUCT_ID)},
|
||||
{} /* Terminating entry */
|
||||
};
|
||||
|
@ -51,6 +52,7 @@ static const struct peak_usb_adapter *const peak_usb_adapters_list[] = {
|
|||
&pcan_usb_pro,
|
||||
&pcan_usb_fd,
|
||||
&pcan_usb_pro_fd,
|
||||
&pcan_usb_chip,
|
||||
&pcan_usb_x6,
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#define PCAN_USBPRO_PRODUCT_ID 0x000d
|
||||
#define PCAN_USBPROFD_PRODUCT_ID 0x0011
|
||||
#define PCAN_USBFD_PRODUCT_ID 0x0012
|
||||
#define PCAN_USBCHIP_PRODUCT_ID 0x0013
|
||||
#define PCAN_USBX6_PRODUCT_ID 0x0014
|
||||
|
||||
#define PCAN_USB_DRIVER_NAME "peak_usb"
|
||||
|
@ -90,6 +91,7 @@ struct peak_usb_adapter {
|
|||
extern const struct peak_usb_adapter pcan_usb;
|
||||
extern const struct peak_usb_adapter pcan_usb_pro;
|
||||
extern const struct peak_usb_adapter pcan_usb_fd;
|
||||
extern const struct peak_usb_adapter pcan_usb_chip;
|
||||
extern const struct peak_usb_adapter pcan_usb_pro_fd;
|
||||
extern const struct peak_usb_adapter pcan_usb_x6;
|
||||
|
||||
|
|
|
@ -1062,6 +1062,78 @@ const struct peak_usb_adapter pcan_usb_fd = {
|
|||
.do_get_berr_counter = pcan_usb_fd_get_berr_counter,
|
||||
};
|
||||
|
||||
/* describes the PCAN-CHIP USB */
|
||||
static const struct can_bittiming_const pcan_usb_chip_const = {
|
||||
.name = "pcan_chip_usb",
|
||||
.tseg1_min = 1,
|
||||
.tseg1_max = (1 << PUCAN_TSLOW_TSGEG1_BITS),
|
||||
.tseg2_min = 1,
|
||||
.tseg2_max = (1 << PUCAN_TSLOW_TSGEG2_BITS),
|
||||
.sjw_max = (1 << PUCAN_TSLOW_SJW_BITS),
|
||||
.brp_min = 1,
|
||||
.brp_max = (1 << PUCAN_TSLOW_BRP_BITS),
|
||||
.brp_inc = 1,
|
||||
};
|
||||
|
||||
static const struct can_bittiming_const pcan_usb_chip_data_const = {
|
||||
.name = "pcan_chip_usb",
|
||||
.tseg1_min = 1,
|
||||
.tseg1_max = (1 << PUCAN_TFAST_TSGEG1_BITS),
|
||||
.tseg2_min = 1,
|
||||
.tseg2_max = (1 << PUCAN_TFAST_TSGEG2_BITS),
|
||||
.sjw_max = (1 << PUCAN_TFAST_SJW_BITS),
|
||||
.brp_min = 1,
|
||||
.brp_max = (1 << PUCAN_TFAST_BRP_BITS),
|
||||
.brp_inc = 1,
|
||||
};
|
||||
|
||||
const struct peak_usb_adapter pcan_usb_chip = {
|
||||
.name = "PCAN-Chip USB",
|
||||
.device_id = PCAN_USBCHIP_PRODUCT_ID,
|
||||
.ctrl_count = PCAN_USBFD_CHANNEL_COUNT,
|
||||
.ctrlmode_supported = CAN_CTRLMODE_FD |
|
||||
CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LISTENONLY,
|
||||
.clock = {
|
||||
.freq = PCAN_UFD_CRYSTAL_HZ,
|
||||
},
|
||||
.bittiming_const = &pcan_usb_chip_const,
|
||||
.data_bittiming_const = &pcan_usb_chip_data_const,
|
||||
|
||||
/* size of device private data */
|
||||
.sizeof_dev_private = sizeof(struct pcan_usb_fd_device),
|
||||
|
||||
/* timestamps usage */
|
||||
.ts_used_bits = 32,
|
||||
.ts_period = 1000000, /* calibration period in ts. */
|
||||
.us_per_ts_scale = 1, /* us = (ts * scale) >> shift */
|
||||
.us_per_ts_shift = 0,
|
||||
|
||||
/* give here messages in/out endpoints */
|
||||
.ep_msg_in = PCAN_USBPRO_EP_MSGIN,
|
||||
.ep_msg_out = {PCAN_USBPRO_EP_MSGOUT_0},
|
||||
|
||||
/* size of rx/tx usb buffers */
|
||||
.rx_buffer_size = PCAN_UFD_RX_BUFFER_SIZE,
|
||||
.tx_buffer_size = PCAN_UFD_TX_BUFFER_SIZE,
|
||||
|
||||
/* device callbacks */
|
||||
.intf_probe = pcan_usb_pro_probe, /* same as PCAN-USB Pro */
|
||||
.dev_init = pcan_usb_fd_init,
|
||||
|
||||
.dev_exit = pcan_usb_fd_exit,
|
||||
.dev_free = pcan_usb_fd_free,
|
||||
.dev_set_bus = pcan_usb_fd_set_bus,
|
||||
.dev_set_bittiming = pcan_usb_fd_set_bittiming_slow,
|
||||
.dev_set_data_bittiming = pcan_usb_fd_set_bittiming_fast,
|
||||
.dev_decode_buf = pcan_usb_fd_decode_buf,
|
||||
.dev_start = pcan_usb_fd_start,
|
||||
.dev_stop = pcan_usb_fd_stop,
|
||||
.dev_restart_async = pcan_usb_fd_restart_async,
|
||||
.dev_encode_msg = pcan_usb_fd_encode_msg,
|
||||
|
||||
.do_get_berr_counter = pcan_usb_fd_get_berr_counter,
|
||||
};
|
||||
|
||||
/* describes the PCAN-USB Pro FD adapter */
|
||||
static const struct can_bittiming_const pcan_usb_pro_fd_const = {
|
||||
.name = "pcan_usb_pro_fd",
|
||||
|
|
|
@ -326,6 +326,7 @@ static void b53_get_vlan_entry(struct b53_device *dev, u16 vid,
|
|||
|
||||
static void b53_set_forwarding(struct b53_device *dev, int enable)
|
||||
{
|
||||
struct dsa_switch *ds = dev->ds;
|
||||
u8 mgmt;
|
||||
|
||||
b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
|
||||
|
@ -336,6 +337,15 @@ static void b53_set_forwarding(struct b53_device *dev, int enable)
|
|||
mgmt &= ~SM_SW_FWD_EN;
|
||||
|
||||
b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt);
|
||||
|
||||
/* Include IMP port in dumb forwarding mode when no tagging protocol is
|
||||
* set
|
||||
*/
|
||||
if (ds->ops->get_tag_protocol(ds) == DSA_TAG_PROTO_NONE) {
|
||||
b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, &mgmt);
|
||||
mgmt |= B53_MII_DUMB_FWDG_EN;
|
||||
b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt);
|
||||
}
|
||||
}
|
||||
|
||||
static void b53_enable_vlan(struct b53_device *dev, bool enable)
|
||||
|
@ -598,7 +608,8 @@ static void b53_switch_reset_gpio(struct b53_device *dev)
|
|||
|
||||
static int b53_switch_reset(struct b53_device *dev)
|
||||
{
|
||||
u8 mgmt;
|
||||
unsigned int timeout = 1000;
|
||||
u8 mgmt, reg;
|
||||
|
||||
b53_switch_reset_gpio(dev);
|
||||
|
||||
|
@ -607,6 +618,28 @@ static int b53_switch_reset(struct b53_device *dev)
|
|||
b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, 0x00);
|
||||
}
|
||||
|
||||
/* This is specific to 58xx devices here, do not use is58xx() which
|
||||
* covers the larger Starfigther 2 family, including 7445/7278 which
|
||||
* still use this driver as a library and need to perform the reset
|
||||
* earlier.
|
||||
*/
|
||||
if (dev->chip_id == BCM58XX_DEVICE_ID) {
|
||||
b53_read8(dev, B53_CTRL_PAGE, B53_SOFTRESET, ®);
|
||||
reg |= SW_RST | EN_SW_RST | EN_CH_RST;
|
||||
b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, reg);
|
||||
|
||||
do {
|
||||
b53_read8(dev, B53_CTRL_PAGE, B53_SOFTRESET, ®);
|
||||
if (!(reg & SW_RST))
|
||||
break;
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
} while (timeout-- > 0);
|
||||
|
||||
if (timeout == 0)
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
|
||||
|
||||
if (!(mgmt & SM_SW_FWD_EN)) {
|
||||
|
@ -1731,7 +1764,7 @@ static const struct b53_chip_data b53_switch_chips[] = {
|
|||
.vlans = 4096,
|
||||
.enabled_ports = 0x1ff,
|
||||
.arl_entries = 4,
|
||||
.cpu_port = B53_CPU_PORT_25,
|
||||
.cpu_port = B53_CPU_PORT,
|
||||
.vta_regs = B53_VTA_REGS,
|
||||
.duplex_reg = B53_DUPLEX_STAT_GE,
|
||||
.jumbo_pm_reg = B53_JUMBO_PORT_MASK,
|
||||
|
|
|
@ -104,6 +104,10 @@
|
|||
#define B53_UC_FWD_EN BIT(6)
|
||||
#define B53_MC_FWD_EN BIT(7)
|
||||
|
||||
/* Switch control (8 bit) */
|
||||
#define B53_SWITCH_CTRL 0x22
|
||||
#define B53_MII_DUMB_FWDG_EN BIT(6)
|
||||
|
||||
/* (16 bit) */
|
||||
#define B53_UC_FLOOD_MASK 0x32
|
||||
#define B53_MC_FLOOD_MASK 0x34
|
||||
|
@ -139,6 +143,7 @@
|
|||
/* Software reset register (8 bit) */
|
||||
#define B53_SOFTRESET 0x79
|
||||
#define SW_RST BIT(7)
|
||||
#define EN_CH_RST BIT(6)
|
||||
#define EN_SW_RST BIT(4)
|
||||
|
||||
/* Fast Aging Control register (8 bit) */
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
#define MLX5E_VALID_NUM_MTTS(num_mtts) (MLX5_MTT_OCTW(num_mtts) - 1 <= U16_MAX)
|
||||
|
||||
#define MLX5_UMR_ALIGN (2048)
|
||||
#define MLX5_MPWRQ_SMALL_PACKET_THRESHOLD (128)
|
||||
#define MLX5_MPWRQ_SMALL_PACKET_THRESHOLD (256)
|
||||
|
||||
#define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ (64 * 1024)
|
||||
#define MLX5E_DEFAULT_LRO_TIMEOUT 32
|
||||
|
|
|
@ -564,6 +564,7 @@ int mlx5e_ethtool_get_all_flows(struct mlx5e_priv *priv, struct ethtool_rxnfc *i
|
|||
int idx = 0;
|
||||
int err = 0;
|
||||
|
||||
info->data = MAX_NUM_OF_ETHTOOL_RULES;
|
||||
while ((!err || err == -ENOENT) && idx < info->rule_cnt) {
|
||||
err = mlx5e_ethtool_get_flow(priv, info, location);
|
||||
if (!err)
|
||||
|
|
|
@ -167,7 +167,7 @@ unlock:
|
|||
|
||||
static void mlx5e_update_sw_counters(struct mlx5e_priv *priv)
|
||||
{
|
||||
struct mlx5e_sw_stats *s = &priv->stats.sw;
|
||||
struct mlx5e_sw_stats temp, *s = &temp;
|
||||
struct mlx5e_rq_stats *rq_stats;
|
||||
struct mlx5e_sq_stats *sq_stats;
|
||||
u64 tx_offload_none = 0;
|
||||
|
@ -224,6 +224,7 @@ static void mlx5e_update_sw_counters(struct mlx5e_priv *priv)
|
|||
s->link_down_events_phy = MLX5_GET(ppcnt_reg,
|
||||
priv->stats.pport.phy_counters,
|
||||
counter_set.phys_layer_cntrs.link_down_events);
|
||||
memcpy(&priv->stats.sw, s, sizeof(*s));
|
||||
}
|
||||
|
||||
static void mlx5e_update_vport_counters(struct mlx5e_priv *priv)
|
||||
|
@ -238,7 +239,6 @@ static void mlx5e_update_vport_counters(struct mlx5e_priv *priv)
|
|||
MLX5_SET(query_vport_counter_in, in, op_mod, 0);
|
||||
MLX5_SET(query_vport_counter_in, in, other_vport, 0);
|
||||
|
||||
memset(out, 0, outlen);
|
||||
mlx5_cmd_exec(mdev, in, sizeof(in), out, outlen);
|
||||
}
|
||||
|
||||
|
|
|
@ -710,7 +710,8 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
|
|||
|
||||
if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH) &&
|
||||
rep->vport != FDB_UPLINK_VPORT) {
|
||||
if (min_inline > esw->offloads.inline_mode) {
|
||||
if (esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE &&
|
||||
esw->offloads.inline_mode < min_inline) {
|
||||
netdev_warn(priv->netdev,
|
||||
"Flow is not offloaded due to min inline setting, required %d actual %d\n",
|
||||
min_inline, esw->offloads.inline_mode);
|
||||
|
@ -1140,8 +1141,8 @@ static int mlx5e_route_lookup_ipv6(struct mlx5e_priv *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int gen_vxlan_header_ipv4(struct net_device *out_dev,
|
||||
char buf[],
|
||||
static void gen_vxlan_header_ipv4(struct net_device *out_dev,
|
||||
char buf[], int encap_size,
|
||||
unsigned char h_dest[ETH_ALEN],
|
||||
int ttl,
|
||||
__be32 daddr,
|
||||
|
@ -1149,7 +1150,6 @@ static int gen_vxlan_header_ipv4(struct net_device *out_dev,
|
|||
__be16 udp_dst_port,
|
||||
__be32 vx_vni)
|
||||
{
|
||||
int encap_size = VXLAN_HLEN + sizeof(struct iphdr) + ETH_HLEN;
|
||||
struct ethhdr *eth = (struct ethhdr *)buf;
|
||||
struct iphdr *ip = (struct iphdr *)((char *)eth + sizeof(struct ethhdr));
|
||||
struct udphdr *udp = (struct udphdr *)((char *)ip + sizeof(struct iphdr));
|
||||
|
@ -1172,12 +1172,10 @@ static int gen_vxlan_header_ipv4(struct net_device *out_dev,
|
|||
udp->dest = udp_dst_port;
|
||||
vxh->vx_flags = VXLAN_HF_VNI;
|
||||
vxh->vx_vni = vxlan_vni_field(vx_vni);
|
||||
|
||||
return encap_size;
|
||||
}
|
||||
|
||||
static int gen_vxlan_header_ipv6(struct net_device *out_dev,
|
||||
char buf[],
|
||||
static void gen_vxlan_header_ipv6(struct net_device *out_dev,
|
||||
char buf[], int encap_size,
|
||||
unsigned char h_dest[ETH_ALEN],
|
||||
int ttl,
|
||||
struct in6_addr *daddr,
|
||||
|
@ -1185,7 +1183,6 @@ static int gen_vxlan_header_ipv6(struct net_device *out_dev,
|
|||
__be16 udp_dst_port,
|
||||
__be32 vx_vni)
|
||||
{
|
||||
int encap_size = VXLAN_HLEN + sizeof(struct ipv6hdr) + ETH_HLEN;
|
||||
struct ethhdr *eth = (struct ethhdr *)buf;
|
||||
struct ipv6hdr *ip6h = (struct ipv6hdr *)((char *)eth + sizeof(struct ethhdr));
|
||||
struct udphdr *udp = (struct udphdr *)((char *)ip6h + sizeof(struct ipv6hdr));
|
||||
|
@ -1207,8 +1204,6 @@ static int gen_vxlan_header_ipv6(struct net_device *out_dev,
|
|||
udp->dest = udp_dst_port;
|
||||
vxh->vx_flags = VXLAN_HF_VNI;
|
||||
vxh->vx_vni = vxlan_vni_field(vx_vni);
|
||||
|
||||
return encap_size;
|
||||
}
|
||||
|
||||
static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
|
||||
|
@ -1217,13 +1212,20 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
|
|||
struct net_device **out_dev)
|
||||
{
|
||||
int max_encap_size = MLX5_CAP_ESW(priv->mdev, max_encap_header_size);
|
||||
int ipv4_encap_size = ETH_HLEN + sizeof(struct iphdr) + VXLAN_HLEN;
|
||||
struct ip_tunnel_key *tun_key = &e->tun_info.key;
|
||||
int encap_size, ttl, err;
|
||||
struct neighbour *n = NULL;
|
||||
struct flowi4 fl4 = {};
|
||||
char *encap_header;
|
||||
int ttl, err;
|
||||
|
||||
encap_header = kzalloc(max_encap_size, GFP_KERNEL);
|
||||
if (max_encap_size < ipv4_encap_size) {
|
||||
mlx5_core_warn(priv->mdev, "encap size %d too big, max supported is %d\n",
|
||||
ipv4_encap_size, max_encap_size);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
encap_header = kzalloc(ipv4_encap_size, GFP_KERNEL);
|
||||
if (!encap_header)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1258,8 +1260,8 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
|
|||
|
||||
switch (e->tunnel_type) {
|
||||
case MLX5_HEADER_TYPE_VXLAN:
|
||||
encap_size = gen_vxlan_header_ipv4(*out_dev, encap_header,
|
||||
e->h_dest, ttl,
|
||||
gen_vxlan_header_ipv4(*out_dev, encap_header,
|
||||
ipv4_encap_size, e->h_dest, ttl,
|
||||
fl4.daddr,
|
||||
fl4.saddr, tun_key->tp_dst,
|
||||
tunnel_id_to_key32(tun_key->tun_id));
|
||||
|
@ -1270,7 +1272,7 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
|
|||
}
|
||||
|
||||
err = mlx5_encap_alloc(priv->mdev, e->tunnel_type,
|
||||
encap_size, encap_header, &e->encap_id);
|
||||
ipv4_encap_size, encap_header, &e->encap_id);
|
||||
out:
|
||||
if (err && n)
|
||||
neigh_release(n);
|
||||
|
@ -1285,13 +1287,20 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv,
|
|||
|
||||
{
|
||||
int max_encap_size = MLX5_CAP_ESW(priv->mdev, max_encap_header_size);
|
||||
int ipv6_encap_size = ETH_HLEN + sizeof(struct ipv6hdr) + VXLAN_HLEN;
|
||||
struct ip_tunnel_key *tun_key = &e->tun_info.key;
|
||||
int encap_size, err, ttl = 0;
|
||||
struct neighbour *n = NULL;
|
||||
struct flowi6 fl6 = {};
|
||||
char *encap_header;
|
||||
int err, ttl = 0;
|
||||
|
||||
encap_header = kzalloc(max_encap_size, GFP_KERNEL);
|
||||
if (max_encap_size < ipv6_encap_size) {
|
||||
mlx5_core_warn(priv->mdev, "encap size %d too big, max supported is %d\n",
|
||||
ipv6_encap_size, max_encap_size);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
encap_header = kzalloc(ipv6_encap_size, GFP_KERNEL);
|
||||
if (!encap_header)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -1327,8 +1336,8 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv,
|
|||
|
||||
switch (e->tunnel_type) {
|
||||
case MLX5_HEADER_TYPE_VXLAN:
|
||||
encap_size = gen_vxlan_header_ipv6(*out_dev, encap_header,
|
||||
e->h_dest, ttl,
|
||||
gen_vxlan_header_ipv6(*out_dev, encap_header,
|
||||
ipv6_encap_size, e->h_dest, ttl,
|
||||
&fl6.daddr,
|
||||
&fl6.saddr, tun_key->tp_dst,
|
||||
tunnel_id_to_key32(tun_key->tun_id));
|
||||
|
@ -1339,7 +1348,7 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv,
|
|||
}
|
||||
|
||||
err = mlx5_encap_alloc(priv->mdev, e->tunnel_type,
|
||||
encap_size, encap_header, &e->encap_id);
|
||||
ipv6_encap_size, encap_header, &e->encap_id);
|
||||
out:
|
||||
if (err && n)
|
||||
neigh_release(n);
|
||||
|
|
|
@ -955,8 +955,7 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode)
|
|||
struct mlx5_core_dev *dev = devlink_priv(devlink);
|
||||
struct mlx5_eswitch *esw = dev->priv.eswitch;
|
||||
int num_vports = esw->enabled_vports;
|
||||
int err;
|
||||
int vport;
|
||||
int err, vport;
|
||||
u8 mlx5_mode;
|
||||
|
||||
if (!MLX5_CAP_GEN(dev, vport_group_manager))
|
||||
|
@ -965,9 +964,17 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode)
|
|||
if (esw->mode == SRIOV_NONE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (MLX5_CAP_ETH(dev, wqe_inline_mode) !=
|
||||
MLX5_CAP_INLINE_MODE_VPORT_CONTEXT)
|
||||
switch (MLX5_CAP_ETH(dev, wqe_inline_mode)) {
|
||||
case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
|
||||
if (mode == DEVLINK_ESWITCH_INLINE_MODE_NONE)
|
||||
return 0;
|
||||
/* fall through */
|
||||
case MLX5_CAP_INLINE_MODE_L2:
|
||||
esw_warn(dev, "Inline mode can't be set\n");
|
||||
return -EOPNOTSUPP;
|
||||
case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
|
||||
break;
|
||||
}
|
||||
|
||||
if (esw->offloads.num_flows > 0) {
|
||||
esw_warn(dev, "Can't set inline mode when flows are configured\n");
|
||||
|
@ -1010,18 +1017,14 @@ int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode)
|
|||
if (esw->mode == SRIOV_NONE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (MLX5_CAP_ETH(dev, wqe_inline_mode) !=
|
||||
MLX5_CAP_INLINE_MODE_VPORT_CONTEXT)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);
|
||||
}
|
||||
|
||||
int mlx5_eswitch_inline_mode_get(struct mlx5_eswitch *esw, int nvfs, u8 *mode)
|
||||
{
|
||||
u8 prev_mlx5_mode, mlx5_mode = MLX5_INLINE_MODE_L2;
|
||||
struct mlx5_core_dev *dev = esw->dev;
|
||||
int vport;
|
||||
u8 prev_mlx5_mode, mlx5_mode = MLX5_INLINE_MODE_L2;
|
||||
|
||||
if (!MLX5_CAP_GEN(dev, vport_group_manager))
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -1029,10 +1032,18 @@ int mlx5_eswitch_inline_mode_get(struct mlx5_eswitch *esw, int nvfs, u8 *mode)
|
|||
if (esw->mode == SRIOV_NONE)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (MLX5_CAP_ETH(dev, wqe_inline_mode) !=
|
||||
MLX5_CAP_INLINE_MODE_VPORT_CONTEXT)
|
||||
return -EOPNOTSUPP;
|
||||
switch (MLX5_CAP_ETH(dev, wqe_inline_mode)) {
|
||||
case MLX5_CAP_INLINE_MODE_NOT_REQUIRED:
|
||||
mlx5_mode = MLX5_INLINE_MODE_NONE;
|
||||
goto out;
|
||||
case MLX5_CAP_INLINE_MODE_L2:
|
||||
mlx5_mode = MLX5_INLINE_MODE_L2;
|
||||
goto out;
|
||||
case MLX5_CAP_INLINE_MODE_VPORT_CONTEXT:
|
||||
goto query_vports;
|
||||
}
|
||||
|
||||
query_vports:
|
||||
for (vport = 1; vport <= nvfs; vport++) {
|
||||
mlx5_query_nic_vport_min_inline(dev, vport, &mlx5_mode);
|
||||
if (vport > 1 && prev_mlx5_mode != mlx5_mode)
|
||||
|
@ -1040,6 +1051,7 @@ int mlx5_eswitch_inline_mode_get(struct mlx5_eswitch *esw, int nvfs, u8 *mode)
|
|||
prev_mlx5_mode = mlx5_mode;
|
||||
}
|
||||
|
||||
out:
|
||||
*mode = mlx5_mode;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1029,7 +1029,7 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
|
|||
if (err) {
|
||||
dev_err(&dev->pdev->dev, "Firmware over %d MS in initializing state, aborting\n",
|
||||
FW_INIT_TIMEOUT_MILI);
|
||||
goto out_err;
|
||||
goto err_cmd_cleanup;
|
||||
}
|
||||
|
||||
err = mlx5_core_enable_hca(dev, 0);
|
||||
|
|
|
@ -87,6 +87,7 @@ static void up_rel_func(struct kref *kref)
|
|||
struct mlx5_uars_page *up = container_of(kref, struct mlx5_uars_page, ref_count);
|
||||
|
||||
list_del(&up->list);
|
||||
iounmap(up->map);
|
||||
if (mlx5_cmd_free_uar(up->mdev, up->index))
|
||||
mlx5_core_warn(up->mdev, "failed to free uar index %d\n", up->index);
|
||||
kfree(up->reg_bitmap);
|
||||
|
|
|
@ -64,11 +64,11 @@
|
|||
((u32)(prio_tc_tbl >> ((7 - prio) * 4)) & 0x7)
|
||||
|
||||
static const struct qed_dcbx_app_metadata qed_dcbx_app_update[] = {
|
||||
{DCBX_PROTOCOL_ISCSI, "ISCSI", QED_PCI_DEFAULT},
|
||||
{DCBX_PROTOCOL_FCOE, "FCOE", QED_PCI_DEFAULT},
|
||||
{DCBX_PROTOCOL_ROCE, "ROCE", QED_PCI_DEFAULT},
|
||||
{DCBX_PROTOCOL_ROCE_V2, "ROCE_V2", QED_PCI_DEFAULT},
|
||||
{DCBX_PROTOCOL_ETH, "ETH", QED_PCI_ETH}
|
||||
{DCBX_PROTOCOL_ISCSI, "ISCSI", QED_PCI_ISCSI},
|
||||
{DCBX_PROTOCOL_FCOE, "FCOE", QED_PCI_FCOE},
|
||||
{DCBX_PROTOCOL_ROCE, "ROCE", QED_PCI_ETH_ROCE},
|
||||
{DCBX_PROTOCOL_ROCE_V2, "ROCE_V2", QED_PCI_ETH_ROCE},
|
||||
{DCBX_PROTOCOL_ETH, "ETH", QED_PCI_ETH},
|
||||
};
|
||||
|
||||
static bool qed_dcbx_app_ethtype(u32 app_info_bitmap)
|
||||
|
|
|
@ -1516,11 +1516,12 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
entry = priv->cur_tx[q] % (priv->num_tx_ring[q] * NUM_TX_DESC);
|
||||
priv->tx_skb[q][entry / NUM_TX_DESC] = skb;
|
||||
|
||||
if (skb_put_padto(skb, ETH_ZLEN))
|
||||
goto drop;
|
||||
goto exit;
|
||||
|
||||
entry = priv->cur_tx[q] % (priv->num_tx_ring[q] * NUM_TX_DESC);
|
||||
priv->tx_skb[q][entry / NUM_TX_DESC] = skb;
|
||||
|
||||
buffer = PTR_ALIGN(priv->tx_align[q], DPTR_ALIGN) +
|
||||
entry / NUM_TX_DESC * DPTR_ALIGN;
|
||||
|
|
|
@ -74,7 +74,10 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
|
|||
#define EFX_RXQ_MIN_ENT 128U
|
||||
#define EFX_TXQ_MIN_ENT(efx) (2 * efx_tx_max_skb_descs(efx))
|
||||
|
||||
#define EFX_TXQ_MAX_ENT(efx) (EFX_WORKAROUND_35388(efx) ? \
|
||||
/* All EF10 architecture NICs steal one bit of the DMAQ size for various
|
||||
* other purposes when counting TxQ entries, so we halve the queue size.
|
||||
*/
|
||||
#define EFX_TXQ_MAX_ENT(efx) (EFX_WORKAROUND_EF10(efx) ? \
|
||||
EFX_MAX_DMAQ_SIZE / 2 : EFX_MAX_DMAQ_SIZE)
|
||||
|
||||
static inline bool efx_rss_enabled(struct efx_nic *efx)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
|
||||
#define EFX_WORKAROUND_SIENA(efx) (efx_nic_rev(efx) == EFX_REV_SIENA_A0)
|
||||
#define EFX_WORKAROUND_EF10(efx) (efx_nic_rev(efx) >= EFX_REV_HUNT_A0)
|
||||
#define EFX_WORKAROUND_10G(efx) 1
|
||||
|
||||
/* Bit-bashed I2C reads cause performance drop */
|
||||
|
|
|
@ -1017,8 +1017,8 @@ tc35815_free_queues(struct net_device *dev)
|
|||
BUG_ON(lp->tx_skbs[i].skb != skb);
|
||||
#endif
|
||||
if (skb) {
|
||||
dev_kfree_skb(skb);
|
||||
pci_unmap_single(lp->pci_dev, lp->tx_skbs[i].skb_dma, skb->len, PCI_DMA_TODEVICE);
|
||||
dev_kfree_skb(skb);
|
||||
lp->tx_skbs[i].skb = NULL;
|
||||
lp->tx_skbs[i].skb_dma = 0;
|
||||
}
|
||||
|
|
|
@ -751,7 +751,6 @@ struct netvsc_device {
|
|||
u32 send_section_cnt;
|
||||
u32 send_section_size;
|
||||
unsigned long *send_section_map;
|
||||
int map_words;
|
||||
|
||||
/* Used for NetVSP initialization protocol */
|
||||
struct completion channel_init_wait;
|
||||
|
|
|
@ -249,6 +249,7 @@ static int netvsc_init_buf(struct hv_device *device)
|
|||
struct netvsc_device *net_device;
|
||||
struct nvsp_message *init_packet;
|
||||
struct net_device *ndev;
|
||||
size_t map_words;
|
||||
int node;
|
||||
|
||||
net_device = get_outbound_net_device(device);
|
||||
|
@ -414,11 +415,9 @@ static int netvsc_init_buf(struct hv_device *device)
|
|||
net_device->send_section_size, net_device->send_section_cnt);
|
||||
|
||||
/* Setup state for managing the send buffer. */
|
||||
net_device->map_words = DIV_ROUND_UP(net_device->send_section_cnt,
|
||||
BITS_PER_LONG);
|
||||
map_words = DIV_ROUND_UP(net_device->send_section_cnt, BITS_PER_LONG);
|
||||
|
||||
net_device->send_section_map = kcalloc(net_device->map_words,
|
||||
sizeof(ulong), GFP_KERNEL);
|
||||
net_device->send_section_map = kcalloc(map_words, sizeof(ulong), GFP_KERNEL);
|
||||
if (net_device->send_section_map == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto cleanup;
|
||||
|
@ -698,7 +697,7 @@ static u32 netvsc_get_next_send_section(struct netvsc_device *net_device)
|
|||
unsigned long *map_addr = net_device->send_section_map;
|
||||
unsigned int i;
|
||||
|
||||
for_each_clear_bit(i, map_addr, net_device->map_words) {
|
||||
for_each_clear_bit(i, map_addr, net_device->send_section_cnt) {
|
||||
if (sync_test_and_set_bit(i, map_addr) == 0)
|
||||
return i;
|
||||
}
|
||||
|
|
|
@ -617,7 +617,8 @@ static void macsec_encrypt_done(struct crypto_async_request *base, int err)
|
|||
|
||||
static struct aead_request *macsec_alloc_req(struct crypto_aead *tfm,
|
||||
unsigned char **iv,
|
||||
struct scatterlist **sg)
|
||||
struct scatterlist **sg,
|
||||
int num_frags)
|
||||
{
|
||||
size_t size, iv_offset, sg_offset;
|
||||
struct aead_request *req;
|
||||
|
@ -629,7 +630,7 @@ static struct aead_request *macsec_alloc_req(struct crypto_aead *tfm,
|
|||
|
||||
size = ALIGN(size, __alignof__(struct scatterlist));
|
||||
sg_offset = size;
|
||||
size += sizeof(struct scatterlist) * (MAX_SKB_FRAGS + 1);
|
||||
size += sizeof(struct scatterlist) * num_frags;
|
||||
|
||||
tmp = kmalloc(size, GFP_ATOMIC);
|
||||
if (!tmp)
|
||||
|
@ -649,6 +650,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
|
|||
{
|
||||
int ret;
|
||||
struct scatterlist *sg;
|
||||
struct sk_buff *trailer;
|
||||
unsigned char *iv;
|
||||
struct ethhdr *eth;
|
||||
struct macsec_eth_header *hh;
|
||||
|
@ -723,7 +725,14 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
|
|||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
req = macsec_alloc_req(tx_sa->key.tfm, &iv, &sg);
|
||||
ret = skb_cow_data(skb, 0, &trailer);
|
||||
if (unlikely(ret < 0)) {
|
||||
macsec_txsa_put(tx_sa);
|
||||
kfree_skb(skb);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
req = macsec_alloc_req(tx_sa->key.tfm, &iv, &sg, ret);
|
||||
if (!req) {
|
||||
macsec_txsa_put(tx_sa);
|
||||
kfree_skb(skb);
|
||||
|
@ -732,7 +741,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb,
|
|||
|
||||
macsec_fill_iv(iv, secy->sci, pn);
|
||||
|
||||
sg_init_table(sg, MAX_SKB_FRAGS + 1);
|
||||
sg_init_table(sg, ret);
|
||||
skb_to_sgvec(skb, sg, 0, skb->len);
|
||||
|
||||
if (tx_sc->encrypt) {
|
||||
|
@ -917,6 +926,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
|
|||
{
|
||||
int ret;
|
||||
struct scatterlist *sg;
|
||||
struct sk_buff *trailer;
|
||||
unsigned char *iv;
|
||||
struct aead_request *req;
|
||||
struct macsec_eth_header *hdr;
|
||||
|
@ -927,7 +937,12 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
|
|||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
req = macsec_alloc_req(rx_sa->key.tfm, &iv, &sg);
|
||||
ret = skb_cow_data(skb, 0, &trailer);
|
||||
if (unlikely(ret < 0)) {
|
||||
kfree_skb(skb);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
req = macsec_alloc_req(rx_sa->key.tfm, &iv, &sg, ret);
|
||||
if (!req) {
|
||||
kfree_skb(skb);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
@ -936,7 +951,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb,
|
|||
hdr = (struct macsec_eth_header *)skb->data;
|
||||
macsec_fill_iv(iv, sci, ntohl(hdr->packet_number));
|
||||
|
||||
sg_init_table(sg, MAX_SKB_FRAGS + 1);
|
||||
sg_init_table(sg, ret);
|
||||
skb_to_sgvec(skb, sg, 0, skb->len);
|
||||
|
||||
if (hdr->tci_an & MACSEC_TCI_E) {
|
||||
|
|
|
@ -1139,6 +1139,7 @@ static int macvlan_port_create(struct net_device *dev)
|
|||
static void macvlan_port_destroy(struct net_device *dev)
|
||||
{
|
||||
struct macvlan_port *port = macvlan_port_get_rtnl(dev);
|
||||
struct sk_buff *skb;
|
||||
|
||||
dev->priv_flags &= ~IFF_MACVLAN_PORT;
|
||||
netdev_rx_handler_unregister(dev);
|
||||
|
@ -1147,7 +1148,15 @@ static void macvlan_port_destroy(struct net_device *dev)
|
|||
* but we need to cancel it and purge left skbs if any.
|
||||
*/
|
||||
cancel_work_sync(&port->bc_work);
|
||||
__skb_queue_purge(&port->bc_queue);
|
||||
|
||||
while ((skb = __skb_dequeue(&port->bc_queue))) {
|
||||
const struct macvlan_dev *src = MACVLAN_SKB_CB(skb)->src;
|
||||
|
||||
if (src)
|
||||
dev_put(src->dev);
|
||||
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
kfree(port);
|
||||
}
|
||||
|
|
|
@ -297,17 +297,6 @@ static int kszphy_config_init(struct phy_device *phydev)
|
|||
if (priv->led_mode >= 0)
|
||||
kszphy_setup_led(phydev, type->led_mode_reg, priv->led_mode);
|
||||
|
||||
if (phy_interrupt_is_valid(phydev)) {
|
||||
int ctl = phy_read(phydev, MII_BMCR);
|
||||
|
||||
if (ctl < 0)
|
||||
return ctl;
|
||||
|
||||
ret = phy_write(phydev, MII_BMCR, ctl & ~BMCR_ANENABLE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -622,16 +622,18 @@ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)
|
|||
EXPORT_SYMBOL(phy_mii_ioctl);
|
||||
|
||||
/**
|
||||
* phy_start_aneg - start auto-negotiation for this PHY device
|
||||
* phy_start_aneg_priv - start auto-negotiation for this PHY device
|
||||
* @phydev: the phy_device struct
|
||||
* @sync: indicate whether we should wait for the workqueue cancelation
|
||||
*
|
||||
* Description: Sanitizes the settings (if we're not autonegotiating
|
||||
* them), and then calls the driver's config_aneg function.
|
||||
* If the PHYCONTROL Layer is operating, we change the state to
|
||||
* reflect the beginning of Auto-negotiation or forcing.
|
||||
*/
|
||||
int phy_start_aneg(struct phy_device *phydev)
|
||||
static int phy_start_aneg_priv(struct phy_device *phydev, bool sync)
|
||||
{
|
||||
bool trigger = 0;
|
||||
int err;
|
||||
|
||||
if (!phydev->drv)
|
||||
|
@ -659,10 +661,40 @@ int phy_start_aneg(struct phy_device *phydev)
|
|||
}
|
||||
}
|
||||
|
||||
/* Re-schedule a PHY state machine to check PHY status because
|
||||
* negotiation may already be done and aneg interrupt may not be
|
||||
* generated.
|
||||
*/
|
||||
if (phy_interrupt_is_valid(phydev) && (phydev->state == PHY_AN)) {
|
||||
err = phy_aneg_done(phydev);
|
||||
if (err > 0) {
|
||||
trigger = true;
|
||||
err = 0;
|
||||
}
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&phydev->lock);
|
||||
|
||||
if (trigger)
|
||||
phy_trigger_machine(phydev, sync);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* phy_start_aneg - start auto-negotiation for this PHY device
|
||||
* @phydev: the phy_device struct
|
||||
*
|
||||
* Description: Sanitizes the settings (if we're not autonegotiating
|
||||
* them), and then calls the driver's config_aneg function.
|
||||
* If the PHYCONTROL Layer is operating, we change the state to
|
||||
* reflect the beginning of Auto-negotiation or forcing.
|
||||
*/
|
||||
int phy_start_aneg(struct phy_device *phydev)
|
||||
{
|
||||
return phy_start_aneg_priv(phydev, true);
|
||||
}
|
||||
EXPORT_SYMBOL(phy_start_aneg);
|
||||
|
||||
/**
|
||||
|
@ -690,7 +722,7 @@ void phy_start_machine(struct phy_device *phydev)
|
|||
* state machine runs.
|
||||
*/
|
||||
|
||||
static void phy_trigger_machine(struct phy_device *phydev, bool sync)
|
||||
void phy_trigger_machine(struct phy_device *phydev, bool sync)
|
||||
{
|
||||
if (sync)
|
||||
cancel_delayed_work_sync(&phydev->state_queue);
|
||||
|
@ -1185,7 +1217,7 @@ void phy_state_machine(struct work_struct *work)
|
|||
mutex_unlock(&phydev->lock);
|
||||
|
||||
if (needs_aneg)
|
||||
err = phy_start_aneg(phydev);
|
||||
err = phy_start_aneg_priv(phydev, false);
|
||||
else if (do_suspend)
|
||||
phy_suspend(phydev);
|
||||
|
||||
|
|
|
@ -2361,8 +2361,10 @@ start_again:
|
|||
|
||||
hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags | NLM_F_MULTI,
|
||||
TEAM_CMD_OPTIONS_GET);
|
||||
if (!hdr)
|
||||
if (!hdr) {
|
||||
nlmsg_free(skb);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex))
|
||||
goto nla_put_failure;
|
||||
|
@ -2635,8 +2637,10 @@ start_again:
|
|||
|
||||
hdr = genlmsg_put(skb, portid, seq, &team_nl_family, flags | NLM_F_MULTI,
|
||||
TEAM_CMD_PORT_LIST_GET);
|
||||
if (!hdr)
|
||||
if (!hdr) {
|
||||
nlmsg_free(skb);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex))
|
||||
goto nla_put_failure;
|
||||
|
|
|
@ -369,7 +369,7 @@ config USB_NET_NET1080
|
|||
optionally with LEDs that indicate traffic
|
||||
|
||||
config USB_NET_PLUSB
|
||||
tristate "Prolific PL-2301/2302/25A1 based cables"
|
||||
tristate "Prolific PL-2301/2302/25A1/27A1 based cables"
|
||||
# if the handshake/init/reset problems, from original 'plusb',
|
||||
# are ever resolved ... then remove "experimental"
|
||||
depends on USB_USBNET
|
||||
|
|
|
@ -3279,9 +3279,9 @@ static void __exit hso_exit(void)
|
|||
pr_info("unloaded\n");
|
||||
|
||||
tty_unregister_driver(tty_drv);
|
||||
put_tty_driver(tty_drv);
|
||||
/* deregister the usb driver */
|
||||
usb_deregister(&hso_driver);
|
||||
put_tty_driver(tty_drv);
|
||||
}
|
||||
|
||||
/* Module definitions */
|
||||
|
|
|
@ -102,7 +102,7 @@ static int pl_reset(struct usbnet *dev)
|
|||
}
|
||||
|
||||
static const struct driver_info prolific_info = {
|
||||
.description = "Prolific PL-2301/PL-2302/PL-25A1",
|
||||
.description = "Prolific PL-2301/PL-2302/PL-25A1/PL-27A1",
|
||||
.flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT,
|
||||
/* some PL-2302 versions seem to fail usb_set_interface() */
|
||||
.reset = pl_reset,
|
||||
|
@ -139,6 +139,17 @@ static const struct usb_device_id products [] = {
|
|||
* Host-to-Host Cable
|
||||
*/
|
||||
.driver_info = (unsigned long) &prolific_info,
|
||||
|
||||
},
|
||||
|
||||
/* super speed cables */
|
||||
{
|
||||
USB_DEVICE(0x067b, 0x27a1), /* PL-27A1, no eeprom
|
||||
* also: goobay Active USB 3.0
|
||||
* Data Link,
|
||||
* Unitek Y-3501
|
||||
*/
|
||||
.driver_info = (unsigned long) &prolific_info,
|
||||
},
|
||||
|
||||
{ }, // END
|
||||
|
@ -158,5 +169,5 @@ static struct usb_driver plusb_driver = {
|
|||
module_usb_driver(plusb_driver);
|
||||
|
||||
MODULE_AUTHOR("David Brownell");
|
||||
MODULE_DESCRIPTION("Prolific PL-2301/2302/25A1 USB Host to Host Link Driver");
|
||||
MODULE_DESCRIPTION("Prolific PL-2301/2302/25A1/27A1 USB Host to Host Link Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
|
@ -1061,10 +1061,10 @@ int scsi_init_io(struct scsi_cmnd *cmd)
|
|||
struct scsi_device *sdev = cmd->device;
|
||||
struct request *rq = cmd->request;
|
||||
bool is_mq = (rq->mq_ctx != NULL);
|
||||
int error;
|
||||
int error = BLKPREP_KILL;
|
||||
|
||||
if (WARN_ON_ONCE(!blk_rq_nr_phys_segments(rq)))
|
||||
return -EINVAL;
|
||||
goto err_exit;
|
||||
|
||||
error = scsi_init_sgtable(rq, &cmd->sdb);
|
||||
if (error)
|
||||
|
|
11
fs/stat.c
11
fs/stat.c
|
@ -547,13 +547,13 @@ cp_statx(const struct kstat *stat, struct statx __user *buffer)
|
|||
/**
|
||||
* sys_statx - System call to get enhanced stats
|
||||
* @dfd: Base directory to pathwalk from *or* fd to stat.
|
||||
* @filename: File to stat *or* NULL.
|
||||
* @filename: File to stat or "" with AT_EMPTY_PATH
|
||||
* @flags: AT_* flags to control pathwalk.
|
||||
* @mask: Parts of statx struct actually required.
|
||||
* @buffer: Result buffer.
|
||||
*
|
||||
* Note that if filename is NULL, then it does the equivalent of fstat() using
|
||||
* dfd to indicate the file of interest.
|
||||
* Note that fstat() can be emulated by setting dfd to the fd of interest,
|
||||
* supplying "" as the filename and setting AT_EMPTY_PATH in the flags.
|
||||
*/
|
||||
SYSCALL_DEFINE5(statx,
|
||||
int, dfd, const char __user *, filename, unsigned, flags,
|
||||
|
@ -567,11 +567,10 @@ SYSCALL_DEFINE5(statx,
|
|||
return -EINVAL;
|
||||
if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
|
||||
return -EINVAL;
|
||||
if (!filename)
|
||||
return -EINVAL;
|
||||
|
||||
if (filename)
|
||||
error = vfs_statx(dfd, filename, flags, &stat, mask);
|
||||
else
|
||||
error = vfs_statx_fd(dfd, &stat, mask, flags);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <linux/math64.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/ctype.h>
|
||||
#include "ubifs.h"
|
||||
|
||||
static DEFINE_SPINLOCK(dbg_lock);
|
||||
|
@ -286,8 +287,10 @@ void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode)
|
|||
break;
|
||||
}
|
||||
|
||||
pr_err("\t%d: %s (%s)\n",
|
||||
count++, dent->name, get_dent_type(dent->type));
|
||||
pr_err("\t%d: inode %llu, type %s, len %d\n",
|
||||
count++, (unsigned long long) le64_to_cpu(dent->inum),
|
||||
get_dent_type(dent->type),
|
||||
le16_to_cpu(dent->nlen));
|
||||
|
||||
fname_name(&nm) = dent->name;
|
||||
fname_len(&nm) = le16_to_cpu(dent->nlen);
|
||||
|
@ -464,7 +467,8 @@ void ubifs_dump_node(const struct ubifs_info *c, const void *node)
|
|||
pr_err("(bad name length, not printing, bad or corrupted node)");
|
||||
else {
|
||||
for (i = 0; i < nlen && dent->name[i]; i++)
|
||||
pr_cont("%c", dent->name[i]);
|
||||
pr_cont("%c", isprint(dent->name[i]) ?
|
||||
dent->name[i] : '?');
|
||||
}
|
||||
pr_cont("\n");
|
||||
|
||||
|
|
|
@ -606,8 +606,8 @@ static int ubifs_readdir(struct file *file, struct dir_context *ctx)
|
|||
}
|
||||
|
||||
while (1) {
|
||||
dbg_gen("feed '%s', ino %llu, new f_pos %#x",
|
||||
dent->name, (unsigned long long)le64_to_cpu(dent->inum),
|
||||
dbg_gen("ino %llu, new f_pos %#x",
|
||||
(unsigned long long)le64_to_cpu(dent->inum),
|
||||
key_hash_flash(c, &dent->key));
|
||||
ubifs_assert(le64_to_cpu(dent->ch.sqnum) >
|
||||
ubifs_inode(dir)->creat_sqnum);
|
||||
|
@ -748,6 +748,11 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
|
|||
goto out_fname;
|
||||
|
||||
lock_2_inodes(dir, inode);
|
||||
|
||||
/* Handle O_TMPFILE corner case, it is allowed to link a O_TMPFILE. */
|
||||
if (inode->i_nlink == 0)
|
||||
ubifs_delete_orphan(c, inode->i_ino);
|
||||
|
||||
inc_nlink(inode);
|
||||
ihold(inode);
|
||||
inode->i_ctime = ubifs_current_time(inode);
|
||||
|
@ -768,6 +773,8 @@ out_cancel:
|
|||
dir->i_size -= sz_change;
|
||||
dir_ui->ui_size = dir->i_size;
|
||||
drop_nlink(inode);
|
||||
if (inode->i_nlink == 0)
|
||||
ubifs_add_orphan(c, inode->i_ino);
|
||||
unlock_2_inodes(dir, inode);
|
||||
ubifs_release_budget(c, &req);
|
||||
iput(inode);
|
||||
|
@ -1068,8 +1075,10 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry,
|
|||
}
|
||||
|
||||
err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
|
||||
if (err)
|
||||
if (err) {
|
||||
kfree(dev);
|
||||
goto out_budg;
|
||||
}
|
||||
|
||||
sz_change = CALC_DENT_SIZE(fname_len(&nm));
|
||||
|
||||
|
@ -1316,9 +1325,6 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
|
|||
unsigned int uninitialized_var(saved_nlink);
|
||||
struct fscrypt_name old_nm, new_nm;
|
||||
|
||||
if (flags & ~RENAME_NOREPLACE)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Budget request settings: deletion direntry, new direntry, removing
|
||||
* the old inode, and changing old and new parent directory inodes.
|
||||
|
|
|
@ -841,6 +841,7 @@ void phy_change_work(struct work_struct *work);
|
|||
void phy_mac_interrupt(struct phy_device *phydev, int new_link);
|
||||
void phy_start_machine(struct phy_device *phydev);
|
||||
void phy_stop_machine(struct phy_device *phydev);
|
||||
void phy_trigger_machine(struct phy_device *phydev, bool sync);
|
||||
int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
|
||||
int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
|
||||
int phy_ethtool_ksettings_get(struct phy_device *phydev,
|
||||
|
|
|
@ -98,7 +98,7 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
|
|||
int ncpus, v, vecs_to_assign, vecs_per_node;
|
||||
|
||||
/* Spread the vectors per node */
|
||||
vecs_per_node = (affv - curvec) / nodes;
|
||||
vecs_per_node = (affv - (curvec - affd->pre_vectors)) / nodes;
|
||||
|
||||
/* Get the cpus on this node which are in the mask */
|
||||
cpumask_and(nmsk, cpu_online_mask, cpumask_of_node(n));
|
||||
|
|
|
@ -123,6 +123,7 @@ static void br_dev_uninit(struct net_device *dev)
|
|||
{
|
||||
struct net_bridge *br = netdev_priv(dev);
|
||||
|
||||
br_multicast_dev_del(br);
|
||||
br_multicast_uninit_stats(br);
|
||||
br_vlan_flush(br);
|
||||
free_percpu(br->stats);
|
||||
|
|
|
@ -312,7 +312,6 @@ void br_dev_delete(struct net_device *dev, struct list_head *head)
|
|||
|
||||
br_fdb_delete_by_port(br, NULL, 0, 1);
|
||||
|
||||
br_multicast_dev_del(br);
|
||||
cancel_delayed_work_sync(&br->gc_work);
|
||||
|
||||
br_sysfs_delbr(br->dev);
|
||||
|
|
|
@ -2451,6 +2451,9 @@ void __dev_kfree_skb_irq(struct sk_buff *skb, enum skb_free_reason reason)
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (unlikely(!skb))
|
||||
return;
|
||||
|
||||
if (likely(atomic_read(&skb->users) == 1)) {
|
||||
smp_rmb();
|
||||
atomic_set(&skb->users, 0);
|
||||
|
|
|
@ -2403,7 +2403,8 @@ struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
|
|||
}
|
||||
|
||||
/* L3 master device is the loopback for that domain */
|
||||
dev_out = l3mdev_master_dev_rcu(dev_out) ? : net->loopback_dev;
|
||||
dev_out = l3mdev_master_dev_rcu(FIB_RES_DEV(res)) ? :
|
||||
net->loopback_dev;
|
||||
fl4->flowi4_oif = dev_out->ifindex;
|
||||
flags |= RTCF_LOCAL;
|
||||
goto make_route;
|
||||
|
|
|
@ -168,12 +168,8 @@ void tcp_assign_congestion_control(struct sock *sk)
|
|||
}
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
|
||||
/* Clear out private data before diag gets it and
|
||||
* the ca has not been initialized.
|
||||
*/
|
||||
if (ca->get_info)
|
||||
memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
|
||||
|
||||
if (ca->flags & TCP_CONG_NEEDS_ECN)
|
||||
INET_ECN_xmit(sk);
|
||||
else
|
||||
|
@ -200,12 +196,11 @@ static void tcp_reinit_congestion_control(struct sock *sk,
|
|||
tcp_cleanup_congestion_control(sk);
|
||||
icsk->icsk_ca_ops = ca;
|
||||
icsk->icsk_ca_setsockopt = 1;
|
||||
|
||||
if (sk->sk_state != TCP_CLOSE) {
|
||||
memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv));
|
||||
|
||||
if (sk->sk_state != TCP_CLOSE)
|
||||
tcp_init_congestion_control(sk);
|
||||
}
|
||||
}
|
||||
|
||||
/* Manage refcounts on socket close. */
|
||||
void tcp_cleanup_congestion_control(struct sock *sk)
|
||||
|
|
|
@ -29,6 +29,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
|
|||
u16 mac_len = skb->mac_len;
|
||||
int udp_offset, outer_hlen;
|
||||
__wsum partial;
|
||||
bool need_ipsec;
|
||||
|
||||
if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
|
||||
goto out;
|
||||
|
@ -62,8 +63,10 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
|
|||
|
||||
ufo = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP);
|
||||
|
||||
need_ipsec = skb_dst(skb) && dst_xfrm(skb_dst(skb));
|
||||
/* Try to offload checksum if possible */
|
||||
offload_csum = !!(need_csum &&
|
||||
!need_ipsec &&
|
||||
(skb->dev->features &
|
||||
(is_ipv6 ? (NETIF_F_HW_CSUM | NETIF_F_IPV6_CSUM) :
|
||||
(NETIF_F_HW_CSUM | NETIF_F_IP_CSUM))));
|
||||
|
|
|
@ -3303,14 +3303,24 @@ static void addrconf_gre_config(struct net_device *dev)
|
|||
static int fixup_permanent_addr(struct inet6_dev *idev,
|
||||
struct inet6_ifaddr *ifp)
|
||||
{
|
||||
if (!ifp->rt) {
|
||||
struct rt6_info *rt;
|
||||
/* rt6i_ref == 0 means the host route was removed from the
|
||||
* FIB, for example, if 'lo' device is taken down. In that
|
||||
* case regenerate the host route.
|
||||
*/
|
||||
if (!ifp->rt || !atomic_read(&ifp->rt->rt6i_ref)) {
|
||||
struct rt6_info *rt, *prev;
|
||||
|
||||
rt = addrconf_dst_alloc(idev, &ifp->addr, false);
|
||||
if (unlikely(IS_ERR(rt)))
|
||||
return PTR_ERR(rt);
|
||||
|
||||
/* ifp->rt can be accessed outside of rtnl */
|
||||
spin_lock(&ifp->lock);
|
||||
prev = ifp->rt;
|
||||
ifp->rt = rt;
|
||||
spin_unlock(&ifp->lock);
|
||||
|
||||
ip6_rt_put(prev);
|
||||
}
|
||||
|
||||
if (!(ifp->flags & IFA_F_NOPREFIXROUTE)) {
|
||||
|
|
|
@ -933,8 +933,6 @@ static int __init inet6_init(void)
|
|||
if (err)
|
||||
goto igmp_fail;
|
||||
|
||||
ipv6_stub = &ipv6_stub_impl;
|
||||
|
||||
err = ipv6_netfilter_init();
|
||||
if (err)
|
||||
goto netfilter_fail;
|
||||
|
@ -1014,6 +1012,10 @@ static int __init inet6_init(void)
|
|||
if (err)
|
||||
goto sysctl_fail;
|
||||
#endif
|
||||
|
||||
/* ensure that ipv6 stubs are visible only after ipv6 is ready */
|
||||
wmb();
|
||||
ipv6_stub = &ipv6_stub_impl;
|
||||
out:
|
||||
return err;
|
||||
|
||||
|
|
|
@ -909,6 +909,8 @@ static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,
|
|||
{
|
||||
switch (opt->type) {
|
||||
case IPV6_SRCRT_TYPE_0:
|
||||
case IPV6_SRCRT_STRICT:
|
||||
case IPV6_SRCRT_TYPE_2:
|
||||
ipv6_push_rthdr0(skb, proto, opt, addr_p, saddr);
|
||||
break;
|
||||
case IPV6_SRCRT_TYPE_4:
|
||||
|
@ -1163,6 +1165,8 @@ struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
|
|||
|
||||
switch (opt->srcrt->type) {
|
||||
case IPV6_SRCRT_TYPE_0:
|
||||
case IPV6_SRCRT_STRICT:
|
||||
case IPV6_SRCRT_TYPE_2:
|
||||
fl6->daddr = *((struct rt0_hdr *)opt->srcrt)->addr;
|
||||
break;
|
||||
case IPV6_SRCRT_TYPE_4:
|
||||
|
|
|
@ -1037,7 +1037,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
|
|||
struct ip6_tnl *t = netdev_priv(dev);
|
||||
struct net *net = t->net;
|
||||
struct net_device_stats *stats = &t->dev->stats;
|
||||
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
|
||||
struct ipv6hdr *ipv6h;
|
||||
struct ipv6_tel_txoption opt;
|
||||
struct dst_entry *dst = NULL, *ndst = NULL;
|
||||
struct net_device *tdev;
|
||||
|
@ -1057,6 +1057,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
|
|||
|
||||
/* NBMA tunnel */
|
||||
if (ipv6_addr_any(&t->parms.raddr)) {
|
||||
if (skb->protocol == htons(ETH_P_IPV6)) {
|
||||
struct in6_addr *addr6;
|
||||
struct neighbour *neigh;
|
||||
int addr_type;
|
||||
|
@ -1077,6 +1078,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,
|
|||
|
||||
memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
|
||||
neigh_release(neigh);
|
||||
}
|
||||
} else if (!(t->parms.flags &
|
||||
(IP6_TNL_F_USE_ORIG_TCLASS | IP6_TNL_F_USE_ORIG_FWMARK))) {
|
||||
/* enable the cache only only if the routing decision does
|
||||
|
|
|
@ -1753,7 +1753,8 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event,
|
|||
idev = in6_dev_get(dev);
|
||||
if (!idev)
|
||||
break;
|
||||
if (idev->cnf.ndisc_notify)
|
||||
if (idev->cnf.ndisc_notify ||
|
||||
net->ipv6.devconf_all->ndisc_notify)
|
||||
ndisc_send_unsol_na(dev);
|
||||
in6_dev_put(idev);
|
||||
break;
|
||||
|
|
|
@ -1178,8 +1178,7 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
|
|||
spin_lock_bh(&sk->sk_receive_queue.lock);
|
||||
skb = skb_peek(&sk->sk_receive_queue);
|
||||
if (skb)
|
||||
amount = skb_tail_pointer(skb) -
|
||||
skb_transport_header(skb);
|
||||
amount = skb->len;
|
||||
spin_unlock_bh(&sk->sk_receive_queue.lock);
|
||||
return put_user(amount, (int __user *)arg);
|
||||
}
|
||||
|
|
|
@ -3880,6 +3880,8 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
|
|||
case PACKET_HDRLEN:
|
||||
if (len > sizeof(int))
|
||||
len = sizeof(int);
|
||||
if (len < sizeof(int))
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&val, optval, len))
|
||||
return -EFAULT;
|
||||
switch (val) {
|
||||
|
|
|
@ -1083,7 +1083,7 @@ static int __tipc_sendstream(struct socket *sock, struct msghdr *m, size_t dlen)
|
|||
}
|
||||
} while (sent < dlen && !rc);
|
||||
|
||||
return rc ? rc : sent;
|
||||
return sent ? sent : rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1484,7 +1484,7 @@ restart:
|
|||
if (unlikely(flags & MSG_PEEK))
|
||||
goto exit;
|
||||
|
||||
tsk->rcv_unacked += tsk_inc(tsk, hlen + sz);
|
||||
tsk->rcv_unacked += tsk_inc(tsk, hlen + msg_data_sz(msg));
|
||||
if (unlikely(tsk->rcv_unacked >= (tsk->rcv_win / 4)))
|
||||
tipc_sk_send_ack(tsk);
|
||||
tsk_advance_rx_queue(sk);
|
||||
|
|
|
@ -28,19 +28,16 @@
|
|||
/* wait until all locks are released */
|
||||
void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line)
|
||||
{
|
||||
int max_count = 5 * HZ;
|
||||
int warn_count = 5 * HZ;
|
||||
|
||||
if (atomic_read(lockp) < 0) {
|
||||
pr_warn("ALSA: seq_lock: lock trouble [counter = %d] in %s:%d\n", atomic_read(lockp), file, line);
|
||||
return;
|
||||
}
|
||||
while (atomic_read(lockp) > 0) {
|
||||
if (max_count == 0) {
|
||||
pr_warn("ALSA: seq_lock: timeout [%d left] in %s:%d\n", atomic_read(lockp), file, line);
|
||||
break;
|
||||
}
|
||||
if (warn_count-- == 0)
|
||||
pr_warn("ALSA: seq_lock: waiting [%d left] in %s:%d\n", atomic_read(lockp), file, line);
|
||||
schedule_timeout_uninterruptible(1);
|
||||
max_count--;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ struct snd_fw_async_midi_port {
|
|||
|
||||
struct snd_rawmidi_substream *substream;
|
||||
snd_fw_async_midi_port_fill fill;
|
||||
unsigned int consume_bytes;
|
||||
int consume_bytes;
|
||||
};
|
||||
|
||||
int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port,
|
||||
|
|
|
@ -227,11 +227,11 @@ static void do_registration(struct work_struct *work)
|
|||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = detect_quirks(oxfw);
|
||||
err = snd_oxfw_stream_discover(oxfw);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
err = snd_oxfw_stream_discover(oxfw);
|
||||
err = detect_quirks(oxfw);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
|
||||
|
|
|
@ -621,7 +621,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
|
|||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.platform_name = "sst-mfld-platform",
|
||||
.ignore_suspend = 1,
|
||||
.nonatomic = true,
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
|
@ -634,7 +634,6 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
|
|||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.platform_name = "sst-mfld-platform",
|
||||
.ignore_suspend = 1,
|
||||
.nonatomic = true,
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
|
@ -661,6 +660,7 @@ static struct snd_soc_dai_link byt_rt5640_dais[] = {
|
|||
| SND_SOC_DAIFMT_CBS_CFS,
|
||||
.be_hw_params_fixup = byt_rt5640_codec_fixup,
|
||||
.ignore_suspend = 1,
|
||||
.nonatomic = true,
|
||||
.dpcm_playback = 1,
|
||||
.dpcm_capture = 1,
|
||||
.init = byt_rt5640_init,
|
||||
|
|
|
@ -235,7 +235,6 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = {
|
|||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.platform_name = "sst-mfld-platform",
|
||||
.ignore_suspend = 1,
|
||||
.nonatomic = true,
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
|
@ -249,7 +248,6 @@ static struct snd_soc_dai_link byt_rt5651_dais[] = {
|
|||
.codec_dai_name = "snd-soc-dummy-dai",
|
||||
.codec_name = "snd-soc-dummy",
|
||||
.platform_name = "sst-mfld-platform",
|
||||
.ignore_suspend = 1,
|
||||
.nonatomic = true,
|
||||
.dynamic = 1,
|
||||
.dpcm_playback = 1,
|
||||
|
|
|
@ -933,6 +933,7 @@ static int soc_tplg_denum_create_texts(struct soc_enum *se,
|
|||
}
|
||||
}
|
||||
|
||||
se->texts = (const char * const *)se->dobj.control.dtexts;
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
|
|
@ -1299,6 +1299,7 @@ struct uniperif {
|
|||
int ver; /* IP version, used by register access macros */
|
||||
struct regmap_field *clk_sel;
|
||||
struct regmap_field *valid_sel;
|
||||
spinlock_t irq_lock; /* use to prevent race condition with IRQ */
|
||||
|
||||
/* capabilities */
|
||||
const struct snd_pcm_hardware *hw;
|
||||
|
|
|
@ -65,10 +65,13 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
|
|||
unsigned int status;
|
||||
unsigned int tmp;
|
||||
|
||||
if (player->state == UNIPERIF_STATE_STOPPED) {
|
||||
/* Unexpected IRQ: do nothing */
|
||||
return IRQ_NONE;
|
||||
}
|
||||
spin_lock(&player->irq_lock);
|
||||
if (!player->substream)
|
||||
goto irq_spin_unlock;
|
||||
|
||||
snd_pcm_stream_lock(player->substream);
|
||||
if (player->state == UNIPERIF_STATE_STOPPED)
|
||||
goto stream_unlock;
|
||||
|
||||
/* Get interrupt status & clear them immediately */
|
||||
status = GET_UNIPERIF_ITS(player);
|
||||
|
@ -88,9 +91,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
|
|||
SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player);
|
||||
|
||||
/* Stop the player */
|
||||
snd_pcm_stream_lock(player->substream);
|
||||
snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
|
||||
snd_pcm_stream_unlock(player->substream);
|
||||
}
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
|
@ -104,9 +105,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
|
|||
SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player);
|
||||
|
||||
/* Stop the player */
|
||||
snd_pcm_stream_lock(player->substream);
|
||||
snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
|
||||
snd_pcm_stream_unlock(player->substream);
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
@ -116,7 +115,8 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
|
|||
if (!player->underflow_enabled) {
|
||||
dev_err(player->dev,
|
||||
"unexpected Underflow recovering\n");
|
||||
return -EPERM;
|
||||
ret = -EPERM;
|
||||
goto stream_unlock;
|
||||
}
|
||||
/* Read the underflow recovery duration */
|
||||
tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player);
|
||||
|
@ -138,13 +138,16 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
|
|||
dev_err(player->dev, "Underflow recovery failed\n");
|
||||
|
||||
/* Stop the player */
|
||||
snd_pcm_stream_lock(player->substream);
|
||||
snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
|
||||
snd_pcm_stream_unlock(player->substream);
|
||||
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
stream_unlock:
|
||||
snd_pcm_stream_unlock(player->substream);
|
||||
irq_spin_unlock:
|
||||
spin_unlock(&player->irq_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -588,6 +591,7 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol,
|
|||
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||
struct uniperif *player = priv->dai_data.uni;
|
||||
struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958;
|
||||
unsigned long flags;
|
||||
|
||||
mutex_lock(&player->ctrl_lock);
|
||||
iec958->status[0] = ucontrol->value.iec958.status[0];
|
||||
|
@ -596,12 +600,14 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol,
|
|||
iec958->status[3] = ucontrol->value.iec958.status[3];
|
||||
mutex_unlock(&player->ctrl_lock);
|
||||
|
||||
spin_lock_irqsave(&player->irq_lock, flags);
|
||||
if (player->substream && player->substream->runtime)
|
||||
uni_player_set_channel_status(player,
|
||||
player->substream->runtime);
|
||||
else
|
||||
uni_player_set_channel_status(player, NULL);
|
||||
|
||||
spin_unlock_irqrestore(&player->irq_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -686,9 +692,12 @@ static int uni_player_startup(struct snd_pcm_substream *substream,
|
|||
{
|
||||
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||
struct uniperif *player = priv->dai_data.uni;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&player->irq_lock, flags);
|
||||
player->substream = substream;
|
||||
spin_unlock_irqrestore(&player->irq_lock, flags);
|
||||
|
||||
player->clk_adj = 0;
|
||||
|
||||
|
@ -986,12 +995,15 @@ static void uni_player_shutdown(struct snd_pcm_substream *substream,
|
|||
{
|
||||
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||
struct uniperif *player = priv->dai_data.uni;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&player->irq_lock, flags);
|
||||
if (player->state != UNIPERIF_STATE_STOPPED)
|
||||
/* Stop the player */
|
||||
uni_player_stop(player);
|
||||
|
||||
player->substream = NULL;
|
||||
spin_unlock_irqrestore(&player->irq_lock, flags);
|
||||
}
|
||||
|
||||
static int uni_player_parse_dt_audio_glue(struct platform_device *pdev,
|
||||
|
@ -1096,6 +1108,7 @@ int uni_player_init(struct platform_device *pdev,
|
|||
}
|
||||
|
||||
mutex_init(&player->ctrl_lock);
|
||||
spin_lock_init(&player->irq_lock);
|
||||
|
||||
/* Ensure that disabled by default */
|
||||
SET_UNIPERIF_CONFIG_BACK_STALL_REQ_DISABLE(player);
|
||||
|
|
|
@ -46,10 +46,15 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
|
|||
struct uniperif *reader = dev_id;
|
||||
unsigned int status;
|
||||
|
||||
spin_lock(&reader->irq_lock);
|
||||
if (!reader->substream)
|
||||
goto irq_spin_unlock;
|
||||
|
||||
snd_pcm_stream_lock(reader->substream);
|
||||
if (reader->state == UNIPERIF_STATE_STOPPED) {
|
||||
/* Unexpected IRQ: do nothing */
|
||||
dev_warn(reader->dev, "unexpected IRQ\n");
|
||||
return IRQ_HANDLED;
|
||||
goto stream_unlock;
|
||||
}
|
||||
|
||||
/* Get interrupt status & clear them immediately */
|
||||
|
@ -60,13 +65,16 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
|
|||
if (unlikely(status & UNIPERIF_ITS_FIFO_ERROR_MASK(reader))) {
|
||||
dev_err(reader->dev, "FIFO error detected\n");
|
||||
|
||||
snd_pcm_stream_lock(reader->substream);
|
||||
snd_pcm_stop(reader->substream, SNDRV_PCM_STATE_XRUN);
|
||||
snd_pcm_stream_unlock(reader->substream);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
stream_unlock:
|
||||
snd_pcm_stream_unlock(reader->substream);
|
||||
irq_spin_unlock:
|
||||
spin_unlock(&reader->irq_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -347,9 +355,12 @@ static int uni_reader_startup(struct snd_pcm_substream *substream,
|
|||
{
|
||||
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||
struct uniperif *reader = priv->dai_data.uni;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&reader->irq_lock, flags);
|
||||
reader->substream = substream;
|
||||
spin_unlock_irqrestore(&reader->irq_lock, flags);
|
||||
|
||||
if (!UNIPERIF_TYPE_IS_TDM(reader))
|
||||
return 0;
|
||||
|
@ -375,12 +386,15 @@ static void uni_reader_shutdown(struct snd_pcm_substream *substream,
|
|||
{
|
||||
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
|
||||
struct uniperif *reader = priv->dai_data.uni;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&reader->irq_lock, flags);
|
||||
if (reader->state != UNIPERIF_STATE_STOPPED) {
|
||||
/* Stop the reader */
|
||||
uni_reader_stop(reader);
|
||||
}
|
||||
reader->substream = NULL;
|
||||
spin_unlock_irqrestore(&reader->irq_lock, flags);
|
||||
}
|
||||
|
||||
static const struct snd_soc_dai_ops uni_reader_dai_ops = {
|
||||
|
@ -415,6 +429,8 @@ int uni_reader_init(struct platform_device *pdev,
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
spin_lock_init(&reader->irq_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(uni_reader_init);
|
||||
|
|
Loading…
Reference in New Issue