1
0
Fork 0

This is the 5.4.90 stable release

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEZH8oZUiU471FcZm+ONu9yGCSaT4FAmAENzgACgkQONu9yGCS
 aT7khA//eTBSPP1vAJIqph0YgQbgCCzvzQTj5enM6F1cCZqVha8s0ZjY4fl9Mkky
 MTVmQdGEem4MoqypzFgAQPQn8KpoM//sQue+b9evny3wU/cmgry5Hs7H3F1/Y7Yv
 q27Q5jzRTmvcy4Up21FhpFE58FXCXiO5H58FrtKEuJtoCxk+akyGuF8Z0UH3Rvp/
 FTKjAKnfzQ9b3MjBJY16W3EqZnpLB+sFMhimS+QyHAr4biTXgIhM/ZebyKxYOGDw
 fq9MX5XCSM5Aka9RfWIGl8FF5y1IICkBQ0Il+xI7zsQwONFD9UIMhAcTE2LxybQT
 YsV/GJ7r/nZWSTcup+vD+tTNceXQoBY2EDGIKeX3rNme8cLWWJeDbTc7KbIkIi35
 ctRFeEcUiFMoQEhIXyi7c8DcOU4xjmTUXtigjhcLLzAODuOBriWbIsM81RuLwNGC
 i/jLYEWhQ+tXozLsmb1/7fL8mvAlZfD3Vwkm4aTSSPul1i52tqBnRZBSut0+KRMa
 +SOpxytl+H5tFV6Z3bI0lrtJ0xnKdr0oJj367JsxIG1yeOpkqe8CEFWW+14TsjqV
 R1ETqDTtqi8YTGfIgp4Q3EUe9LdoJwUQFKh1lv0SMKYac6vtz/C+MxziJXHPValE
 dNK3MocE1zpfMgnZpHP/IwbLOeiWfNl+ZL/wpD73EUr1PvUiRvQ=
 =4Noe
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEdQaENiSDAlGTDEbB7G51OISzHs0FAmAEuNMACgkQ7G51OISz
 Hs0XMw//UEpM14N+UcLb3yTHYyr/vksat/Rz0fT3R2bBMgmlxmTsUgDv5OZLiXlO
 mWMbN2k1kDvKl4EuiJfmOK+5FICoFkdBpXugomjLFI0BeJukywdz6l4omDTqHkE7
 dK3ntPdpTVFP0zJI7lMOk5DsKW/GprOOeFaw0PEO8255yoo59l8Ayxi3k6rWU3f+
 a1laEtpwyitIFBAW4KCOT50/f1vpVnqlhB+2fRpFUwGBceuv42p0fBTZ7vi98Mmu
 KtKRVHnPKQIROx07oFUlxeeNsyhRacJXXoSvyyfBGc9pf3vs8nCGXhITXSVuQHsh
 EZh4Ur007Q40sDDaH7FkC0jxqGOc8A/oCAwF9WCVoWy0yx0t/CKpMcgsoBl2H3MC
 v0/DusVQQod1ohcH0lG6fxM3roKkbbOF2HelRDnz+n7mw9biboKKL3Q+i2CNUmam
 KutJixqfW2NsfZo87ObSmn2iv7xcDAZWLO4axMgAfygTdoL39v/Ws7ZJ3IEujh/a
 zKAx9Mb4/TAv1OlmI+3wpsq+efSZ90fUAXnW+ymJazh+sJj/Do+61RcgoyDrG6U+
 SGfIa/rbrnG44jywPisAdLMjtg4YBC3ccSh0oqdbO3lrXyT+afL7XLuH8BfT/rYY
 e33E+xb4qOc4/bfWCFt/rVyZR4PoOo4TJHyoFugQ+N32U7V921c=
 =UIOp
 -----END PGP SIGNATURE-----

Merge tag 'v5.4.90' into 5.4-2.2.x-imx

This is the 5.4.90 stable release

Signed-off-by: Andrey Zhizhikin <andrey.zhizhikin@leica-geosystems.com>
5.4-rM2-2.2.x-imx-squashed
Andrey Zhizhikin 2021-01-17 22:23:12 +00:00
commit 873af59ba2
58 changed files with 453 additions and 238 deletions

View File

@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
VERSION = 5 VERSION = 5
PATCHLEVEL = 4 PATCHLEVEL = 4
SUBLEVEL = 89 SUBLEVEL = 90
EXTRAVERSION = EXTRAVERSION =
NAME = Kleptomaniac Octopus NAME = Kleptomaniac Octopus

View File

@ -234,10 +234,12 @@ static int _omap_device_notifier_call(struct notifier_block *nb,
break; break;
case BUS_NOTIFY_BIND_DRIVER: case BUS_NOTIFY_BIND_DRIVER:
od = to_omap_device(pdev); od = to_omap_device(pdev);
if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED) && if (od) {
pm_runtime_status_suspended(dev)) {
od->_driver_status = BUS_NOTIFY_BIND_DRIVER; od->_driver_status = BUS_NOTIFY_BIND_DRIVER;
pm_runtime_set_active(dev); if (od->_state == OMAP_DEVICE_STATE_ENABLED &&
pm_runtime_status_suspended(dev)) {
pm_runtime_set_active(dev);
}
} }
break; break;
case BUS_NOTIFY_ADD_DEVICE: case BUS_NOTIFY_ADD_DEVICE:

View File

@ -625,6 +625,10 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
{ {
u64 pmcr, val; u64 pmcr, val;
/* No PMU available, PMCR_EL0 may UNDEF... */
if (!kvm_arm_support_pmu_v3())
return;
pmcr = read_sysreg(pmcr_el0); pmcr = read_sysreg(pmcr_el0);
/* /*
* Writable bits of PMCR_EL0 (ARMV8_PMU_PMCR_MASK) are reset to UNKNOWN * Writable bits of PMCR_EL0 (ARMV8_PMU_PMCR_MASK) are reset to UNKNOWN

View File

@ -869,9 +869,10 @@ GLOBAL(__begin_SYSENTER_singlestep_region)
* Xen doesn't set %esp to be precisely what the normal SYSENTER * Xen doesn't set %esp to be precisely what the normal SYSENTER
* entry point expects, so fix it up before using the normal path. * entry point expects, so fix it up before using the normal path.
*/ */
ENTRY(xen_sysenter_target) SYM_CODE_START(xen_sysenter_target)
addl $5*4, %esp /* remove xen-provided frame */ addl $5*4, %esp /* remove xen-provided frame */
jmp .Lsysenter_past_esp jmp .Lsysenter_past_esp
SYM_CODE_END(xen_sysenter_target)
#endif #endif
/* /*

View File

@ -9,8 +9,7 @@
.code32 .code32
ALIGN ALIGN
ENTRY(wakeup_pmode_return) SYM_CODE_START(wakeup_pmode_return)
wakeup_pmode_return:
movw $__KERNEL_DS, %ax movw $__KERNEL_DS, %ax
movw %ax, %ss movw %ax, %ss
movw %ax, %fs movw %ax, %fs
@ -39,6 +38,7 @@ wakeup_pmode_return:
# jump to place where we left off # jump to place where we left off
movl saved_eip, %eax movl saved_eip, %eax
jmp *%eax jmp *%eax
SYM_CODE_END(wakeup_pmode_return)
bogus_magic: bogus_magic:
jmp bogus_magic jmp bogus_magic
@ -72,7 +72,7 @@ restore_registers:
popfl popfl
ret ret
ENTRY(do_suspend_lowlevel) SYM_CODE_START(do_suspend_lowlevel)
call save_processor_state call save_processor_state
call save_registers call save_registers
pushl $3 pushl $3
@ -87,6 +87,7 @@ ret_point:
call restore_registers call restore_registers
call restore_processor_state call restore_processor_state
ret ret
SYM_CODE_END(do_suspend_lowlevel)
.data .data
ALIGN ALIGN

View File

@ -525,85 +525,70 @@ static void rdtgroup_remove(struct rdtgroup *rdtgrp)
kfree(rdtgrp); kfree(rdtgrp);
} }
struct task_move_callback { static void _update_task_closid_rmid(void *task)
struct callback_head work;
struct rdtgroup *rdtgrp;
};
static void move_myself(struct callback_head *head)
{ {
struct task_move_callback *callback;
struct rdtgroup *rdtgrp;
callback = container_of(head, struct task_move_callback, work);
rdtgrp = callback->rdtgrp;
/* /*
* If resource group was deleted before this task work callback * If the task is still current on this CPU, update PQR_ASSOC MSR.
* was invoked, then assign the task to root group and free the * Otherwise, the MSR is updated when the task is scheduled in.
* resource group.
*/ */
if (atomic_dec_and_test(&rdtgrp->waitcount) && if (task == current)
(rdtgrp->flags & RDT_DELETED)) { resctrl_sched_in();
current->closid = 0; }
current->rmid = 0;
rdtgroup_remove(rdtgrp);
}
preempt_disable(); static void update_task_closid_rmid(struct task_struct *t)
/* update PQR_ASSOC MSR to make resource group go into effect */ {
resctrl_sched_in(); if (IS_ENABLED(CONFIG_SMP) && task_curr(t))
preempt_enable(); smp_call_function_single(task_cpu(t), _update_task_closid_rmid, t, 1);
else
kfree(callback); _update_task_closid_rmid(t);
} }
static int __rdtgroup_move_task(struct task_struct *tsk, static int __rdtgroup_move_task(struct task_struct *tsk,
struct rdtgroup *rdtgrp) struct rdtgroup *rdtgrp)
{ {
struct task_move_callback *callback; /* If the task is already in rdtgrp, no need to move the task. */
int ret; if ((rdtgrp->type == RDTCTRL_GROUP && tsk->closid == rdtgrp->closid &&
tsk->rmid == rdtgrp->mon.rmid) ||
callback = kzalloc(sizeof(*callback), GFP_KERNEL); (rdtgrp->type == RDTMON_GROUP && tsk->rmid == rdtgrp->mon.rmid &&
if (!callback) tsk->closid == rdtgrp->mon.parent->closid))
return -ENOMEM; return 0;
callback->work.func = move_myself;
callback->rdtgrp = rdtgrp;
/* /*
* Take a refcount, so rdtgrp cannot be freed before the * Set the task's closid/rmid before the PQR_ASSOC MSR can be
* callback has been invoked. * updated by them.
*
* For ctrl_mon groups, move both closid and rmid.
* For monitor groups, can move the tasks only from
* their parent CTRL group.
*/ */
atomic_inc(&rdtgrp->waitcount);
ret = task_work_add(tsk, &callback->work, true); if (rdtgrp->type == RDTCTRL_GROUP) {
if (ret) { tsk->closid = rdtgrp->closid;
/* tsk->rmid = rdtgrp->mon.rmid;
* Task is exiting. Drop the refcount and free the callback. } else if (rdtgrp->type == RDTMON_GROUP) {
* No need to check the refcount as the group cannot be if (rdtgrp->mon.parent->closid == tsk->closid) {
* deleted before the write function unlocks rdtgroup_mutex.
*/
atomic_dec(&rdtgrp->waitcount);
kfree(callback);
rdt_last_cmd_puts("Task exited\n");
} else {
/*
* For ctrl_mon groups move both closid and rmid.
* For monitor groups, can move the tasks only from
* their parent CTRL group.
*/
if (rdtgrp->type == RDTCTRL_GROUP) {
tsk->closid = rdtgrp->closid;
tsk->rmid = rdtgrp->mon.rmid; tsk->rmid = rdtgrp->mon.rmid;
} else if (rdtgrp->type == RDTMON_GROUP) { } else {
if (rdtgrp->mon.parent->closid == tsk->closid) { rdt_last_cmd_puts("Can't move task to different control group\n");
tsk->rmid = rdtgrp->mon.rmid; return -EINVAL;
} else {
rdt_last_cmd_puts("Can't move task to different control group\n");
ret = -EINVAL;
}
} }
} }
return ret;
/*
* Ensure the task's closid and rmid are written before determining if
* the task is current that will decide if it will be interrupted.
*/
barrier();
/*
* By now, the task's closid and rmid are set. If the task is current
* on a CPU, the PQR_ASSOC MSR needs to be updated to make the resource
* group go into effect. If the task is not current, the MSR will be
* updated when the task is scheduled in.
*/
update_task_closid_rmid(tsk);
return 0;
} }
/** /**

View File

@ -89,7 +89,7 @@ WEAK(ftrace_stub)
ret ret
END(ftrace_caller) END(ftrace_caller)
ENTRY(ftrace_regs_caller) SYM_CODE_START(ftrace_regs_caller)
/* /*
* We're here from an mcount/fentry CALL, and the stack frame looks like: * We're here from an mcount/fentry CALL, and the stack frame looks like:
* *
@ -163,6 +163,7 @@ GLOBAL(ftrace_regs_call)
popl %eax popl %eax
jmp .Lftrace_ret jmp .Lftrace_ret
SYM_CODE_END(ftrace_regs_caller)
#ifdef CONFIG_FUNCTION_GRAPH_TRACER #ifdef CONFIG_FUNCTION_GRAPH_TRACER
ENTRY(ftrace_graph_caller) ENTRY(ftrace_graph_caller)

View File

@ -64,7 +64,7 @@ RESERVE_BRK(pagetables, INIT_MAP_SIZE)
* can. * can.
*/ */
__HEAD __HEAD
ENTRY(startup_32) SYM_CODE_START(startup_32)
movl pa(initial_stack),%ecx movl pa(initial_stack),%ecx
/* test KEEP_SEGMENTS flag to see if the bootloader is asking /* test KEEP_SEGMENTS flag to see if the bootloader is asking
@ -172,6 +172,7 @@ num_subarch_entries = (. - subarch_entries) / 4
#else #else
jmp .Ldefault_entry jmp .Ldefault_entry
#endif /* CONFIG_PARAVIRT */ #endif /* CONFIG_PARAVIRT */
SYM_CODE_END(startup_32)
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
/* /*

View File

@ -35,7 +35,7 @@ ENTRY(swsusp_arch_suspend)
ret ret
ENDPROC(swsusp_arch_suspend) ENDPROC(swsusp_arch_suspend)
ENTRY(restore_image) SYM_CODE_START(restore_image)
/* prepare to jump to the image kernel */ /* prepare to jump to the image kernel */
movl restore_jump_address, %ebx movl restore_jump_address, %ebx
movl restore_cr3, %ebp movl restore_cr3, %ebp
@ -45,9 +45,10 @@ ENTRY(restore_image)
/* jump to relocated restore code */ /* jump to relocated restore code */
movl relocated_restore_code, %eax movl relocated_restore_code, %eax
jmpl *%eax jmpl *%eax
SYM_CODE_END(restore_image)
/* code below has been relocated to a safe page */ /* code below has been relocated to a safe page */
ENTRY(core_restore_code) SYM_CODE_START(core_restore_code)
movl temp_pgt, %eax movl temp_pgt, %eax
movl %eax, %cr3 movl %eax, %cr3
@ -77,6 +78,7 @@ copy_loop:
done: done:
jmpl *%ebx jmpl *%ebx
SYM_CODE_END(core_restore_code)
/* code below belongs to the image kernel */ /* code below belongs to the image kernel */
.align PAGE_SIZE .align PAGE_SIZE

View File

@ -29,7 +29,7 @@
.code16 .code16
.balign PAGE_SIZE .balign PAGE_SIZE
ENTRY(trampoline_start) SYM_CODE_START(trampoline_start)
wbinvd # Needed for NUMA-Q should be harmless for others wbinvd # Needed for NUMA-Q should be harmless for others
LJMPW_RM(1f) LJMPW_RM(1f)
@ -54,11 +54,13 @@ ENTRY(trampoline_start)
lmsw %dx # into protected mode lmsw %dx # into protected mode
ljmpl $__BOOT_CS, $pa_startup_32 ljmpl $__BOOT_CS, $pa_startup_32
SYM_CODE_END(trampoline_start)
.section ".text32","ax" .section ".text32","ax"
.code32 .code32
ENTRY(startup_32) # note: also used from wakeup_asm.S SYM_CODE_START(startup_32) # note: also used from wakeup_asm.S
jmp *%eax jmp *%eax
SYM_CODE_END(startup_32)
.bss .bss
.balign 8 .balign 8

View File

@ -56,7 +56,7 @@
_ASM_EXTABLE(1b,2b) _ASM_EXTABLE(1b,2b)
.endm .endm
ENTRY(xen_iret) SYM_CODE_START(xen_iret)
/* test eflags for special cases */ /* test eflags for special cases */
testl $(X86_EFLAGS_VM | XEN_EFLAGS_NMI), 8(%esp) testl $(X86_EFLAGS_VM | XEN_EFLAGS_NMI), 8(%esp)
jnz hyper_iret jnz hyper_iret
@ -122,6 +122,7 @@ xen_iret_end_crit:
hyper_iret: hyper_iret:
/* put this out of line since its very rarely used */ /* put this out of line since its very rarely used */
jmp hypercall_page + __HYPERVISOR_iret * 32 jmp hypercall_page + __HYPERVISOR_iret * 32
SYM_CODE_END(xen_iret)
.globl xen_iret_start_crit, xen_iret_end_crit .globl xen_iret_start_crit, xen_iret_end_crit
@ -152,7 +153,7 @@ hyper_iret:
* The only caveat is that if the outer eax hasn't been restored yet (i.e. * The only caveat is that if the outer eax hasn't been restored yet (i.e.
* it's still on stack), we need to restore its value here. * it's still on stack), we need to restore its value here.
*/ */
ENTRY(xen_iret_crit_fixup) SYM_CODE_START(xen_iret_crit_fixup)
/* /*
* Paranoia: Make sure we're really coming from kernel space. * Paranoia: Make sure we're really coming from kernel space.
* One could imagine a case where userspace jumps into the * One could imagine a case where userspace jumps into the
@ -179,4 +180,4 @@ ENTRY(xen_iret_crit_fixup)
2: 2:
ret ret
END(xen_iret_crit_fixup) SYM_CODE_END(xen_iret_crit_fixup)

View File

@ -222,14 +222,17 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter)
part = rcu_dereference(ptbl->part[piter->idx]); part = rcu_dereference(ptbl->part[piter->idx]);
if (!part) if (!part)
continue; continue;
get_device(part_to_dev(part));
piter->part = part;
if (!part_nr_sects_read(part) && if (!part_nr_sects_read(part) &&
!(piter->flags & DISK_PITER_INCL_EMPTY) && !(piter->flags & DISK_PITER_INCL_EMPTY) &&
!(piter->flags & DISK_PITER_INCL_EMPTY_PART0 && !(piter->flags & DISK_PITER_INCL_EMPTY_PART0 &&
piter->idx == 0)) piter->idx == 0)) {
put_device(part_to_dev(part));
piter->part = NULL;
continue; continue;
}
get_device(part_to_dev(part));
piter->part = part;
piter->idx += inc; piter->idx += inc;
break; break;
} }

View File

@ -583,8 +583,12 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
devname = dev_name(map->dev); devname = dev_name(map->dev);
if (name) { if (name) {
map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s", if (!map->debugfs_name) {
map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s",
devname, name); devname, name);
if (!map->debugfs_name)
return;
}
name = map->debugfs_name; name = map->debugfs_name;
} else { } else {
name = devname; name = devname;
@ -592,9 +596,10 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
if (!strcmp(name, "dummy")) { if (!strcmp(name, "dummy")) {
kfree(map->debugfs_name); kfree(map->debugfs_name);
map->debugfs_name = kasprintf(GFP_KERNEL, "dummy%d", map->debugfs_name = kasprintf(GFP_KERNEL, "dummy%d",
dummy_index); dummy_index);
if (!map->debugfs_name)
return;
name = map->debugfs_name; name = map->debugfs_name;
dummy_index++; dummy_index++;
} }

View File

@ -461,6 +461,7 @@ config BLK_DEV_RBD
config BLK_DEV_RSXX config BLK_DEV_RSXX
tristate "IBM Flash Adapter 900GB Full Height PCIe Device Driver" tristate "IBM Flash Adapter 900GB Full Height PCIe Device Driver"
depends on PCI depends on PCI
select CRC32
help help
Device driver for IBM's high speed PCIe SSD Device driver for IBM's high speed PCIe SSD
storage device: Flash Adapter 900GB Full Height. storage device: Flash Adapter 900GB Full Height.

View File

@ -878,9 +878,9 @@ static int get_transition_latency(struct powernow_k8_data *data)
/* Take a frequency, and issue the fid/vid transition command */ /* Take a frequency, and issue the fid/vid transition command */
static int transition_frequency_fidvid(struct powernow_k8_data *data, static int transition_frequency_fidvid(struct powernow_k8_data *data,
unsigned int index) unsigned int index,
struct cpufreq_policy *policy)
{ {
struct cpufreq_policy *policy;
u32 fid = 0; u32 fid = 0;
u32 vid = 0; u32 vid = 0;
int res; int res;
@ -912,9 +912,6 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
freqs.old = find_khz_freq_from_fid(data->currfid); freqs.old = find_khz_freq_from_fid(data->currfid);
freqs.new = find_khz_freq_from_fid(fid); freqs.new = find_khz_freq_from_fid(fid);
policy = cpufreq_cpu_get(smp_processor_id());
cpufreq_cpu_put(policy);
cpufreq_freq_transition_begin(policy, &freqs); cpufreq_freq_transition_begin(policy, &freqs);
res = transition_fid_vid(data, fid, vid); res = transition_fid_vid(data, fid, vid);
cpufreq_freq_transition_end(policy, &freqs, res); cpufreq_freq_transition_end(policy, &freqs, res);
@ -969,7 +966,7 @@ static long powernowk8_target_fn(void *arg)
powernow_k8_acpi_pst_values(data, newstate); powernow_k8_acpi_pst_values(data, newstate);
ret = transition_frequency_fidvid(data, newstate); ret = transition_frequency_fidvid(data, newstate, pol);
if (ret) { if (ret) {
pr_err("transition frequency failed\n"); pr_err("transition frequency failed\n");

View File

@ -577,7 +577,7 @@ static void chtls_reset_synq(struct listen_ctx *listen_ctx)
while (!skb_queue_empty(&listen_ctx->synq)) { while (!skb_queue_empty(&listen_ctx->synq)) {
struct chtls_sock *csk = struct chtls_sock *csk =
container_of((struct synq *)__skb_dequeue container_of((struct synq *)skb_peek
(&listen_ctx->synq), struct chtls_sock, synq); (&listen_ctx->synq), struct chtls_sock, synq);
struct sock *child = csk->sk; struct sock *child = csk->sk;
@ -1021,6 +1021,7 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
const struct cpl_pass_accept_req *req, const struct cpl_pass_accept_req *req,
struct chtls_dev *cdev) struct chtls_dev *cdev)
{ {
struct adapter *adap = pci_get_drvdata(cdev->pdev);
struct inet_sock *newinet; struct inet_sock *newinet;
const struct iphdr *iph; const struct iphdr *iph;
struct tls_context *ctx; struct tls_context *ctx;
@ -1030,9 +1031,10 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
struct neighbour *n; struct neighbour *n;
struct tcp_sock *tp; struct tcp_sock *tp;
struct sock *newsk; struct sock *newsk;
bool found = false;
u16 port_id; u16 port_id;
int rxq_idx; int rxq_idx;
int step; int step, i;
iph = (const struct iphdr *)network_hdr; iph = (const struct iphdr *)network_hdr;
newsk = tcp_create_openreq_child(lsk, oreq, cdev->askb); newsk = tcp_create_openreq_child(lsk, oreq, cdev->askb);
@ -1044,7 +1046,7 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
goto free_sk; goto free_sk;
n = dst_neigh_lookup(dst, &iph->saddr); n = dst_neigh_lookup(dst, &iph->saddr);
if (!n) if (!n || !n->dev)
goto free_sk; goto free_sk;
ndev = n->dev; ndev = n->dev;
@ -1053,6 +1055,13 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
if (is_vlan_dev(ndev)) if (is_vlan_dev(ndev))
ndev = vlan_dev_real_dev(ndev); ndev = vlan_dev_real_dev(ndev);
for_each_port(adap, i)
if (cdev->ports[i] == ndev)
found = true;
if (!found)
goto free_dst;
port_id = cxgb4_port_idx(ndev); port_id = cxgb4_port_idx(ndev);
csk = chtls_sock_create(cdev); csk = chtls_sock_create(cdev);
@ -1108,6 +1117,7 @@ static struct sock *chtls_recv_sock(struct sock *lsk,
free_csk: free_csk:
chtls_sock_release(&csk->kref); chtls_sock_release(&csk->kref);
free_dst: free_dst:
neigh_release(n);
dst_release(dst); dst_release(dst);
free_sk: free_sk:
inet_csk_prepare_forced_close(newsk); inet_csk_prepare_forced_close(newsk);
@ -1443,6 +1453,11 @@ static int chtls_pass_establish(struct chtls_dev *cdev, struct sk_buff *skb)
sk_wake_async(sk, 0, POLL_OUT); sk_wake_async(sk, 0, POLL_OUT);
data = lookup_stid(cdev->tids, stid); data = lookup_stid(cdev->tids, stid);
if (!data) {
/* listening server close */
kfree_skb(skb);
goto unlock;
}
lsk = ((struct listen_ctx *)data)->lsk; lsk = ((struct listen_ctx *)data)->lsk;
bh_lock_sock(lsk); bh_lock_sock(lsk);
@ -1828,39 +1843,6 @@ static void send_defer_abort_rpl(struct chtls_dev *cdev, struct sk_buff *skb)
kfree_skb(skb); kfree_skb(skb);
} }
static void send_abort_rpl(struct sock *sk, struct sk_buff *skb,
struct chtls_dev *cdev, int status, int queue)
{
struct cpl_abort_req_rss *req = cplhdr(skb);
struct sk_buff *reply_skb;
struct chtls_sock *csk;
csk = rcu_dereference_sk_user_data(sk);
reply_skb = alloc_skb(sizeof(struct cpl_abort_rpl),
GFP_KERNEL);
if (!reply_skb) {
req->status = (queue << 1);
send_defer_abort_rpl(cdev, skb);
return;
}
set_abort_rpl_wr(reply_skb, GET_TID(req), status);
kfree_skb(skb);
set_wr_txq(reply_skb, CPL_PRIORITY_DATA, queue);
if (csk_conn_inline(csk)) {
struct l2t_entry *e = csk->l2t_entry;
if (e && sk->sk_state != TCP_SYN_RECV) {
cxgb4_l2t_send(csk->egress_dev, reply_skb, e);
return;
}
}
cxgb4_ofld_send(cdev->lldi->ports[0], reply_skb);
}
/* /*
* Add an skb to the deferred skb queue for processing from process context. * Add an skb to the deferred skb queue for processing from process context.
*/ */
@ -1923,9 +1905,9 @@ static void bl_abort_syn_rcv(struct sock *lsk, struct sk_buff *skb)
queue = csk->txq_idx; queue = csk->txq_idx;
skb->sk = NULL; skb->sk = NULL;
chtls_send_abort_rpl(child, skb, BLOG_SKB_CB(skb)->cdev,
CPL_ABORT_NO_RST, queue);
do_abort_syn_rcv(child, lsk); do_abort_syn_rcv(child, lsk);
send_abort_rpl(child, skb, BLOG_SKB_CB(skb)->cdev,
CPL_ABORT_NO_RST, queue);
} }
static int abort_syn_rcv(struct sock *sk, struct sk_buff *skb) static int abort_syn_rcv(struct sock *sk, struct sk_buff *skb)
@ -1955,8 +1937,8 @@ static int abort_syn_rcv(struct sock *sk, struct sk_buff *skb)
if (!sock_owned_by_user(psk)) { if (!sock_owned_by_user(psk)) {
int queue = csk->txq_idx; int queue = csk->txq_idx;
chtls_send_abort_rpl(sk, skb, cdev, CPL_ABORT_NO_RST, queue);
do_abort_syn_rcv(sk, psk); do_abort_syn_rcv(sk, psk);
send_abort_rpl(sk, skb, cdev, CPL_ABORT_NO_RST, queue);
} else { } else {
skb->sk = sk; skb->sk = sk;
BLOG_SKB_CB(skb)->backlog_rcv = bl_abort_syn_rcv; BLOG_SKB_CB(skb)->backlog_rcv = bl_abort_syn_rcv;
@ -1974,9 +1956,6 @@ static void chtls_abort_req_rss(struct sock *sk, struct sk_buff *skb)
int queue = csk->txq_idx; int queue = csk->txq_idx;
if (is_neg_adv(req->status)) { if (is_neg_adv(req->status)) {
if (sk->sk_state == TCP_SYN_RECV)
chtls_set_tcb_tflag(sk, 0, 0);
kfree_skb(skb); kfree_skb(skb);
return; return;
} }
@ -2002,12 +1981,11 @@ static void chtls_abort_req_rss(struct sock *sk, struct sk_buff *skb)
if (sk->sk_state == TCP_SYN_RECV && !abort_syn_rcv(sk, skb)) if (sk->sk_state == TCP_SYN_RECV && !abort_syn_rcv(sk, skb))
return; return;
chtls_release_resources(sk);
chtls_conn_done(sk);
} }
chtls_send_abort_rpl(sk, skb, csk->cdev, rst_status, queue); chtls_send_abort_rpl(sk, skb, csk->cdev, rst_status, queue);
chtls_release_resources(sk);
chtls_conn_done(sk);
} }
static void chtls_abort_rpl_rss(struct sock *sk, struct sk_buff *skb) static void chtls_abort_rpl_rss(struct sock *sk, struct sk_buff *skb)

View File

@ -85,12 +85,12 @@ static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
if (desc->chunk) { if (desc->chunk) {
/* Create and add new element into the linked list */ /* Create and add new element into the linked list */
desc->chunks_alloc++;
list_add_tail(&chunk->list, &desc->chunk->list);
if (!dw_edma_alloc_burst(chunk)) { if (!dw_edma_alloc_burst(chunk)) {
kfree(chunk); kfree(chunk);
return NULL; return NULL;
} }
desc->chunks_alloc++;
list_add_tail(&chunk->list, &desc->chunk->list);
} else { } else {
/* List head */ /* List head */
chunk->burst = NULL; chunk->burst = NULL;

View File

@ -1007,6 +1007,7 @@ static int mtk_hsdma_probe(struct platform_device *pdev)
return 0; return 0;
err_free: err_free:
mtk_hsdma_hw_deinit(hsdma);
of_dma_controller_free(pdev->dev.of_node); of_dma_controller_free(pdev->dev.of_node);
err_unregister: err_unregister:
dma_async_device_unregister(dd); dma_async_device_unregister(dd);

View File

@ -2431,7 +2431,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
has_dre = false; has_dre = false;
if (!has_dre) if (!has_dre)
xdev->common.copy_align = fls(width - 1); xdev->common.copy_align = (enum dmaengine_alignment)fls(width - 1);
if (of_device_is_compatible(node, "xlnx,axi-vdma-mm2s-channel") || if (of_device_is_compatible(node, "xlnx,axi-vdma-mm2s-channel") ||
of_device_is_compatible(node, "xlnx,axi-dma-mm2s-channel") || of_device_is_compatible(node, "xlnx,axi-dma-mm2s-channel") ||
@ -2543,7 +2543,8 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
static int xilinx_dma_child_probe(struct xilinx_dma_device *xdev, static int xilinx_dma_child_probe(struct xilinx_dma_device *xdev,
struct device_node *node) struct device_node *node)
{ {
int ret, i, nr_channels = 1; int ret, i;
u32 nr_channels = 1;
ret = of_property_read_u32(node, "dma-channels", &nr_channels); ret = of_property_read_u32(node, "dma-channels", &nr_channels);
if ((ret < 0) && xdev->mcdma) if ((ret < 0) && xdev->mcdma)
@ -2742,7 +2743,11 @@ static int xilinx_dma_probe(struct platform_device *pdev)
} }
/* Register the DMA engine with the core */ /* Register the DMA engine with the core */
dma_async_device_register(&xdev->common); err = dma_async_device_register(&xdev->common);
if (err) {
dev_err(xdev->dev, "failed to register the dma device\n");
goto error;
}
err = of_dma_controller_register(node, of_dma_xilinx_xlate, err = of_dma_controller_register(node, of_dma_xilinx_xlate,
xdev); xdev);

View File

@ -1270,6 +1270,37 @@ static int wacom_devm_sysfs_create_group(struct wacom *wacom,
group); group);
} }
static void wacom_devm_kfifo_release(struct device *dev, void *res)
{
struct kfifo_rec_ptr_2 *devres = res;
kfifo_free(devres);
}
static int wacom_devm_kfifo_alloc(struct wacom *wacom)
{
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
struct kfifo_rec_ptr_2 *pen_fifo = &wacom_wac->pen_fifo;
int error;
pen_fifo = devres_alloc(wacom_devm_kfifo_release,
sizeof(struct kfifo_rec_ptr_2),
GFP_KERNEL);
if (!pen_fifo)
return -ENOMEM;
error = kfifo_alloc(pen_fifo, WACOM_PKGLEN_MAX, GFP_KERNEL);
if (error) {
devres_free(pen_fifo);
return error;
}
devres_add(&wacom->hdev->dev, pen_fifo);
return 0;
}
enum led_brightness wacom_leds_brightness_get(struct wacom_led *led) enum led_brightness wacom_leds_brightness_get(struct wacom_led *led)
{ {
struct wacom *wacom = led->wacom; struct wacom *wacom = led->wacom;
@ -2724,7 +2755,7 @@ static int wacom_probe(struct hid_device *hdev,
if (features->check_for_hid_type && features->hid_type != hdev->type) if (features->check_for_hid_type && features->hid_type != hdev->type)
return -ENODEV; return -ENODEV;
error = kfifo_alloc(&wacom_wac->pen_fifo, WACOM_PKGLEN_MAX, GFP_KERNEL); error = wacom_devm_kfifo_alloc(wacom);
if (error) if (error)
return error; return error;
@ -2786,8 +2817,6 @@ static void wacom_remove(struct hid_device *hdev)
if (wacom->wacom_wac.features.type != REMOTE) if (wacom->wacom_wac.features.type != REMOTE)
wacom_release_resources(wacom); wacom_release_resources(wacom);
kfifo_free(&wacom_wac->pen_fifo);
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM

View File

@ -1424,7 +1424,7 @@ static int i801_add_mux(struct i801_priv *priv)
/* Register GPIO descriptor lookup table */ /* Register GPIO descriptor lookup table */
lookup = devm_kzalloc(dev, lookup = devm_kzalloc(dev,
struct_size(lookup, table, mux_config->n_gpios), struct_size(lookup, table, mux_config->n_gpios + 1),
GFP_KERNEL); GFP_KERNEL);
if (!lookup) if (!lookup)
return -ENOMEM; return -ENOMEM;

View File

@ -72,6 +72,8 @@
/* timeout (ms) for pm runtime autosuspend */ /* timeout (ms) for pm runtime autosuspend */
#define SPRD_I2C_PM_TIMEOUT 1000 #define SPRD_I2C_PM_TIMEOUT 1000
/* timeout (ms) for transfer message */
#define I2C_XFER_TIMEOUT 1000
/* SPRD i2c data structure */ /* SPRD i2c data structure */
struct sprd_i2c { struct sprd_i2c {
@ -244,6 +246,7 @@ static int sprd_i2c_handle_msg(struct i2c_adapter *i2c_adap,
struct i2c_msg *msg, bool is_last_msg) struct i2c_msg *msg, bool is_last_msg)
{ {
struct sprd_i2c *i2c_dev = i2c_adap->algo_data; struct sprd_i2c *i2c_dev = i2c_adap->algo_data;
unsigned long time_left;
i2c_dev->msg = msg; i2c_dev->msg = msg;
i2c_dev->buf = msg->buf; i2c_dev->buf = msg->buf;
@ -273,7 +276,10 @@ static int sprd_i2c_handle_msg(struct i2c_adapter *i2c_adap,
sprd_i2c_opt_start(i2c_dev); sprd_i2c_opt_start(i2c_dev);
wait_for_completion(&i2c_dev->complete); time_left = wait_for_completion_timeout(&i2c_dev->complete,
msecs_to_jiffies(I2C_XFER_TIMEOUT));
if (!time_left)
return -ETIMEDOUT;
return i2c_dev->err; return i2c_dev->err;
} }

View File

@ -664,13 +664,29 @@ static irqreturn_t st_lsm6dsx_handler_irq(int irq, void *private)
static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private)
{ {
struct st_lsm6dsx_hw *hw = private; struct st_lsm6dsx_hw *hw = private;
int count; int fifo_len = 0, len;
mutex_lock(&hw->fifo_lock); /*
count = hw->settings->fifo_ops.read_fifo(hw); * If we are using edge IRQs, new samples can arrive while
mutex_unlock(&hw->fifo_lock); * processing current interrupt since there are no hw
* guarantees the irq line stays "low" long enough to properly
* detect the new interrupt. In this case the new sample will
* be missed.
* Polling FIFO status register allow us to read new
* samples even if the interrupt arrives while processing
* previous data and the timeslot where the line is "low" is
* too short to be properly detected.
*/
do {
mutex_lock(&hw->fifo_lock);
len = hw->settings->fifo_ops.read_fifo(hw);
mutex_unlock(&hw->fifo_lock);
return count ? IRQ_HANDLED : IRQ_NONE; if (len > 0)
fifo_len += len;
} while (len > 0);
return fifo_len ? IRQ_HANDLED : IRQ_NONE;
} }
static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev) static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev)

View File

@ -1400,6 +1400,8 @@ static int intel_irq_remapping_alloc(struct irq_domain *domain,
irq_data = irq_domain_get_irq_data(domain, virq + i); irq_data = irq_domain_get_irq_data(domain, virq + i);
irq_cfg = irqd_cfg(irq_data); irq_cfg = irqd_cfg(irq_data);
if (!irq_data || !irq_cfg) { if (!irq_data || !irq_cfg) {
if (!i)
kfree(data);
ret = -EINVAL; ret = -EINVAL;
goto out_free_data; goto out_free_data;
} }

View File

@ -19,6 +19,7 @@ if NVM
config NVM_PBLK config NVM_PBLK
tristate "Physical Block Device Open-Channel SSD target" tristate "Physical Block Device Open-Channel SSD target"
select CRC32
help help
Allows an open-channel SSD to be exposed as a block device to the Allows an open-channel SSD to be exposed as a block device to the
host. The target assumes the device exposes raw flash and must be host. The target assumes the device exposes raw flash and must be

View File

@ -123,6 +123,7 @@ config CAN_JANZ_ICAN3
config CAN_KVASER_PCIEFD config CAN_KVASER_PCIEFD
depends on PCI depends on PCI
tristate "Kvaser PCIe FD cards" tristate "Kvaser PCIe FD cards"
select CRC32
help help
This is a driver for the Kvaser PCI Express CAN FD family. This is a driver for the Kvaser PCI Express CAN FD family.

View File

@ -1868,8 +1868,6 @@ void m_can_class_unregister(struct m_can_classdev *m_can_dev)
{ {
unregister_candev(m_can_dev->net); unregister_candev(m_can_dev->net);
m_can_clk_stop(m_can_dev);
free_candev(m_can_dev->net); free_candev(m_can_dev->net);
} }
EXPORT_SYMBOL_GPL(m_can_class_unregister); EXPORT_SYMBOL_GPL(m_can_class_unregister);

View File

@ -126,30 +126,6 @@ struct tcan4x5x_priv {
int reg_offset; int reg_offset;
}; };
static struct can_bittiming_const tcan4x5x_bittiming_const = {
.name = DEVICE_NAME,
.tseg1_min = 2,
.tseg1_max = 31,
.tseg2_min = 2,
.tseg2_max = 16,
.sjw_max = 16,
.brp_min = 1,
.brp_max = 32,
.brp_inc = 1,
};
static struct can_bittiming_const tcan4x5x_data_bittiming_const = {
.name = DEVICE_NAME,
.tseg1_min = 1,
.tseg1_max = 32,
.tseg2_min = 1,
.tseg2_max = 16,
.sjw_max = 16,
.brp_min = 1,
.brp_max = 32,
.brp_inc = 1,
};
static void tcan4x5x_check_wake(struct tcan4x5x_priv *priv) static void tcan4x5x_check_wake(struct tcan4x5x_priv *priv)
{ {
int wake_state = 0; int wake_state = 0;
@ -449,8 +425,6 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
mcan_class->dev = &spi->dev; mcan_class->dev = &spi->dev;
mcan_class->ops = &tcan4x5x_ops; mcan_class->ops = &tcan4x5x_ops;
mcan_class->is_peripheral = true; mcan_class->is_peripheral = true;
mcan_class->bit_timing = &tcan4x5x_bittiming_const;
mcan_class->data_timing = &tcan4x5x_data_bittiming_const;
mcan_class->net->irq = spi->irq; mcan_class->net->irq = spi->irq;
spi_set_drvdata(spi, priv); spi_set_drvdata(spi, priv);

View File

@ -1419,11 +1419,12 @@ static void gswip_phylink_validate(struct dsa_switch *ds, int port,
phylink_set(mask, Pause); phylink_set(mask, Pause);
phylink_set(mask, Asym_Pause); phylink_set(mask, Asym_Pause);
/* With the exclusion of MII and Reverse MII, we support Gigabit, /* With the exclusion of MII, Reverse MII and Reduced MII, we
* including Half duplex * support Gigabit, including Half duplex
*/ */
if (state->interface != PHY_INTERFACE_MODE_MII && if (state->interface != PHY_INTERFACE_MODE_MII &&
state->interface != PHY_INTERFACE_MODE_REVMII) { state->interface != PHY_INTERFACE_MODE_REVMII &&
state->interface != PHY_INTERFACE_MODE_RMII) {
phylink_set(mask, 1000baseT_Full); phylink_set(mask, 1000baseT_Full);
phylink_set(mask, 1000baseT_Half); phylink_set(mask, 1000baseT_Half);
} }

View File

@ -123,7 +123,7 @@ struct hclgevf_mbx_arq_ring {
#define hclge_mbx_ring_ptr_move_crq(crq) \ #define hclge_mbx_ring_ptr_move_crq(crq) \
(crq->next_to_use = (crq->next_to_use + 1) % crq->desc_num) (crq->next_to_use = (crq->next_to_use + 1) % crq->desc_num)
#define hclge_mbx_tail_ptr_move_arq(arq) \ #define hclge_mbx_tail_ptr_move_arq(arq) \
(arq.tail = (arq.tail + 1) % HCLGE_MBX_MAX_ARQ_MSG_SIZE) (arq.tail = (arq.tail + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM)
#define hclge_mbx_head_ptr_move_arq(arq) \ #define hclge_mbx_head_ptr_move_arq(arq) \
(arq.head = (arq.head + 1) % HCLGE_MBX_MAX_ARQ_MSG_SIZE) (arq.head = (arq.head + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM)
#endif #endif

View File

@ -746,7 +746,8 @@ static int hclge_get_sset_count(struct hnae3_handle *handle, int stringset)
handle->flags |= HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK; handle->flags |= HNAE3_SUPPORT_SERDES_SERIAL_LOOPBACK;
handle->flags |= HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK; handle->flags |= HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK;
if (hdev->hw.mac.phydev) { if (hdev->hw.mac.phydev && hdev->hw.mac.phydev->drv &&
hdev->hw.mac.phydev->drv->set_loopback) {
count += 1; count += 1;
handle->flags |= HNAE3_SUPPORT_PHY_LOOPBACK; handle->flags |= HNAE3_SUPPORT_PHY_LOOPBACK;
} }

View File

@ -4545,7 +4545,7 @@ static int mvpp2_port_init(struct mvpp2_port *port)
struct mvpp2 *priv = port->priv; struct mvpp2 *priv = port->priv;
struct mvpp2_txq_pcpu *txq_pcpu; struct mvpp2_txq_pcpu *txq_pcpu;
unsigned int thread; unsigned int thread;
int queue, err; int queue, err, val;
/* Checks for hardware constraints */ /* Checks for hardware constraints */
if (port->first_rxq + port->nrxqs > if (port->first_rxq + port->nrxqs >
@ -4559,6 +4559,18 @@ static int mvpp2_port_init(struct mvpp2_port *port)
mvpp2_egress_disable(port); mvpp2_egress_disable(port);
mvpp2_port_disable(port); mvpp2_port_disable(port);
if (mvpp2_is_xlg(port->phy_interface)) {
val = readl(port->base + MVPP22_XLG_CTRL0_REG);
val &= ~MVPP22_XLG_CTRL0_FORCE_LINK_PASS;
val |= MVPP22_XLG_CTRL0_FORCE_LINK_DOWN;
writel(val, port->base + MVPP22_XLG_CTRL0_REG);
} else {
val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
val &= ~MVPP2_GMAC_FORCE_LINK_PASS;
val |= MVPP2_GMAC_FORCE_LINK_DOWN;
writel(val, port->base + MVPP2_GMAC_AUTONEG_CONFIG);
}
port->tx_time_coal = MVPP2_TXDONE_COAL_USEC; port->tx_time_coal = MVPP2_TXDONE_COAL_USEC;
port->txqs = devm_kcalloc(dev, port->ntxqs, sizeof(*port->txqs), port->txqs = devm_kcalloc(dev, port->ntxqs, sizeof(*port->txqs),

View File

@ -725,8 +725,10 @@ static int cgx_lmac_init(struct cgx *cgx)
if (!lmac) if (!lmac)
return -ENOMEM; return -ENOMEM;
lmac->name = kcalloc(1, sizeof("cgx_fwi_xxx_yyy"), GFP_KERNEL); lmac->name = kcalloc(1, sizeof("cgx_fwi_xxx_yyy"), GFP_KERNEL);
if (!lmac->name) if (!lmac->name) {
return -ENOMEM; err = -ENOMEM;
goto err_lmac_free;
}
sprintf(lmac->name, "cgx_fwi_%d_%d", cgx->cgx_id, i); sprintf(lmac->name, "cgx_fwi_%d_%d", cgx->cgx_id, i);
lmac->lmac_id = i; lmac->lmac_id = i;
lmac->cgx = cgx; lmac->cgx = cgx;
@ -737,7 +739,7 @@ static int cgx_lmac_init(struct cgx *cgx)
CGX_LMAC_FWI + i * 9), CGX_LMAC_FWI + i * 9),
cgx_fwi_event_handler, 0, lmac->name, lmac); cgx_fwi_event_handler, 0, lmac->name, lmac);
if (err) if (err)
return err; goto err_irq;
/* Enable interrupt */ /* Enable interrupt */
cgx_write(cgx, lmac->lmac_id, CGXX_CMRX_INT_ENA_W1S, cgx_write(cgx, lmac->lmac_id, CGXX_CMRX_INT_ENA_W1S,
@ -748,6 +750,12 @@ static int cgx_lmac_init(struct cgx *cgx)
} }
return cgx_lmac_verify_fwi_version(cgx); return cgx_lmac_verify_fwi_version(cgx);
err_irq:
kfree(lmac->name);
err_lmac_free:
kfree(lmac);
return err;
} }
static int cgx_lmac_exit(struct cgx *cgx) static int cgx_lmac_exit(struct cgx *cgx)

View File

@ -976,6 +976,22 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
return mlx5e_ethtool_get_link_ksettings(priv, link_ksettings); return mlx5e_ethtool_get_link_ksettings(priv, link_ksettings);
} }
static int mlx5e_speed_validate(struct net_device *netdev, bool ext,
const unsigned long link_modes, u8 autoneg)
{
/* Extended link-mode has no speed limitations. */
if (ext)
return 0;
if ((link_modes & MLX5E_PROT_MASK(MLX5E_56GBASE_R4)) &&
autoneg != AUTONEG_ENABLE) {
netdev_err(netdev, "%s: 56G link speed requires autoneg enabled\n",
__func__);
return -EINVAL;
}
return 0;
}
static u32 mlx5e_ethtool2ptys_adver_link(const unsigned long *link_modes) static u32 mlx5e_ethtool2ptys_adver_link(const unsigned long *link_modes)
{ {
u32 i, ptys_modes = 0; u32 i, ptys_modes = 0;
@ -1068,13 +1084,9 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
link_modes = autoneg == AUTONEG_ENABLE ? ethtool2ptys_adver_func(adver) : link_modes = autoneg == AUTONEG_ENABLE ? ethtool2ptys_adver_func(adver) :
mlx5e_port_speed2linkmodes(mdev, speed, !ext); mlx5e_port_speed2linkmodes(mdev, speed, !ext);
if ((link_modes & MLX5E_PROT_MASK(MLX5E_56GBASE_R4)) && err = mlx5e_speed_validate(priv->netdev, ext, link_modes, autoneg);
autoneg != AUTONEG_ENABLE) { if (err)
netdev_err(priv->netdev, "%s: 56G link speed requires autoneg enabled\n",
__func__);
err = -EINVAL;
goto out; goto out;
}
link_modes = link_modes & eproto.cap; link_modes = link_modes & eproto.cap;
if (!link_modes) { if (!link_modes) {

View File

@ -927,6 +927,7 @@ static int mlx5e_create_ttc_table_groups(struct mlx5e_ttc_table *ttc,
in = kvzalloc(inlen, GFP_KERNEL); in = kvzalloc(inlen, GFP_KERNEL);
if (!in) { if (!in) {
kfree(ft->g); kfree(ft->g);
ft->g = NULL;
return -ENOMEM; return -ENOMEM;
} }
@ -1067,6 +1068,7 @@ static int mlx5e_create_inner_ttc_table_groups(struct mlx5e_ttc_table *ttc)
in = kvzalloc(inlen, GFP_KERNEL); in = kvzalloc(inlen, GFP_KERNEL);
if (!in) { if (!in) {
kfree(ft->g); kfree(ft->g);
ft->g = NULL;
return -ENOMEM; return -ENOMEM;
} }
@ -1346,6 +1348,7 @@ err_destroy_groups:
ft->g[ft->num_groups] = NULL; ft->g[ft->num_groups] = NULL;
mlx5e_destroy_groups(ft); mlx5e_destroy_groups(ft);
kvfree(in); kvfree(in);
kfree(ft->g);
return err; return err;
} }

View File

@ -116,7 +116,7 @@ free:
static void mlx5_rdma_del_roce_addr(struct mlx5_core_dev *dev) static void mlx5_rdma_del_roce_addr(struct mlx5_core_dev *dev)
{ {
mlx5_core_roce_gid_set(dev, 0, 0, 0, mlx5_core_roce_gid_set(dev, 0, 0, 0,
NULL, NULL, false, 0, 0); NULL, NULL, false, 0, 1);
} }
static void mlx5_rdma_make_default_gid(struct mlx5_core_dev *dev, union ib_gid *gid) static void mlx5_rdma_make_default_gid(struct mlx5_core_dev *dev, union ib_gid *gid)

View File

@ -540,10 +540,14 @@ static int mac_sonic_platform_probe(struct platform_device *pdev)
err = register_netdev(dev); err = register_netdev(dev);
if (err) if (err)
goto out; goto undo_probe;
return 0; return 0;
undo_probe:
dma_free_coherent(lp->device,
SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
lp->descriptors, lp->descriptors_laddr);
out: out:
free_netdev(dev); free_netdev(dev);
@ -618,12 +622,16 @@ static int mac_sonic_nubus_probe(struct nubus_board *board)
err = register_netdev(ndev); err = register_netdev(ndev);
if (err) if (err)
goto out; goto undo_probe;
nubus_set_drvdata(board, ndev); nubus_set_drvdata(board, ndev);
return 0; return 0;
undo_probe:
dma_free_coherent(lp->device,
SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
lp->descriptors, lp->descriptors_laddr);
out: out:
free_netdev(ndev); free_netdev(ndev);
return err; return err;

View File

@ -265,11 +265,14 @@ int xtsonic_probe(struct platform_device *pdev)
sonic_msg_init(dev); sonic_msg_init(dev);
if ((err = register_netdev(dev))) if ((err = register_netdev(dev)))
goto out1; goto undo_probe1;
return 0; return 0;
out1: undo_probe1:
dma_free_coherent(lp->device,
SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
lp->descriptors, lp->descriptors_laddr);
release_region(dev->base_addr, SONIC_MEM_SIZE); release_region(dev->base_addr, SONIC_MEM_SIZE);
out: out:
free_netdev(dev); free_netdev(dev);

View File

@ -78,6 +78,7 @@ config QED
depends on PCI depends on PCI
select ZLIB_INFLATE select ZLIB_INFLATE
select CRC8 select CRC8
select CRC32
select NET_DEVLINK select NET_DEVLINK
---help--- ---help---
This enables the support for ... This enables the support for ...

View File

@ -64,6 +64,7 @@ struct emac_variant {
* @variant: reference to the current board variant * @variant: reference to the current board variant
* @regmap: regmap for using the syscon * @regmap: regmap for using the syscon
* @internal_phy_powered: Does the internal PHY is enabled * @internal_phy_powered: Does the internal PHY is enabled
* @use_internal_phy: Is the internal PHY selected for use
* @mux_handle: Internal pointer used by mdio-mux lib * @mux_handle: Internal pointer used by mdio-mux lib
*/ */
struct sunxi_priv_data { struct sunxi_priv_data {
@ -74,6 +75,7 @@ struct sunxi_priv_data {
const struct emac_variant *variant; const struct emac_variant *variant;
struct regmap_field *regmap_field; struct regmap_field *regmap_field;
bool internal_phy_powered; bool internal_phy_powered;
bool use_internal_phy;
void *mux_handle; void *mux_handle;
}; };
@ -539,8 +541,11 @@ static const struct stmmac_dma_ops sun8i_dwmac_dma_ops = {
.dma_interrupt = sun8i_dwmac_dma_interrupt, .dma_interrupt = sun8i_dwmac_dma_interrupt,
}; };
static int sun8i_dwmac_power_internal_phy(struct stmmac_priv *priv);
static int sun8i_dwmac_init(struct platform_device *pdev, void *priv) static int sun8i_dwmac_init(struct platform_device *pdev, void *priv)
{ {
struct net_device *ndev = platform_get_drvdata(pdev);
struct sunxi_priv_data *gmac = priv; struct sunxi_priv_data *gmac = priv;
int ret; int ret;
@ -554,13 +559,25 @@ static int sun8i_dwmac_init(struct platform_device *pdev, void *priv)
ret = clk_prepare_enable(gmac->tx_clk); ret = clk_prepare_enable(gmac->tx_clk);
if (ret) { if (ret) {
if (gmac->regulator)
regulator_disable(gmac->regulator);
dev_err(&pdev->dev, "Could not enable AHB clock\n"); dev_err(&pdev->dev, "Could not enable AHB clock\n");
return ret; goto err_disable_regulator;
}
if (gmac->use_internal_phy) {
ret = sun8i_dwmac_power_internal_phy(netdev_priv(ndev));
if (ret)
goto err_disable_clk;
} }
return 0; return 0;
err_disable_clk:
clk_disable_unprepare(gmac->tx_clk);
err_disable_regulator:
if (gmac->regulator)
regulator_disable(gmac->regulator);
return ret;
} }
static void sun8i_dwmac_core_init(struct mac_device_info *hw, static void sun8i_dwmac_core_init(struct mac_device_info *hw,
@ -831,7 +848,6 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child,
struct sunxi_priv_data *gmac = priv->plat->bsp_priv; struct sunxi_priv_data *gmac = priv->plat->bsp_priv;
u32 reg, val; u32 reg, val;
int ret = 0; int ret = 0;
bool need_power_ephy = false;
if (current_child ^ desired_child) { if (current_child ^ desired_child) {
regmap_field_read(gmac->regmap_field, &reg); regmap_field_read(gmac->regmap_field, &reg);
@ -839,13 +855,12 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child,
case DWMAC_SUN8I_MDIO_MUX_INTERNAL_ID: case DWMAC_SUN8I_MDIO_MUX_INTERNAL_ID:
dev_info(priv->device, "Switch mux to internal PHY"); dev_info(priv->device, "Switch mux to internal PHY");
val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SELECT; val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SELECT;
gmac->use_internal_phy = true;
need_power_ephy = true;
break; break;
case DWMAC_SUN8I_MDIO_MUX_EXTERNAL_ID: case DWMAC_SUN8I_MDIO_MUX_EXTERNAL_ID:
dev_info(priv->device, "Switch mux to external PHY"); dev_info(priv->device, "Switch mux to external PHY");
val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SHUTDOWN; val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SHUTDOWN;
need_power_ephy = false; gmac->use_internal_phy = false;
break; break;
default: default:
dev_err(priv->device, "Invalid child ID %x\n", dev_err(priv->device, "Invalid child ID %x\n",
@ -853,7 +868,7 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child,
return -EINVAL; return -EINVAL;
} }
regmap_field_write(gmac->regmap_field, val); regmap_field_write(gmac->regmap_field, val);
if (need_power_ephy) { if (gmac->use_internal_phy) {
ret = sun8i_dwmac_power_internal_phy(priv); ret = sun8i_dwmac_power_internal_phy(priv);
if (ret) if (ret)
return ret; return ret;
@ -1004,17 +1019,12 @@ static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv)
struct sunxi_priv_data *gmac = priv; struct sunxi_priv_data *gmac = priv;
if (gmac->variant->soc_has_internal_phy) { if (gmac->variant->soc_has_internal_phy) {
/* sun8i_dwmac_exit could be called with mdiomux uninit */
if (gmac->mux_handle)
mdio_mux_uninit(gmac->mux_handle);
if (gmac->internal_phy_powered) if (gmac->internal_phy_powered)
sun8i_dwmac_unpower_internal_phy(gmac); sun8i_dwmac_unpower_internal_phy(gmac);
} }
sun8i_dwmac_unset_syscon(gmac); sun8i_dwmac_unset_syscon(gmac);
reset_control_put(gmac->rst_ephy);
clk_disable_unprepare(gmac->tx_clk); clk_disable_unprepare(gmac->tx_clk);
if (gmac->regulator) if (gmac->regulator)
@ -1243,12 +1253,32 @@ static int sun8i_dwmac_probe(struct platform_device *pdev)
return ret; return ret;
dwmac_mux: dwmac_mux:
reset_control_put(gmac->rst_ephy);
clk_put(gmac->ephy_clk);
sun8i_dwmac_unset_syscon(gmac); sun8i_dwmac_unset_syscon(gmac);
dwmac_exit: dwmac_exit:
stmmac_pltfr_remove(pdev); stmmac_pltfr_remove(pdev);
return ret; return ret;
} }
static int sun8i_dwmac_remove(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev);
struct sunxi_priv_data *gmac = priv->plat->bsp_priv;
if (gmac->variant->soc_has_internal_phy) {
mdio_mux_uninit(gmac->mux_handle);
sun8i_dwmac_unpower_internal_phy(gmac);
reset_control_put(gmac->rst_ephy);
clk_put(gmac->ephy_clk);
}
stmmac_pltfr_remove(pdev);
return 0;
}
static const struct of_device_id sun8i_dwmac_match[] = { static const struct of_device_id sun8i_dwmac_match[] = {
{ .compatible = "allwinner,sun8i-h3-emac", { .compatible = "allwinner,sun8i-h3-emac",
.data = &emac_variant_h3 }, .data = &emac_variant_h3 },
@ -1268,7 +1298,7 @@ MODULE_DEVICE_TABLE(of, sun8i_dwmac_match);
static struct platform_driver sun8i_dwmac_driver = { static struct platform_driver sun8i_dwmac_driver = {
.probe = sun8i_dwmac_probe, .probe = sun8i_dwmac_probe,
.remove = stmmac_pltfr_remove, .remove = sun8i_dwmac_remove,
.driver = { .driver = {
.name = "dwmac-sun8i", .name = "dwmac-sun8i",
.pm = &stmmac_pltfr_pm_ops, .pm = &stmmac_pltfr_pm_ops,

View File

@ -1126,7 +1126,10 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
* accordingly. Otherwise, we should check here. * accordingly. Otherwise, we should check here.
*/ */
if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)
delayed_ndp_size = ALIGN(ctx->max_ndp_size, ctx->tx_ndp_modulus); delayed_ndp_size = ctx->max_ndp_size +
max_t(u32,
ctx->tx_ndp_modulus,
ctx->tx_modulus + ctx->tx_remainder) - 1;
else else
delayed_ndp_size = 0; delayed_ndp_size = 0;
@ -1307,7 +1310,8 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
if (!(dev->driver_info->flags & FLAG_SEND_ZLP) && if (!(dev->driver_info->flags & FLAG_SEND_ZLP) &&
skb_out->len > ctx->min_tx_pkt) { skb_out->len > ctx->min_tx_pkt) {
padding_count = ctx->tx_curr_size - skb_out->len; padding_count = ctx->tx_curr_size - skb_out->len;
skb_put_zero(skb_out, padding_count); if (!WARN_ON(padding_count > ctx->tx_curr_size))
skb_put_zero(skb_out, padding_count);
} else if (skb_out->len < ctx->tx_curr_size && } else if (skb_out->len < ctx->tx_curr_size &&
(skb_out->len % dev->maxpacket) == 0) { (skb_out->len % dev->maxpacket) == 0) {
skb_put_u8(skb_out, 0); /* force short packet */ skb_put_u8(skb_out, 0); /* force short packet */

View File

@ -282,6 +282,7 @@ config SLIC_DS26522
tristate "Slic Maxim ds26522 card support" tristate "Slic Maxim ds26522 card support"
depends on SPI depends on SPI
depends on FSL_SOC || ARCH_MXC || ARCH_LAYERSCAPE || COMPILE_TEST depends on FSL_SOC || ARCH_MXC || ARCH_LAYERSCAPE || COMPILE_TEST
select BITREVERSE
help help
This module initializes and configures the slic maxim card This module initializes and configures the slic maxim card
in T1 or E1 mode. in T1 or E1 mode.

View File

@ -2,6 +2,7 @@
config WIL6210 config WIL6210
tristate "Wilocity 60g WiFi card wil6210 support" tristate "Wilocity 60g WiFi card wil6210 support"
select WANT_DEV_COREDUMP select WANT_DEV_COREDUMP
select CRC32
depends on CFG80211 depends on CFG80211
depends on PCI depends on PCI
default n default n

View File

@ -726,7 +726,7 @@ static const struct rpmh_vreg_hw_data pmic5_ftsmps510 = {
static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = { static const struct rpmh_vreg_hw_data pmic5_hfsmps515 = {
.regulator_type = VRM, .regulator_type = VRM,
.ops = &rpmh_regulator_vrm_ops, .ops = &rpmh_regulator_vrm_ops,
.voltage_range = REGULATOR_LINEAR_RANGE(2800000, 0, 4, 1600), .voltage_range = REGULATOR_LINEAR_RANGE(2800000, 0, 4, 16000),
.n_voltages = 5, .n_voltages = 5,
.pmic_mode_map = pmic_mode_map_pmic5_smps, .pmic_mode_map = pmic_mode_map_pmic5_smps,
.of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode, .of_map_mode = rpmh_regulator_pmic4_smps_of_map_mode,

View File

@ -2114,7 +2114,7 @@ static netdev_features_t qeth_l3_osa_features_check(struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
netdev_features_t features) netdev_features_t features)
{ {
if (qeth_get_ip_version(skb) != 4) if (vlan_get_protocol(skb) != htons(ETH_P_IP))
features &= ~NETIF_F_HW_VLAN_CTAG_TX; features &= ~NETIF_F_HW_VLAN_CTAG_TX;
return qeth_features_check(skb, dev, features); return qeth_features_check(skb, dev, features);
} }

View File

@ -494,9 +494,9 @@ static u32 stm32h7_spi_prepare_fthlv(struct stm32_spi *spi, u32 xfer_len)
/* align packet size with data registers access */ /* align packet size with data registers access */
if (spi->cur_bpw > 8) if (spi->cur_bpw > 8)
fthlv -= (fthlv % 2); /* multiple of 2 */ fthlv += (fthlv % 2) ? 1 : 0;
else else
fthlv -= (fthlv % 4); /* multiple of 4 */ fthlv += (fthlv % 4) ? (4 - (fthlv % 4)) : 0;
if (!fthlv) if (!fthlv)
fthlv = 1; fthlv = 1;

View File

@ -59,7 +59,7 @@ static void exfat_write_super(struct super_block *sb);
/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */ /* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */
static void exfat_time_fat2unix(struct timespec64 *ts, struct date_time_t *tp) static void exfat_time_fat2unix(struct timespec64 *ts, struct date_time_t *tp)
{ {
ts->tv_sec = mktime64(tp->Year + 1980, tp->Month + 1, tp->Day, ts->tv_sec = mktime64(tp->Year + 1980, tp->Month, tp->Day,
tp->Hour, tp->Minute, tp->Second); tp->Hour, tp->Minute, tp->Second);
ts->tv_nsec = tp->MilliSecond * NSEC_PER_MSEC; ts->tv_nsec = tp->MilliSecond * NSEC_PER_MSEC;

View File

@ -2303,6 +2303,24 @@ out_unlock:
return ret; return ret;
} }
static int vfio_iommu_dma_avail_build_caps(struct vfio_iommu *iommu,
struct vfio_info_cap *caps)
{
struct vfio_iommu_type1_info_dma_avail cap_dma_avail;
int ret;
mutex_lock(&iommu->lock);
cap_dma_avail.header.id = VFIO_IOMMU_TYPE1_INFO_DMA_AVAIL;
cap_dma_avail.header.version = 1;
cap_dma_avail.avail = iommu->dma_avail;
ret = vfio_info_add_capability(caps, &cap_dma_avail.header,
sizeof(cap_dma_avail));
mutex_unlock(&iommu->lock);
return ret;
}
static long vfio_iommu_type1_ioctl(void *iommu_data, static long vfio_iommu_type1_ioctl(void *iommu_data,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
@ -2349,6 +2367,10 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
info.iova_pgsizes = vfio_pgsize_bitmap(iommu); info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
ret = vfio_iommu_iova_build_caps(iommu, &caps); ret = vfio_iommu_iova_build_caps(iommu, &caps);
if (!ret)
ret = vfio_iommu_dma_avail_build_caps(iommu, &caps);
if (ret) if (ret)
return ret; return ret;

View File

@ -520,7 +520,10 @@
*/ */
#define TEXT_TEXT \ #define TEXT_TEXT \
ALIGN_FUNCTION(); \ ALIGN_FUNCTION(); \
*(.text.hot TEXT_MAIN .text.fixup .text.unlikely) \ *(.text.hot .text.hot.*) \
*(TEXT_MAIN .text.fixup) \
*(.text.unlikely .text.unlikely.*) \
*(.text.unknown .text.unknown.*) \
*(.text..refcount) \ *(.text..refcount) \
*(.ref.text) \ *(.ref.text) \
MEM_KEEP(init.text*) \ MEM_KEEP(init.text*) \

View File

@ -749,6 +749,21 @@ struct vfio_iommu_type1_info_cap_iova_range {
struct vfio_iova_range iova_ranges[]; struct vfio_iova_range iova_ranges[];
}; };
/*
* The DMA available capability allows to report the current number of
* simultaneously outstanding DMA mappings that are allowed.
*
* The structure below defines version 1 of this capability.
*
* avail: specifies the current number of outstanding DMA mappings allowed.
*/
#define VFIO_IOMMU_TYPE1_INFO_DMA_AVAIL 3
struct vfio_iommu_type1_info_dma_avail {
struct vfio_info_cap_header header;
__u32 avail;
};
#define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12) #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12)
/** /**

View File

@ -280,7 +280,8 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
return 0; return 0;
out_free_newdev: out_free_newdev:
if (new_dev->reg_state == NETREG_UNINITIALIZED) if (new_dev->reg_state == NETREG_UNINITIALIZED ||
new_dev->reg_state == NETREG_UNREGISTERED)
free_netdev(new_dev); free_netdev(new_dev);
return err; return err;
} }

View File

@ -2043,6 +2043,12 @@ int pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len)
skb->csum = csum_block_sub(skb->csum, skb->csum = csum_block_sub(skb->csum,
skb_checksum(skb, len, delta, 0), skb_checksum(skb, len, delta, 0),
len); len);
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
int hdlen = (len > skb_headlen(skb)) ? skb_headlen(skb) : len;
int offset = skb_checksum_start_offset(skb) + skb->csum_offset;
if (offset + sizeof(__sum16) > hdlen)
return -EINVAL;
} }
return __pskb_trim(skb, len); return __pskb_trim(skb, len);
} }

View File

@ -303,7 +303,7 @@ static int __ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *
if (skb_is_gso(skb)) if (skb_is_gso(skb))
return ip_finish_output_gso(net, sk, skb, mtu); return ip_finish_output_gso(net, sk, skb, mtu);
if (skb->len > mtu || (IPCB(skb)->flags & IPSKB_FRAG_PMTU)) if (skb->len > mtu || IPCB(skb)->frag_max_size)
return ip_fragment(net, sk, skb, mtu, ip_finish_output2); return ip_fragment(net, sk, skb, mtu, ip_finish_output2);
return ip_finish_output2(net, sk, skb); return ip_finish_output2(net, sk, skb);

View File

@ -765,8 +765,11 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
goto tx_error; goto tx_error;
} }
if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off, inner_iph, df = tnl_params->frag_off;
0, 0, false)) { if (skb->protocol == htons(ETH_P_IP) && !tunnel->ignore_df)
df |= (inner_iph->frag_off & htons(IP_DF));
if (tnl_update_pmtu(dev, skb, rt, df, inner_iph, 0, 0, false)) {
ip_rt_put(rt); ip_rt_put(rt);
goto tx_error; goto tx_error;
} }
@ -794,10 +797,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
ttl = ip4_dst_hoplimit(&rt->dst); ttl = ip4_dst_hoplimit(&rt->dst);
} }
df = tnl_params->frag_off;
if (skb->protocol == htons(ETH_P_IP) && !tunnel->ignore_df)
df |= (inner_iph->frag_off&htons(IP_DF));
max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr) max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr)
+ rt->dst.header_len + ip_encap_hlen(&tunnel->encap); + rt->dst.header_len + ip_encap_hlen(&tunnel->encap);
if (max_headroom > dev->needed_headroom) if (max_headroom > dev->needed_headroom)

View File

@ -1157,8 +1157,10 @@ static struct nexthop *nexthop_create_group(struct net *net,
return nh; return nh;
out_no_nh: out_no_nh:
for (; i >= 0; --i) for (i--; i >= 0; --i) {
list_del(&nhg->nh_entries[i].nh_list);
nexthop_put(nhg->nh_entries[i].nh); nexthop_put(nhg->nh_entries[i].nh);
}
kfree(nhg->spare); kfree(nhg->spare);
kfree(nhg); kfree(nhg);

View File

@ -973,6 +973,8 @@ static void fib6_purge_rt(struct fib6_info *rt, struct fib6_node *fn,
{ {
struct fib6_table *table = rt->fib6_table; struct fib6_table *table = rt->fib6_table;
/* Flush all cached dst in exception table */
rt6_flush_exceptions(rt);
fib6_drop_pcpu_from(rt, table); fib6_drop_pcpu_from(rt, table);
if (rt->nh && !list_empty(&rt->nh_list)) if (rt->nh && !list_empty(&rt->nh_list))
@ -1839,9 +1841,6 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn,
net->ipv6.rt6_stats->fib_rt_entries--; net->ipv6.rt6_stats->fib_rt_entries--;
net->ipv6.rt6_stats->fib_discarded_routes++; net->ipv6.rt6_stats->fib_discarded_routes++;
/* Flush all cached dst in exception table */
rt6_flush_exceptions(rt);
/* Reset round-robin state, if necessary */ /* Reset round-robin state, if necessary */
if (rcu_access_pointer(fn->rr_ptr) == rt) if (rcu_access_pointer(fn->rr_ptr) == rt)
fn->rr_ptr = NULL; fn->rr_ptr = NULL;

View File

@ -9,7 +9,6 @@
#include <unistd.h> #include <unistd.h>
#include <libbpf.h> #include <libbpf.h>
#include <net/if.h> #include <net/if.h>
#include <linux/if.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/tc_act/tc_bpf.h> #include <linux/tc_act/tc_bpf.h>
#include <sys/socket.h> #include <sys/socket.h>

View File

@ -119,7 +119,15 @@
# - list_flush_ipv6_exception # - list_flush_ipv6_exception
# Using the same topology as in pmtu_ipv6, create exceptions, and check # Using the same topology as in pmtu_ipv6, create exceptions, and check
# they are shown when listing exception caches, gone after flushing them # they are shown when listing exception caches, gone after flushing them
#
# - pmtu_ipv4_route_change
# Use the same topology as in pmtu_ipv4, but issue a route replacement
# command and delete the corresponding device afterward. This tests for
# proper cleanup of the PMTU exceptions by the route replacement path.
# Device unregistration should complete successfully
#
# - pmtu_ipv6_route_change
# Same as above but with IPv6
# Kselftest framework requirement - SKIP code is 4. # Kselftest framework requirement - SKIP code is 4.
ksft_skip=4 ksft_skip=4
@ -161,7 +169,9 @@ tests="
cleanup_ipv4_exception ipv4: cleanup of cached exceptions 1 cleanup_ipv4_exception ipv4: cleanup of cached exceptions 1
cleanup_ipv6_exception ipv6: cleanup of cached exceptions 1 cleanup_ipv6_exception ipv6: cleanup of cached exceptions 1
list_flush_ipv4_exception ipv4: list and flush cached exceptions 1 list_flush_ipv4_exception ipv4: list and flush cached exceptions 1
list_flush_ipv6_exception ipv6: list and flush cached exceptions 1" list_flush_ipv6_exception ipv6: list and flush cached exceptions 1
pmtu_ipv4_route_change ipv4: PMTU exception w/route replace 1
pmtu_ipv6_route_change ipv6: PMTU exception w/route replace 1"
NS_A="ns-A" NS_A="ns-A"
NS_B="ns-B" NS_B="ns-B"
@ -1316,6 +1326,63 @@ test_list_flush_ipv6_exception() {
return ${fail} return ${fail}
} }
test_pmtu_ipvX_route_change() {
family=${1}
setup namespaces routing || return 2
trace "${ns_a}" veth_A-R1 "${ns_r1}" veth_R1-A \
"${ns_r1}" veth_R1-B "${ns_b}" veth_B-R1 \
"${ns_a}" veth_A-R2 "${ns_r2}" veth_R2-A \
"${ns_r2}" veth_R2-B "${ns_b}" veth_B-R2
if [ ${family} -eq 4 ]; then
ping=ping
dst1="${prefix4}.${b_r1}.1"
dst2="${prefix4}.${b_r2}.1"
gw="${prefix4}.${a_r1}.2"
else
ping=${ping6}
dst1="${prefix6}:${b_r1}::1"
dst2="${prefix6}:${b_r2}::1"
gw="${prefix6}:${a_r1}::2"
fi
# Set up initial MTU values
mtu "${ns_a}" veth_A-R1 2000
mtu "${ns_r1}" veth_R1-A 2000
mtu "${ns_r1}" veth_R1-B 1400
mtu "${ns_b}" veth_B-R1 1400
mtu "${ns_a}" veth_A-R2 2000
mtu "${ns_r2}" veth_R2-A 2000
mtu "${ns_r2}" veth_R2-B 1500
mtu "${ns_b}" veth_B-R2 1500
# Create route exceptions
run_cmd ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s 1800 ${dst1}
run_cmd ${ns_a} ${ping} -q -M want -i 0.1 -w 1 -s 1800 ${dst2}
# Check that exceptions have been created with the correct PMTU
pmtu_1="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst1})"
check_pmtu_value "1400" "${pmtu_1}" "exceeding MTU" || return 1
pmtu_2="$(route_get_dst_pmtu_from_exception "${ns_a}" ${dst2})"
check_pmtu_value "1500" "${pmtu_2}" "exceeding MTU" || return 1
# Replace the route from A to R1
run_cmd ${ns_a} ip route change default via ${gw}
# Delete the device in A
run_cmd ${ns_a} ip link del "veth_A-R1"
}
test_pmtu_ipv4_route_change() {
test_pmtu_ipvX_route_change 4
}
test_pmtu_ipv6_route_change() {
test_pmtu_ipvX_route_change 6
}
usage() { usage() {
echo echo
echo "$0 [OPTIONS] [TEST]..." echo "$0 [OPTIONS] [TEST]..."