From: Sasha Levin Date: Fri, 8 Dec 2023 10:04:30 +0000 (-0500) Subject: Fixes for 4.19 X-Git-Tag: v6.6.6~59 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d182bfeabab36deb77e04c643b5705d93f8e2a87;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 4.19 Signed-off-by: Sasha Levin --- diff --git a/queue-4.19/block-introduce-multi-page-bvec-helpers.patch b/queue-4.19/block-introduce-multi-page-bvec-helpers.patch new file mode 100644 index 00000000000..cf9f6c20926 --- /dev/null +++ b/queue-4.19/block-introduce-multi-page-bvec-helpers.patch @@ -0,0 +1,117 @@ +From 8ae400c0add40e6d7fd80c616b3f6f7974b2f254 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Feb 2019 19:13:10 +0800 +Subject: block: introduce multi-page bvec helpers + +From: Ming Lei + +[ Upstream commit 3d75ca0adef4280650c6690a0c4702a74a6f3c95 ] + +This patch introduces helpers of 'mp_bvec_iter_*' for multi-page bvec +support. + +The introduced helpers treate one bvec as real multi-page segment, +which may include more than one pages. + +The existed helpers of bvec_iter_* are interfaces for supporting current +bvec iterator which is thought as single-page by drivers, fs, dm and +etc. These introduced helpers will build single-page bvec in flight, so +this way won't break current bio/bvec users, which needn't any change. + +Follows some multi-page bvec background: + +- bvecs stored in bio->bi_io_vec is always multi-page style + +- bvec(struct bio_vec) represents one physically contiguous I/O + buffer, now the buffer may include more than one page after + multi-page bvec is supported, and all these pages represented + by one bvec is physically contiguous. Before multi-page bvec + support, at most one page is included in one bvec, we call it + single-page bvec. + +- .bv_page of the bvec points to the 1st page in the multi-page bvec + +- .bv_offset of the bvec is the offset of the buffer in the bvec + +The effect on the current drivers/filesystem/dm/bcache/...: + +- almost everyone supposes that one bvec only includes one single + page, so we keep the sp interface not changed, for example, + bio_for_each_segment() still returns single-page bvec + +- bio_for_each_segment_all() will return single-page bvec too + +- during iterating, iterator variable(struct bvec_iter) is always + updated in multi-page bvec style, and bvec_iter_advance() is kept + not changed + +- returned(copied) single-page bvec is built in flight by bvec + helpers from the stored multi-page bvec + +Reviewed-by: Christoph Hellwig +Reviewed-by: Omar Sandoval +Signed-off-by: Ming Lei +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + include/linux/bvec.h | 30 +++++++++++++++++++++++++++--- + 1 file changed, 27 insertions(+), 3 deletions(-) + +diff --git a/include/linux/bvec.h b/include/linux/bvec.h +index bc1f16e9f3f4d..cd43c03e31129 100644 +--- a/include/linux/bvec.h ++++ b/include/linux/bvec.h +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + /* + * was unsigned short, but we might as well be ready for > 64kB I/O pages +@@ -52,16 +53,39 @@ struct bvec_iter { + */ + #define __bvec_iter_bvec(bvec, iter) (&(bvec)[(iter).bi_idx]) + +-#define bvec_iter_page(bvec, iter) \ ++/* multi-page (mp_bvec) helpers */ ++#define mp_bvec_iter_page(bvec, iter) \ + (__bvec_iter_bvec((bvec), (iter))->bv_page) + +-#define bvec_iter_len(bvec, iter) \ ++#define mp_bvec_iter_len(bvec, iter) \ + min((iter).bi_size, \ + __bvec_iter_bvec((bvec), (iter))->bv_len - (iter).bi_bvec_done) + +-#define bvec_iter_offset(bvec, iter) \ ++#define mp_bvec_iter_offset(bvec, iter) \ + (__bvec_iter_bvec((bvec), (iter))->bv_offset + (iter).bi_bvec_done) + ++#define mp_bvec_iter_page_idx(bvec, iter) \ ++ (mp_bvec_iter_offset((bvec), (iter)) / PAGE_SIZE) ++ ++#define mp_bvec_iter_bvec(bvec, iter) \ ++((struct bio_vec) { \ ++ .bv_page = mp_bvec_iter_page((bvec), (iter)), \ ++ .bv_len = mp_bvec_iter_len((bvec), (iter)), \ ++ .bv_offset = mp_bvec_iter_offset((bvec), (iter)), \ ++}) ++ ++/* For building single-page bvec in flight */ ++ #define bvec_iter_offset(bvec, iter) \ ++ (mp_bvec_iter_offset((bvec), (iter)) % PAGE_SIZE) ++ ++#define bvec_iter_len(bvec, iter) \ ++ min_t(unsigned, mp_bvec_iter_len((bvec), (iter)), \ ++ PAGE_SIZE - bvec_iter_offset((bvec), (iter))) ++ ++#define bvec_iter_page(bvec, iter) \ ++ nth_page(mp_bvec_iter_page((bvec), (iter)), \ ++ mp_bvec_iter_page_idx((bvec), (iter))) ++ + #define bvec_iter_bvec(bvec, iter) \ + ((struct bio_vec) { \ + .bv_page = bvec_iter_page((bvec), (iter)), \ +-- +2.42.0 + diff --git a/queue-4.19/drm-amdgpu-correct-chunk_ptr-to-a-pointer-to-chunk.patch b/queue-4.19/drm-amdgpu-correct-chunk_ptr-to-a-pointer-to-chunk.patch new file mode 100644 index 00000000000..7327cb57c21 --- /dev/null +++ b/queue-4.19/drm-amdgpu-correct-chunk_ptr-to-a-pointer-to-chunk.patch @@ -0,0 +1,40 @@ +From cde4432152118ac85da2bbea2c07d5ab6266be48 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 31 Oct 2023 10:32:37 +0800 +Subject: drm/amdgpu: correct chunk_ptr to a pointer to chunk. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: YuanShang + +[ Upstream commit 50d51374b498457c4dea26779d32ccfed12ddaff ] + +The variable "chunk_ptr" should be a pointer pointing +to a struct drm_amdgpu_cs_chunk instead of to a pointer +of that. + +Signed-off-by: YuanShang +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +index 70e446c2acf82..94b06c918e80d 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +@@ -147,7 +147,7 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, union drm_amdgpu_cs + } + + for (i = 0; i < p->nchunks; i++) { +- struct drm_amdgpu_cs_chunk __user **chunk_ptr = NULL; ++ struct drm_amdgpu_cs_chunk __user *chunk_ptr = NULL; + struct drm_amdgpu_cs_chunk user_chunk; + uint32_t __user *cdata; + +-- +2.42.0 + diff --git a/queue-4.19/hrtimers-push-pending-hrtimers-away-from-outgoing-cp.patch b/queue-4.19/hrtimers-push-pending-hrtimers-away-from-outgoing-cp.patch new file mode 100644 index 00000000000..fc6accc7de9 --- /dev/null +++ b/queue-4.19/hrtimers-push-pending-hrtimers-away-from-outgoing-cp.patch @@ -0,0 +1,155 @@ +From 052a7117914ed4824dda3350818af593662d07ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Nov 2023 15:57:13 +0100 +Subject: hrtimers: Push pending hrtimers away from outgoing CPU earlier + +From: Thomas Gleixner + +[ Upstream commit 5c0930ccaad5a74d74e8b18b648c5eb21ed2fe94 ] + +2b8272ff4a70 ("cpu/hotplug: Prevent self deadlock on CPU hot-unplug") +solved the straight forward CPU hotplug deadlock vs. the scheduler +bandwidth timer. Yu discovered a more involved variant where a task which +has a bandwidth timer started on the outgoing CPU holds a lock and then +gets throttled. If the lock required by one of the CPU hotplug callbacks +the hotplug operation deadlocks because the unthrottling timer event is not +handled on the dying CPU and can only be recovered once the control CPU +reaches the hotplug state which pulls the pending hrtimers from the dead +CPU. + +Solve this by pushing the hrtimers away from the dying CPU in the dying +callbacks. Nothing can queue a hrtimer on the dying CPU at that point because +all other CPUs spin in stop_machine() with interrupts disabled and once the +operation is finished the CPU is marked offline. + +Reported-by: Yu Liao +Signed-off-by: Thomas Gleixner +Tested-by: Liu Tie +Link: https://lore.kernel.org/r/87a5rphara.ffs@tglx +Signed-off-by: Sasha Levin +--- + include/linux/cpuhotplug.h | 1 + + include/linux/hrtimer.h | 4 ++-- + kernel/cpu.c | 8 +++++++- + kernel/time/hrtimer.c | 33 ++++++++++++--------------------- + 4 files changed, 22 insertions(+), 24 deletions(-) + +diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h +index 71a0a5ffdbb1a..dd9f035be63f7 100644 +--- a/include/linux/cpuhotplug.h ++++ b/include/linux/cpuhotplug.h +@@ -139,6 +139,7 @@ enum cpuhp_state { + CPUHP_AP_ARM_CORESIGHT_STARTING, + CPUHP_AP_ARM64_ISNDEP_STARTING, + CPUHP_AP_SMPCFD_DYING, ++ CPUHP_AP_HRTIMERS_DYING, + CPUHP_AP_X86_TBOOT_DYING, + CPUHP_AP_ARM_CACHE_B15_RAC_DYING, + CPUHP_AP_ONLINE, +diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h +index 542b4fa2cda9b..3bdaa92a2cab3 100644 +--- a/include/linux/hrtimer.h ++++ b/include/linux/hrtimer.h +@@ -508,9 +508,9 @@ extern void sysrq_timer_list_show(void); + + int hrtimers_prepare_cpu(unsigned int cpu); + #ifdef CONFIG_HOTPLUG_CPU +-int hrtimers_dead_cpu(unsigned int cpu); ++int hrtimers_cpu_dying(unsigned int cpu); + #else +-#define hrtimers_dead_cpu NULL ++#define hrtimers_cpu_dying NULL + #endif + + #endif +diff --git a/kernel/cpu.c b/kernel/cpu.c +index c9ca190ec0347..34c09c3d37bc6 100644 +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -1418,7 +1418,7 @@ static struct cpuhp_step cpuhp_hp_states[] = { + [CPUHP_HRTIMERS_PREPARE] = { + .name = "hrtimers:prepare", + .startup.single = hrtimers_prepare_cpu, +- .teardown.single = hrtimers_dead_cpu, ++ .teardown.single = NULL, + }, + [CPUHP_SMPCFD_PREPARE] = { + .name = "smpcfd:prepare", +@@ -1485,6 +1485,12 @@ static struct cpuhp_step cpuhp_hp_states[] = { + .startup.single = NULL, + .teardown.single = smpcfd_dying_cpu, + }, ++ [CPUHP_AP_HRTIMERS_DYING] = { ++ .name = "hrtimers:dying", ++ .startup.single = NULL, ++ .teardown.single = hrtimers_cpu_dying, ++ }, ++ + /* Entry state on starting. Interrupts enabled from here on. Transient + * state for synchronsization */ + [CPUHP_AP_ONLINE] = { +diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c +index 8512f06f0ebef..bf74f43e42af0 100644 +--- a/kernel/time/hrtimer.c ++++ b/kernel/time/hrtimer.c +@@ -1922,29 +1922,22 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base, + } + } + +-int hrtimers_dead_cpu(unsigned int scpu) ++int hrtimers_cpu_dying(unsigned int dying_cpu) + { + struct hrtimer_cpu_base *old_base, *new_base; +- int i; ++ int i, ncpu = cpumask_first(cpu_active_mask); + +- BUG_ON(cpu_online(scpu)); +- tick_cancel_sched_timer(scpu); ++ tick_cancel_sched_timer(dying_cpu); ++ ++ old_base = this_cpu_ptr(&hrtimer_bases); ++ new_base = &per_cpu(hrtimer_bases, ncpu); + +- /* +- * this BH disable ensures that raise_softirq_irqoff() does +- * not wakeup ksoftirqd (and acquire the pi-lock) while +- * holding the cpu_base lock +- */ +- local_bh_disable(); +- local_irq_disable(); +- old_base = &per_cpu(hrtimer_bases, scpu); +- new_base = this_cpu_ptr(&hrtimer_bases); + /* + * The caller is globally serialized and nobody else + * takes two locks at once, deadlock is not possible. + */ +- raw_spin_lock(&new_base->lock); +- raw_spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING); ++ raw_spin_lock(&old_base->lock); ++ raw_spin_lock_nested(&new_base->lock, SINGLE_DEPTH_NESTING); + + for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) { + migrate_hrtimer_list(&old_base->clock_base[i], +@@ -1955,15 +1948,13 @@ int hrtimers_dead_cpu(unsigned int scpu) + * The migration might have changed the first expiring softirq + * timer on this CPU. Update it. + */ +- hrtimer_update_softirq_timer(new_base, false); ++ __hrtimer_get_next_event(new_base, HRTIMER_ACTIVE_SOFT); ++ /* Tell the other CPU to retrigger the next event */ ++ smp_call_function_single(ncpu, retrigger_next_event, NULL, 0); + +- raw_spin_unlock(&old_base->lock); + raw_spin_unlock(&new_base->lock); ++ raw_spin_unlock(&old_base->lock); + +- /* Check, if we got expired work to do */ +- __hrtimer_peek_ahead_timers(); +- local_irq_enable(); +- local_bh_enable(); + return 0; + } + +-- +2.42.0 + diff --git a/queue-4.19/kconfig-fix-memory-leak-from-range-properties.patch b/queue-4.19/kconfig-fix-memory-leak-from-range-properties.patch new file mode 100644 index 00000000000..0613ee7dfe4 --- /dev/null +++ b/queue-4.19/kconfig-fix-memory-leak-from-range-properties.patch @@ -0,0 +1,92 @@ +From 379bc3ff94894e35c07c93c50c1b75be94ef69e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Nov 2023 13:16:53 +0900 +Subject: kconfig: fix memory leak from range properties + +From: Masahiro Yamada + +[ Upstream commit ae1eff0349f2e908fc083630e8441ea6dc434dc0 ] + +Currently, sym_validate_range() duplicates the range string using +xstrdup(), which is overwritten by a subsequent sym_calc_value() call. +It results in a memory leak. + +Instead, only the pointer should be copied. + +Below is a test case, with a summary from Valgrind. + +[Test Kconfig] + + config FOO + int "foo" + range 10 20 + +[Test .config] + + CONFIG_FOO=0 + +[Before] + + LEAK SUMMARY: + definitely lost: 3 bytes in 1 blocks + indirectly lost: 0 bytes in 0 blocks + possibly lost: 0 bytes in 0 blocks + still reachable: 17,465 bytes in 21 blocks + suppressed: 0 bytes in 0 blocks + +[After] + + LEAK SUMMARY: + definitely lost: 0 bytes in 0 blocks + indirectly lost: 0 bytes in 0 blocks + possibly lost: 0 bytes in 0 blocks + still reachable: 17,462 bytes in 20 blocks + suppressed: 0 bytes in 0 blocks + +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + scripts/kconfig/symbol.c | 14 ++++++-------- + 1 file changed, 6 insertions(+), 8 deletions(-) + +diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c +index 703b9b899ee9c..5adb60b7e12f3 100644 +--- a/scripts/kconfig/symbol.c ++++ b/scripts/kconfig/symbol.c +@@ -119,9 +119,9 @@ static long long sym_get_range_val(struct symbol *sym, int base) + static void sym_validate_range(struct symbol *sym) + { + struct property *prop; ++ struct symbol *range_sym; + int base; + long long val, val2; +- char str[64]; + + switch (sym->type) { + case S_INT: +@@ -137,17 +137,15 @@ static void sym_validate_range(struct symbol *sym) + if (!prop) + return; + val = strtoll(sym->curr.val, NULL, base); +- val2 = sym_get_range_val(prop->expr->left.sym, base); ++ range_sym = prop->expr->left.sym; ++ val2 = sym_get_range_val(range_sym, base); + if (val >= val2) { +- val2 = sym_get_range_val(prop->expr->right.sym, base); ++ range_sym = prop->expr->right.sym; ++ val2 = sym_get_range_val(range_sym, base); + if (val <= val2) + return; + } +- if (sym->type == S_INT) +- sprintf(str, "%lld", val2); +- else +- sprintf(str, "0x%llx", val2); +- sym->curr.val = xstrdup(str); ++ sym->curr.val = range_sym->curr.val; + } + + static void sym_set_changed(struct symbol *sym) +-- +2.42.0 + diff --git a/queue-4.19/media-davinci-vpif_capture-fix-potential-double-free.patch b/queue-4.19/media-davinci-vpif_capture-fix-potential-double-free.patch new file mode 100644 index 00000000000..06fafb96f40 --- /dev/null +++ b/queue-4.19/media-davinci-vpif_capture-fix-potential-double-free.patch @@ -0,0 +1,40 @@ +From b0950ab9659e1e6f3a9191b2bf862e77a657fe93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jul 2020 19:04:53 +0200 +Subject: media: davinci: vpif_capture: fix potential double free + +From: Evgeny Novikov + +[ Upstream commit 602649eadaa0c977e362e641f51ec306bc1d365d ] + +In case of errors vpif_probe_complete() releases memory for vpif_obj.sd +and unregisters the V4L2 device. But then this is done again by +vpif_probe() itself. The patch removes the cleaning from +vpif_probe_complete(). + +Found by Linux Driver Verification project (linuxtesting.org). + +Signed-off-by: Evgeny Novikov +Signed-off-by: Hans Verkuil +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Sasha Levin +--- + drivers/media/platform/davinci/vpif_capture.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c +index a96f53ce80886..cf1d11e6dd8c4 100644 +--- a/drivers/media/platform/davinci/vpif_capture.c ++++ b/drivers/media/platform/davinci/vpif_capture.c +@@ -1489,8 +1489,6 @@ static int vpif_probe_complete(void) + /* Unregister video device */ + video_unregister_device(&ch->video_dev); + } +- kfree(vpif_obj.sd); +- v4l2_device_unregister(&vpif_obj.v4l2_dev); + + return err; + } +-- +2.42.0 + diff --git a/queue-4.19/netfilter-ipset-fix-race-condition-between-swap-dest.patch b/queue-4.19/netfilter-ipset-fix-race-condition-between-swap-dest.patch new file mode 100644 index 00000000000..238e55b8de8 --- /dev/null +++ b/queue-4.19/netfilter-ipset-fix-race-condition-between-swap-dest.patch @@ -0,0 +1,105 @@ +From 98d22c406779c2cb93568db16dbad8c6a4d3a0f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Nov 2023 21:13:23 +0100 +Subject: netfilter: ipset: fix race condition between swap/destroy and kernel + side add/del/test + +From: Jozsef Kadlecsik + +[ Upstream commit 28628fa952fefc7f2072ce6e8016968cc452b1ba ] + +Linkui Xiao reported that there's a race condition when ipset swap and destroy is +called, which can lead to crash in add/del/test element operations. Swap then +destroy are usual operations to replace a set with another one in a production +system. The issue can in some cases be reproduced with the script: + +ipset create hash_ip1 hash:net family inet hashsize 1024 maxelem 1048576 +ipset add hash_ip1 172.20.0.0/16 +ipset add hash_ip1 192.168.0.0/16 +iptables -A INPUT -m set --match-set hash_ip1 src -j ACCEPT +while [ 1 ] +do + # ... Ongoing traffic... + ipset create hash_ip2 hash:net family inet hashsize 1024 maxelem 1048576 + ipset add hash_ip2 172.20.0.0/16 + ipset swap hash_ip1 hash_ip2 + ipset destroy hash_ip2 + sleep 0.05 +done + +In the race case the possible order of the operations are + + CPU0 CPU1 + ip_set_test + ipset swap hash_ip1 hash_ip2 + ipset destroy hash_ip2 + hash_net_kadt + +Swap replaces hash_ip1 with hash_ip2 and then destroy removes hash_ip2 which +is the original hash_ip1. ip_set_test was called on hash_ip1 and because destroy +removed it, hash_net_kadt crashes. + +The fix is to force ip_set_swap() to wait for all readers to finish accessing the +old set pointers by calling synchronize_rcu(). + +The first version of the patch was written by Linkui Xiao . + +v2: synchronize_rcu() is moved into ip_set_swap() in order not to burden + ip_set_destroy() unnecessarily when all sets are destroyed. +v3: Florian Westphal pointed out that all netfilter hooks run with rcu_read_lock() held + and em_ipset.c wraps the entire ip_set_test() in rcu read lock/unlock pair. + So there's no need to extend the rcu read locked area in ipset itself. + +Closes: https://lore.kernel.org/all/69e7963b-e7f8-3ad0-210-7b86eebf7f78@netfilter.org/ +Reported by: Linkui Xiao +Signed-off-by: Jozsef Kadlecsik +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/ipset/ip_set_core.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c +index 31756d1bf83e7..031bb83aed70a 100644 +--- a/net/netfilter/ipset/ip_set_core.c ++++ b/net/netfilter/ipset/ip_set_core.c +@@ -64,6 +64,8 @@ MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET); + ip_set_dereference((inst)->ip_set_list)[id] + #define ip_set_ref_netlink(inst,id) \ + rcu_dereference_raw((inst)->ip_set_list)[id] ++#define ip_set_dereference_nfnl(p) \ ++ rcu_dereference_check(p, lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET)) + + /* The set types are implemented in modules and registered set types + * can be found in ip_set_type_list. Adding/deleting types is +@@ -552,15 +554,10 @@ __ip_set_put_netlink(struct ip_set *set) + static inline struct ip_set * + ip_set_rcu_get(struct net *net, ip_set_id_t index) + { +- struct ip_set *set; + struct ip_set_net *inst = ip_set_pernet(net); + +- rcu_read_lock(); +- /* ip_set_list itself needs to be protected */ +- set = rcu_dereference(inst->ip_set_list)[index]; +- rcu_read_unlock(); +- +- return set; ++ /* ip_set_list and the set pointer need to be protected */ ++ return ip_set_dereference_nfnl(inst->ip_set_list)[index]; + } + + int +@@ -1227,6 +1224,9 @@ static int ip_set_swap(struct net *net, struct sock *ctnl, struct sk_buff *skb, + ip_set(inst, to_id) = from; + write_unlock_bh(&ip_set_ref_lock); + ++ /* Make sure all readers of the old set pointers are completed. */ ++ synchronize_rcu(); ++ + return 0; + } + +-- +2.42.0 + diff --git a/queue-4.19/series b/queue-4.19/series new file mode 100644 index 00000000000..b9b74ddcfa5 --- /dev/null +++ b/queue-4.19/series @@ -0,0 +1,12 @@ +spi-imx-add-a-device-specific-prepare_message-callba.patch +spi-imx-move-wml-setting-to-later-than-setup_transfe.patch +spi-imx-correct-wml-as-the-last-sg-length.patch +spi-imx-mx51-ecspi-move-some-initialisation-to-prepa.patch +media-davinci-vpif_capture-fix-potential-double-free.patch +block-introduce-multi-page-bvec-helpers.patch +hrtimers-push-pending-hrtimers-away-from-outgoing-cp.patch +netfilter-ipset-fix-race-condition-between-swap-dest.patch +tg3-move-the-rt-x_dropped-counters-to-tg3_napi.patch +tg3-increment-tx_dropped-in-tg3_tso_bug.patch +kconfig-fix-memory-leak-from-range-properties.patch +drm-amdgpu-correct-chunk_ptr-to-a-pointer-to-chunk.patch diff --git a/queue-4.19/spi-imx-add-a-device-specific-prepare_message-callba.patch b/queue-4.19/spi-imx-add-a-device-specific-prepare_message-callba.patch new file mode 100644 index 00000000000..248573afffc --- /dev/null +++ b/queue-4.19/spi-imx-add-a-device-specific-prepare_message-callba.patch @@ -0,0 +1,162 @@ +From b19a3770ce84da3c16acc7142e754cd8ff80ad3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Nov 2018 07:47:05 +0100 +Subject: spi: imx: add a device specific prepare_message callback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit e697271c4e2987b333148e16a2eb8b5b924fd40a ] + +This is just preparatory work which allows to move some initialisation +that currently is done in the per transfer hook .config to an earlier +point in time in the next few patches. There is no change in behaviour +introduced by this patch. + +Signed-off-by: Uwe Kleine-König +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-imx.c | 40 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 39 insertions(+), 1 deletion(-) + +diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c +index 1ad4b69292ad8..eb27f47578eb9 100644 +--- a/drivers/spi/spi-imx.c ++++ b/drivers/spi/spi-imx.c +@@ -59,6 +59,7 @@ struct spi_imx_data; + + struct spi_imx_devtype_data { + void (*intctrl)(struct spi_imx_data *, int); ++ int (*prepare_message)(struct spi_imx_data *, struct spi_message *); + int (*config)(struct spi_device *); + void (*trigger)(struct spi_imx_data *); + int (*rx_available)(struct spi_imx_data *); +@@ -502,6 +503,12 @@ static void mx51_ecspi_disable(struct spi_imx_data *spi_imx) + writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); + } + ++static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, ++ struct spi_message *msg) ++{ ++ return 0; ++} ++ + static int mx51_ecspi_config(struct spi_device *spi) + { + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); +@@ -672,6 +679,12 @@ static void mx31_trigger(struct spi_imx_data *spi_imx) + writel(reg, spi_imx->base + MXC_CSPICTRL); + } + ++static int mx31_prepare_message(struct spi_imx_data *spi_imx, ++ struct spi_message *msg) ++{ ++ return 0; ++} ++ + static int mx31_config(struct spi_device *spi) + { + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); +@@ -768,6 +781,12 @@ static void mx21_trigger(struct spi_imx_data *spi_imx) + writel(reg, spi_imx->base + MXC_CSPICTRL); + } + ++static int mx21_prepare_message(struct spi_imx_data *spi_imx, ++ struct spi_message *msg) ++{ ++ return 0; ++} ++ + static int mx21_config(struct spi_device *spi) + { + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); +@@ -837,6 +856,12 @@ static void mx1_trigger(struct spi_imx_data *spi_imx) + writel(reg, spi_imx->base + MXC_CSPICTRL); + } + ++static int mx1_prepare_message(struct spi_imx_data *spi_imx, ++ struct spi_message *msg) ++{ ++ return 0; ++} ++ + static int mx1_config(struct spi_device *spi) + { + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); +@@ -871,6 +896,7 @@ static void mx1_reset(struct spi_imx_data *spi_imx) + + static struct spi_imx_devtype_data imx1_cspi_devtype_data = { + .intctrl = mx1_intctrl, ++ .prepare_message = mx1_prepare_message, + .config = mx1_config, + .trigger = mx1_trigger, + .rx_available = mx1_rx_available, +@@ -884,6 +910,7 @@ static struct spi_imx_devtype_data imx1_cspi_devtype_data = { + + static struct spi_imx_devtype_data imx21_cspi_devtype_data = { + .intctrl = mx21_intctrl, ++ .prepare_message = mx21_prepare_message, + .config = mx21_config, + .trigger = mx21_trigger, + .rx_available = mx21_rx_available, +@@ -898,6 +925,7 @@ static struct spi_imx_devtype_data imx21_cspi_devtype_data = { + static struct spi_imx_devtype_data imx27_cspi_devtype_data = { + /* i.mx27 cspi shares the functions with i.mx21 one */ + .intctrl = mx21_intctrl, ++ .prepare_message = mx21_prepare_message, + .config = mx21_config, + .trigger = mx21_trigger, + .rx_available = mx21_rx_available, +@@ -911,6 +939,7 @@ static struct spi_imx_devtype_data imx27_cspi_devtype_data = { + + static struct spi_imx_devtype_data imx31_cspi_devtype_data = { + .intctrl = mx31_intctrl, ++ .prepare_message = mx31_prepare_message, + .config = mx31_config, + .trigger = mx31_trigger, + .rx_available = mx31_rx_available, +@@ -925,6 +954,7 @@ static struct spi_imx_devtype_data imx31_cspi_devtype_data = { + static struct spi_imx_devtype_data imx35_cspi_devtype_data = { + /* i.mx35 and later cspi shares the functions with i.mx31 one */ + .intctrl = mx31_intctrl, ++ .prepare_message = mx31_prepare_message, + .config = mx31_config, + .trigger = mx31_trigger, + .rx_available = mx31_rx_available, +@@ -938,6 +968,7 @@ static struct spi_imx_devtype_data imx35_cspi_devtype_data = { + + static struct spi_imx_devtype_data imx51_ecspi_devtype_data = { + .intctrl = mx51_ecspi_intctrl, ++ .prepare_message = mx51_ecspi_prepare_message, + .config = mx51_ecspi_config, + .trigger = mx51_ecspi_trigger, + .rx_available = mx51_ecspi_rx_available, +@@ -952,6 +983,7 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = { + + static struct spi_imx_devtype_data imx53_ecspi_devtype_data = { + .intctrl = mx51_ecspi_intctrl, ++ .prepare_message = mx51_ecspi_prepare_message, + .config = mx51_ecspi_config, + .trigger = mx51_ecspi_trigger, + .rx_available = mx51_ecspi_rx_available, +@@ -1486,7 +1518,13 @@ spi_imx_prepare_message(struct spi_master *master, struct spi_message *msg) + return ret; + } + +- return 0; ++ ret = spi_imx->devtype_data->prepare_message(spi_imx, msg); ++ if (ret) { ++ clk_disable(spi_imx->clk_ipg); ++ clk_disable(spi_imx->clk_per); ++ } ++ ++ return ret; + } + + static int +-- +2.42.0 + diff --git a/queue-4.19/spi-imx-correct-wml-as-the-last-sg-length.patch b/queue-4.19/spi-imx-correct-wml-as-the-last-sg-length.patch new file mode 100644 index 00000000000..2b7343be129 --- /dev/null +++ b/queue-4.19/spi-imx-correct-wml-as-the-last-sg-length.patch @@ -0,0 +1,107 @@ +From 27dc9c921f14e759f83577ff923313fa05f6d032 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Oct 2018 10:32:45 +0000 +Subject: spi: imx: correct wml as the last sg length + +From: Robin Gong + +[ Upstream commit 5ba5a3730639caddf42af11c60f3f3d99d9a5f00 ] + +Correct wml as the last rx sg length instead of the whole transfer +length. Otherwise, mtd_stresstest will be failed as below: + +insmod mtd_stresstest.ko dev=0 +================================================= +mtd_stresstest: MTD device: 0 +mtd_stresstest: not NAND flash, assume page size is 512 bytes. +mtd_stresstest: MTD device size 4194304, eraseblock size 65536, page size 512, count of eraseblocks 64, pa0 +mtd_stresstest: doing operations +mtd_stresstest: 0 operations done +mtd_test: mtd_read from 1ff532, size 880 +mtd_test: mtd_read from 20c267, size 64998 +spi_master spi0: I/O Error in DMA RX +m25p80 spi0.0: SPI transfer failed: -110 +spi_master spi0: failed to transfer one message from queue +mtd_test: error: read failed at 0x20c267 +mtd_stresstest: error -110 occurred +================================================= +insmod: ERROR: could not insert module mtd_stresstest.ko: Connection timed out + +Signed-off-by: Robin Gong +Signed-off-by: Mark Brown +Stable-dep-of: 00b80ac93553 ("spi: imx: mx51-ecspi: Move some initialisation to prepare_message hook.") +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-imx.c | 29 +++++++++++++++++++---------- + 1 file changed, 19 insertions(+), 10 deletions(-) + +diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c +index 686251e05edfe..139127e27a147 100644 +--- a/drivers/spi/spi-imx.c ++++ b/drivers/spi/spi-imx.c +@@ -218,7 +218,6 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, + struct spi_transfer *transfer) + { + struct spi_imx_data *spi_imx = spi_master_get_devdata(master); +- unsigned int bytes_per_word, i; + + if (!master->dma_rx) + return false; +@@ -226,14 +225,6 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, + if (spi_imx->slave_mode) + return false; + +- bytes_per_word = spi_imx_bytes_per_word(transfer->bits_per_word); +- +- for (i = spi_imx->devtype_data->fifo_size / 2; i > 0; i--) { +- if (!(transfer->len % (i * bytes_per_word))) +- break; +- } +- +- spi_imx->wml = i; + spi_imx->dynamic_burst = 0; + + return true; +@@ -612,7 +603,7 @@ static void mx51_setup_wml(struct spi_imx_data *spi_imx) + * and enable DMA request. + */ + +- writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml) | ++ writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml - 1) | + MX51_ECSPI_DMA_TX_WML(spi_imx->wml) | + MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) | + MX51_ECSPI_DMA_TEDEN | MX51_ECSPI_DMA_RXDEN | +@@ -1330,12 +1321,30 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, + unsigned long timeout; + struct spi_master *master = spi_imx->bitbang.master; + struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg; ++ struct scatterlist *last_sg = sg_last(rx->sgl, rx->nents); ++ unsigned int bytes_per_word, i; + int ret; + ++ /* Get the right burst length from the last sg to ensure no tail data */ ++ bytes_per_word = spi_imx_bytes_per_word(transfer->bits_per_word); ++ for (i = spi_imx->devtype_data->fifo_size / 2; i > 0; i--) { ++ if (!(sg_dma_len(last_sg) % (i * bytes_per_word))) ++ break; ++ } ++ /* Use 1 as wml in case no available burst length got */ ++ if (i == 0) ++ i = 1; ++ ++ spi_imx->wml = i; ++ + ret = spi_imx_dma_configure(master); + if (ret) + return ret; + ++ if (!spi_imx->devtype_data->setup_wml) { ++ dev_err(spi_imx->dev, "No setup_wml()?\n"); ++ return -EINVAL; ++ } + spi_imx->devtype_data->setup_wml(spi_imx); + + /* +-- +2.42.0 + diff --git a/queue-4.19/spi-imx-move-wml-setting-to-later-than-setup_transfe.patch b/queue-4.19/spi-imx-move-wml-setting-to-later-than-setup_transfe.patch new file mode 100644 index 00000000000..50738c161b2 --- /dev/null +++ b/queue-4.19/spi-imx-move-wml-setting-to-later-than-setup_transfe.patch @@ -0,0 +1,104 @@ +From 0391ed229fc995b3d20f5062507b3b4f20a59e83 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Oct 2018 10:32:42 +0000 +Subject: spi: imx: move wml setting to later than setup_transfer + +From: Robin Gong + +[ Upstream commit 987a2dfe3f0485a82d87106e7e1c43f35c1d3b09 ] + +Current dynamic burst length is based on the whole transfer length, +that's ok if there is only one sg, but is not right in case multi sgs +in one transfer,because the tail data should be based on the last sg +length instead of the whole transfer length. Move wml setting for DMA +to the later place, thus, the next patch could get the right last sg +length for wml setting. This patch is a preparation one, no any +function change involved. + +Signed-off-by: Robin Gong +Signed-off-by: Mark Brown +Stable-dep-of: 00b80ac93553 ("spi: imx: mx51-ecspi: Move some initialisation to prepare_message hook.") +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-imx.c | 23 ++++++++++++++--------- + 1 file changed, 14 insertions(+), 9 deletions(-) + +diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c +index eb27f47578eb9..686251e05edfe 100644 +--- a/drivers/spi/spi-imx.c ++++ b/drivers/spi/spi-imx.c +@@ -64,6 +64,7 @@ struct spi_imx_devtype_data { + void (*trigger)(struct spi_imx_data *); + int (*rx_available)(struct spi_imx_data *); + void (*reset)(struct spi_imx_data *); ++ void (*setup_wml)(struct spi_imx_data *); + void (*disable)(struct spi_imx_data *); + bool has_dmamode; + bool has_slavemode; +@@ -601,6 +602,11 @@ static int mx51_ecspi_config(struct spi_device *spi) + else /* SCLK is _very_ slow */ + usleep_range(delay, delay + 10); + ++ return 0; ++} ++ ++static void mx51_setup_wml(struct spi_imx_data *spi_imx) ++{ + /* + * Configure the DMA register: setup the watermark + * and enable DMA request. +@@ -611,8 +617,6 @@ static int mx51_ecspi_config(struct spi_device *spi) + MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) | + MX51_ECSPI_DMA_TEDEN | MX51_ECSPI_DMA_RXDEN | + MX51_ECSPI_DMA_RXTDEN, spi_imx->base + MX51_ECSPI_DMA); +- +- return 0; + } + + static int mx51_ecspi_rx_available(struct spi_imx_data *spi_imx) +@@ -973,6 +977,7 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = { + .trigger = mx51_ecspi_trigger, + .rx_available = mx51_ecspi_rx_available, + .reset = mx51_ecspi_reset, ++ .setup_wml = mx51_setup_wml, + .fifo_size = 64, + .has_dmamode = true, + .dynamic_burst = true, +@@ -1181,7 +1186,6 @@ static int spi_imx_setupxfer(struct spi_device *spi, + struct spi_transfer *t) + { + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); +- int ret; + + if (!t) + return 0; +@@ -1222,12 +1226,6 @@ static int spi_imx_setupxfer(struct spi_device *spi, + else + spi_imx->usedma = 0; + +- if (spi_imx->usedma) { +- ret = spi_imx_dma_configure(spi->master); +- if (ret) +- return ret; +- } +- + if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode) { + spi_imx->rx = mx53_ecspi_rx_slave; + spi_imx->tx = mx53_ecspi_tx_slave; +@@ -1332,6 +1330,13 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, + unsigned long timeout; + struct spi_master *master = spi_imx->bitbang.master; + struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg; ++ int ret; ++ ++ ret = spi_imx_dma_configure(master); ++ if (ret) ++ return ret; ++ ++ spi_imx->devtype_data->setup_wml(spi_imx); + + /* + * The TX DMA setup starts the transfer, so make sure RX is configured +-- +2.42.0 + diff --git a/queue-4.19/spi-imx-mx51-ecspi-move-some-initialisation-to-prepa.patch b/queue-4.19/spi-imx-mx51-ecspi-move-some-initialisation-to-prepa.patch new file mode 100644 index 00000000000..c4411eb3687 --- /dev/null +++ b/queue-4.19/spi-imx-mx51-ecspi-move-some-initialisation-to-prepa.patch @@ -0,0 +1,141 @@ +From 8b50c221ed0e63ba2a57a4bded321db6f9c689c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 30 Nov 2018 07:47:06 +0100 +Subject: spi: imx: mx51-ecspi: Move some initialisation to prepare_message + hook. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König + +[ Upstream commit 00b80ac9355397455adec24c9ee76f1b0225cd27 ] + +The relevant difference between prepare_message and config is that the +former is run before the CS signal is asserted. So the polarity of the +CLK line must be configured in prepare_message as an edge generated by +config might already result in a latch of the MOSI line. + +Signed-off-by: Uwe Kleine-König +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/spi/spi-imx.c | 67 ++++++++++++++++++++++++++----------------- + 1 file changed, 40 insertions(+), 27 deletions(-) + +diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c +index 139127e27a147..0078cb365d8c2 100644 +--- a/drivers/spi/spi-imx.c ++++ b/drivers/spi/spi-imx.c +@@ -498,14 +498,9 @@ static void mx51_ecspi_disable(struct spi_imx_data *spi_imx) + static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, + struct spi_message *msg) + { +- return 0; +-} +- +-static int mx51_ecspi_config(struct spi_device *spi) +-{ +- struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); ++ struct spi_device *spi = msg->spi; + u32 ctrl = MX51_ECSPI_CTRL_ENABLE; +- u32 clk = spi_imx->speed_hz, delay, reg; ++ u32 testreg; + u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG); + + /* set Master or Slave mode */ +@@ -520,19 +515,21 @@ static int mx51_ecspi_config(struct spi_device *spi) + if (spi->mode & SPI_READY) + ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl); + +- /* set clock speed */ +- ctrl |= mx51_ecspi_clkdiv(spi_imx, spi_imx->speed_hz, &clk); +- spi_imx->spi_bus_clk = clk; +- + /* set chip select to use */ + ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select); + +- if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) +- ctrl |= (spi_imx->slave_burst * 8 - 1) +- << MX51_ECSPI_CTRL_BL_OFFSET; ++ /* ++ * The ctrl register must be written first, with the EN bit set other ++ * registers must not be written to. ++ */ ++ writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); ++ ++ testreg = readl(spi_imx->base + MX51_ECSPI_TESTREG); ++ if (spi->mode & SPI_LOOP) ++ testreg |= MX51_ECSPI_TESTREG_LBC; + else +- ctrl |= (spi_imx->bits_per_word - 1) +- << MX51_ECSPI_CTRL_BL_OFFSET; ++ testreg &= ~MX51_ECSPI_TESTREG_LBC; ++ writel(testreg, spi_imx->base + MX51_ECSPI_TESTREG); + + /* + * eCSPI burst completion by Chip Select signal in Slave mode +@@ -556,25 +553,42 @@ static int mx51_ecspi_config(struct spi_device *spi) + cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select); + cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select); + } ++ + if (spi->mode & SPI_CS_HIGH) + cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); + else + cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); + +- if (spi_imx->usedma) +- ctrl |= MX51_ECSPI_CTRL_SMC; ++ writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); + +- /* CTRL register always go first to bring out controller from reset */ +- writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); ++ return 0; ++} + +- reg = readl(spi_imx->base + MX51_ECSPI_TESTREG); +- if (spi->mode & SPI_LOOP) +- reg |= MX51_ECSPI_TESTREG_LBC; ++static int mx51_ecspi_config(struct spi_device *spi) ++{ ++ struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); ++ u32 ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL); ++ u32 clk = spi_imx->speed_hz, delay; ++ ++ /* Clear BL field and set the right value */ ++ ctrl &= ~MX51_ECSPI_CTRL_BL_MASK; ++ if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) ++ ctrl |= (spi_imx->slave_burst * 8 - 1) ++ << MX51_ECSPI_CTRL_BL_OFFSET; + else +- reg &= ~MX51_ECSPI_TESTREG_LBC; +- writel(reg, spi_imx->base + MX51_ECSPI_TESTREG); ++ ctrl |= (spi_imx->bits_per_word - 1) ++ << MX51_ECSPI_CTRL_BL_OFFSET; + +- writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); ++ /* set clock speed */ ++ ctrl &= ~(0xf << MX51_ECSPI_CTRL_POSTDIV_OFFSET | ++ 0xf << MX51_ECSPI_CTRL_PREDIV_OFFSET); ++ ctrl |= mx51_ecspi_clkdiv(spi_imx, spi_imx->speed_hz, &clk); ++ spi_imx->spi_bus_clk = clk; ++ ++ if (spi_imx->usedma) ++ ctrl |= MX51_ECSPI_CTRL_SMC; ++ ++ writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); + + /* + * Wait until the changes in the configuration register CONFIGREG +@@ -602,7 +616,6 @@ static void mx51_setup_wml(struct spi_imx_data *spi_imx) + * Configure the DMA register: setup the watermark + * and enable DMA request. + */ +- + writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml - 1) | + MX51_ECSPI_DMA_TX_WML(spi_imx->wml) | + MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) | +-- +2.42.0 + diff --git a/queue-4.19/tg3-increment-tx_dropped-in-tg3_tso_bug.patch b/queue-4.19/tg3-increment-tx_dropped-in-tg3_tso_bug.patch new file mode 100644 index 00000000000..3734bdce3c5 --- /dev/null +++ b/queue-4.19/tg3-increment-tx_dropped-in-tg3_tso_bug.patch @@ -0,0 +1,41 @@ +From 6cd6f9c23587b1a5dd272cb199168fbcdc49d896 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Nov 2023 10:23:50 -0800 +Subject: tg3: Increment tx_dropped in tg3_tso_bug() + +From: Alex Pakhunov + +[ Upstream commit 17dd5efe5f36a96bd78012594fabe21efb01186b ] + +tg3_tso_bug() drops a packet if it cannot be segmented for any reason. +The number of discarded frames should be incremented accordingly. + +Signed-off-by: Alex Pakhunov +Signed-off-by: Vincent Wong +Reviewed-by: Pavan Chebbi +Link: https://lore.kernel.org/r/20231113182350.37472-2-alexey.pakhunov@spacex.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/tg3.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index 84a5bddf614c8..68bb4a2ff7cee 100644 +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -7889,8 +7889,10 @@ static int tg3_tso_bug(struct tg3 *tp, struct tg3_napi *tnapi, + + segs = skb_gso_segment(skb, tp->dev->features & + ~(NETIF_F_TSO | NETIF_F_TSO6)); +- if (IS_ERR(segs) || !segs) ++ if (IS_ERR(segs) || !segs) { ++ tnapi->tx_dropped++; + goto tg3_tso_bug_end; ++ } + + do { + nskb = segs; +-- +2.42.0 + diff --git a/queue-4.19/tg3-move-the-rt-x_dropped-counters-to-tg3_napi.patch b/queue-4.19/tg3-move-the-rt-x_dropped-counters-to-tg3_napi.patch new file mode 100644 index 00000000000..cfd4ca25fe7 --- /dev/null +++ b/queue-4.19/tg3-move-the-rt-x_dropped-counters-to-tg3_napi.patch @@ -0,0 +1,139 @@ +From 1ad92b149ef06fd3a4adc6cc2703ce78cf3e65e4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Nov 2023 10:23:49 -0800 +Subject: tg3: Move the [rt]x_dropped counters to tg3_napi + +From: Alex Pakhunov + +[ Upstream commit 907d1bdb8b2cc0357d03a1c34d2a08d9943760b1 ] + +This change moves [rt]x_dropped counters to tg3_napi so that they can be +updated by a single writer, race-free. + +Signed-off-by: Alex Pakhunov +Signed-off-by: Vincent Wong +Reviewed-by: Michael Chan +Link: https://lore.kernel.org/r/20231113182350.37472-1-alexey.pakhunov@spacex.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/tg3.c | 38 +++++++++++++++++++++++++---- + drivers/net/ethernet/broadcom/tg3.h | 4 +-- + 2 files changed, 35 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c +index f0b5c8a4d29f5..84a5bddf614c8 100644 +--- a/drivers/net/ethernet/broadcom/tg3.c ++++ b/drivers/net/ethernet/broadcom/tg3.c +@@ -6859,7 +6859,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) + desc_idx, *post_ptr); + drop_it_no_recycle: + /* Other statistics kept track of by card. */ +- tp->rx_dropped++; ++ tnapi->rx_dropped++; + goto next_pkt; + } + +@@ -8163,7 +8163,7 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) + drop: + dev_kfree_skb_any(skb); + drop_nofree: +- tp->tx_dropped++; ++ tnapi->tx_dropped++; + return NETDEV_TX_OK; + } + +@@ -9342,7 +9342,7 @@ static void __tg3_set_rx_mode(struct net_device *); + /* tp->lock is held. */ + static int tg3_halt(struct tg3 *tp, int kind, bool silent) + { +- int err; ++ int err, i; + + tg3_stop_fw(tp); + +@@ -9363,6 +9363,13 @@ static int tg3_halt(struct tg3 *tp, int kind, bool silent) + + /* And make sure the next sample is new data */ + memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats)); ++ ++ for (i = 0; i < TG3_IRQ_MAX_VECS; ++i) { ++ struct tg3_napi *tnapi = &tp->napi[i]; ++ ++ tnapi->rx_dropped = 0; ++ tnapi->tx_dropped = 0; ++ } + } + + return err; +@@ -11919,6 +11926,9 @@ static void tg3_get_nstats(struct tg3 *tp, struct rtnl_link_stats64 *stats) + { + struct rtnl_link_stats64 *old_stats = &tp->net_stats_prev; + struct tg3_hw_stats *hw_stats = tp->hw_stats; ++ unsigned long rx_dropped; ++ unsigned long tx_dropped; ++ int i; + + stats->rx_packets = old_stats->rx_packets + + get_stat64(&hw_stats->rx_ucast_packets) + +@@ -11965,8 +11975,26 @@ static void tg3_get_nstats(struct tg3 *tp, struct rtnl_link_stats64 *stats) + stats->rx_missed_errors = old_stats->rx_missed_errors + + get_stat64(&hw_stats->rx_discards); + +- stats->rx_dropped = tp->rx_dropped; +- stats->tx_dropped = tp->tx_dropped; ++ /* Aggregate per-queue counters. The per-queue counters are updated ++ * by a single writer, race-free. The result computed by this loop ++ * might not be 100% accurate (counters can be updated in the middle of ++ * the loop) but the next tg3_get_nstats() will recompute the current ++ * value so it is acceptable. ++ * ++ * Note that these counters wrap around at 4G on 32bit machines. ++ */ ++ rx_dropped = (unsigned long)(old_stats->rx_dropped); ++ tx_dropped = (unsigned long)(old_stats->tx_dropped); ++ ++ for (i = 0; i < tp->irq_cnt; i++) { ++ struct tg3_napi *tnapi = &tp->napi[i]; ++ ++ rx_dropped += tnapi->rx_dropped; ++ tx_dropped += tnapi->tx_dropped; ++ } ++ ++ stats->rx_dropped = rx_dropped; ++ stats->tx_dropped = tx_dropped; + } + + static int tg3_get_regs_len(struct net_device *dev) +diff --git a/drivers/net/ethernet/broadcom/tg3.h b/drivers/net/ethernet/broadcom/tg3.h +index a772a33b685c5..b8cc8ff4e8782 100644 +--- a/drivers/net/ethernet/broadcom/tg3.h ++++ b/drivers/net/ethernet/broadcom/tg3.h +@@ -3018,6 +3018,7 @@ struct tg3_napi { + u16 *rx_rcb_prod_idx; + struct tg3_rx_prodring_set prodring; + struct tg3_rx_buffer_desc *rx_rcb; ++ unsigned long rx_dropped; + + u32 tx_prod ____cacheline_aligned; + u32 tx_cons; +@@ -3026,6 +3027,7 @@ struct tg3_napi { + u32 prodmbox; + struct tg3_tx_buffer_desc *tx_ring; + struct tg3_tx_ring_info *tx_buffers; ++ unsigned long tx_dropped; + + dma_addr_t status_mapping; + dma_addr_t rx_rcb_mapping; +@@ -3219,8 +3221,6 @@ struct tg3 { + + + /* begin "everything else" cacheline(s) section */ +- unsigned long rx_dropped; +- unsigned long tx_dropped; + struct rtnl_link_stats64 net_stats_prev; + struct tg3_ethtool_stats estats_prev; + +-- +2.42.0 +