]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 4 Feb 2021 15:16:14 +0000 (16:16 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 4 Feb 2021 15:16:14 +0000 (16:16 +0100)
added patches:
acpi-thermal-do-not-call-acpi_thermal_check-directly.patch
arm64-do-not-pass-tagged-addresses-to-__is_lm_address.patch
arm64-fix-kernel-address-detection-of-__is_lm_address.patch
tcp-make-tcp_user_timeout-accurate-for-zero-window-probes.patch

queue-5.4/acpi-thermal-do-not-call-acpi_thermal_check-directly.patch [new file with mode: 0644]
queue-5.4/arm64-do-not-pass-tagged-addresses-to-__is_lm_address.patch [new file with mode: 0644]
queue-5.4/arm64-fix-kernel-address-detection-of-__is_lm_address.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/tcp-make-tcp_user_timeout-accurate-for-zero-window-probes.patch [new file with mode: 0644]

diff --git a/queue-5.4/acpi-thermal-do-not-call-acpi_thermal_check-directly.patch b/queue-5.4/acpi-thermal-do-not-call-acpi_thermal_check-directly.patch
new file mode 100644 (file)
index 0000000..0f0b498
--- /dev/null
@@ -0,0 +1,176 @@
+From 81b704d3e4674e09781d331df73d76675d5ad8cb Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Thu, 14 Jan 2021 19:34:22 +0100
+Subject: ACPI: thermal: Do not call acpi_thermal_check() directly
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit 81b704d3e4674e09781d331df73d76675d5ad8cb upstream.
+
+Calling acpi_thermal_check() from acpi_thermal_notify() directly
+is problematic if _TMP triggers Notify () on the thermal zone for
+which it has been evaluated (which happens on some systems), because
+it causes a new acpi_thermal_notify() invocation to be queued up
+every time and if that takes place too often, an indefinite number of
+pending work items may accumulate in kacpi_notify_wq over time.
+
+Besides, it is not really useful to queue up a new invocation of
+acpi_thermal_check() if one of them is pending already.
+
+For these reasons, rework acpi_thermal_notify() to queue up a thermal
+check instead of calling acpi_thermal_check() directly and only allow
+one thermal check to be pending at a time.  Moreover, only allow one
+acpi_thermal_check_fn() instance at a time to run
+thermal_zone_device_update() for one thermal zone and make it return
+early if it sees other instances running for the same thermal zone.
+
+While at it, fold acpi_thermal_check() into acpi_thermal_check_fn(),
+as it is only called from there after the other changes made here.
+
+[This issue appears to have been exposed by commit 6d25be5782e4
+ ("sched/core, workqueues: Distangle worker accounting from rq
+ lock"), but it is unclear why it was not visible earlier.]
+
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=208877
+Reported-by: Stephen Berman <stephen.berman@gmx.net>
+Diagnosed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Tested-by: Stephen Berman <stephen.berman@gmx.net>
+Cc: All applicable <stable@vger.kernel.org>
+[bigeasy: Backported to v5.4.y]
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/thermal.c |   55 +++++++++++++++++++++++++++++++++----------------
+ 1 file changed, 38 insertions(+), 17 deletions(-)
+
+--- a/drivers/acpi/thermal.c
++++ b/drivers/acpi/thermal.c
+@@ -174,6 +174,8 @@ struct acpi_thermal {
+       int tz_enabled;
+       int kelvin_offset;
+       struct work_struct thermal_check_work;
++      struct mutex thermal_check_lock;
++      refcount_t thermal_check_count;
+ };
+ /* --------------------------------------------------------------------------
+@@ -494,17 +496,6 @@ static int acpi_thermal_get_trip_points(
+       return 0;
+ }
+-static void acpi_thermal_check(void *data)
+-{
+-      struct acpi_thermal *tz = data;
+-
+-      if (!tz->tz_enabled)
+-              return;
+-
+-      thermal_zone_device_update(tz->thermal_zone,
+-                                 THERMAL_EVENT_UNSPECIFIED);
+-}
+-
+ /* sys I/F for generic thermal sysfs support */
+ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp)
+@@ -538,6 +529,8 @@ static int thermal_get_mode(struct therm
+       return 0;
+ }
++static void acpi_thermal_check_fn(struct work_struct *work);
++
+ static int thermal_set_mode(struct thermal_zone_device *thermal,
+                               enum thermal_device_mode mode)
+ {
+@@ -563,7 +556,7 @@ static int thermal_set_mode(struct therm
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                       "%s kernel ACPI thermal control\n",
+                       tz->tz_enabled ? "Enable" : "Disable"));
+-              acpi_thermal_check(tz);
++              acpi_thermal_check_fn(&tz->thermal_check_work);
+       }
+       return 0;
+ }
+@@ -932,6 +925,12 @@ static void acpi_thermal_unregister_ther
+                                  Driver Interface
+    -------------------------------------------------------------------------- */
++static void acpi_queue_thermal_check(struct acpi_thermal *tz)
++{
++      if (!work_pending(&tz->thermal_check_work))
++              queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
++}
++
+ static void acpi_thermal_notify(struct acpi_device *device, u32 event)
+ {
+       struct acpi_thermal *tz = acpi_driver_data(device);
+@@ -942,17 +941,17 @@ static void acpi_thermal_notify(struct a
+       switch (event) {
+       case ACPI_THERMAL_NOTIFY_TEMPERATURE:
+-              acpi_thermal_check(tz);
++              acpi_queue_thermal_check(tz);
+               break;
+       case ACPI_THERMAL_NOTIFY_THRESHOLDS:
+               acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS);
+-              acpi_thermal_check(tz);
++              acpi_queue_thermal_check(tz);
+               acpi_bus_generate_netlink_event(device->pnp.device_class,
+                                                 dev_name(&device->dev), event, 0);
+               break;
+       case ACPI_THERMAL_NOTIFY_DEVICES:
+               acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES);
+-              acpi_thermal_check(tz);
++              acpi_queue_thermal_check(tz);
+               acpi_bus_generate_netlink_event(device->pnp.device_class,
+                                                 dev_name(&device->dev), event, 0);
+               break;
+@@ -1052,7 +1051,27 @@ static void acpi_thermal_check_fn(struct
+ {
+       struct acpi_thermal *tz = container_of(work, struct acpi_thermal,
+                                              thermal_check_work);
+-      acpi_thermal_check(tz);
++
++      if (!tz->tz_enabled)
++              return;
++      /*
++       * In general, it is not sufficient to check the pending bit, because
++       * subsequent instances of this function may be queued after one of them
++       * has started running (e.g. if _TMP sleeps).  Avoid bailing out if just
++       * one of them is running, though, because it may have done the actual
++       * check some time ago, so allow at least one of them to block on the
++       * mutex while another one is running the update.
++       */
++      if (!refcount_dec_not_one(&tz->thermal_check_count))
++              return;
++
++      mutex_lock(&tz->thermal_check_lock);
++
++      thermal_zone_device_update(tz->thermal_zone, THERMAL_EVENT_UNSPECIFIED);
++
++      refcount_inc(&tz->thermal_check_count);
++
++      mutex_unlock(&tz->thermal_check_lock);
+ }
+ static int acpi_thermal_add(struct acpi_device *device)
+@@ -1084,6 +1103,8 @@ static int acpi_thermal_add(struct acpi_
+       if (result)
+               goto free_memory;
++      refcount_set(&tz->thermal_check_count, 3);
++      mutex_init(&tz->thermal_check_lock);
+       INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn);
+       pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device),
+@@ -1149,7 +1170,7 @@ static int acpi_thermal_resume(struct de
+               tz->state.active |= tz->trips.active[i].flags.enabled;
+       }
+-      queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work);
++      acpi_queue_thermal_check(tz);
+       return AE_OK;
+ }
diff --git a/queue-5.4/arm64-do-not-pass-tagged-addresses-to-__is_lm_address.patch b/queue-5.4/arm64-do-not-pass-tagged-addresses-to-__is_lm_address.patch
new file mode 100644 (file)
index 0000000..4c1f362
--- /dev/null
@@ -0,0 +1,53 @@
+From 91cb2c8b072e00632adf463b78b44f123d46a0fa Mon Sep 17 00:00:00 2001
+From: Catalin Marinas <catalin.marinas@arm.com>
+Date: Mon, 1 Feb 2021 19:06:33 +0000
+Subject: arm64: Do not pass tagged addresses to __is_lm_address()
+
+From: Catalin Marinas <catalin.marinas@arm.com>
+
+commit 91cb2c8b072e00632adf463b78b44f123d46a0fa upstream.
+
+Commit 519ea6f1c82f ("arm64: Fix kernel address detection of
+__is_lm_address()") fixed the incorrect validation of addresses below
+PAGE_OFFSET. However, it no longer allowed tagged addresses to be passed
+to virt_addr_valid().
+
+Fix this by explicitly resetting the pointer tag prior to invoking
+__is_lm_address(). This is consistent with the __lm_to_phys() macro.
+
+Fixes: 519ea6f1c82f ("arm64: Fix kernel address detection of __is_lm_address()")
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Acked-by: Ard Biesheuvel <ardb@kernel.org>
+Cc: <stable@vger.kernel.org> # 5.4.x
+Cc: Will Deacon <will@kernel.org>
+Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Link: https://lore.kernel.org/r/20210201190634.22942-2-catalin.marinas@arm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/include/asm/memory.h |    2 +-
+ arch/arm64/mm/physaddr.c        |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm64/include/asm/memory.h
++++ b/arch/arm64/include/asm/memory.h
+@@ -332,7 +332,7 @@ static inline void *phys_to_virt(phys_ad
+ #endif /* !CONFIG_SPARSEMEM_VMEMMAP || CONFIG_DEBUG_VIRTUAL */
+ #define virt_addr_valid(addr) ({                                      \
+-      __typeof__(addr) __addr = addr;                                 \
++      __typeof__(addr) __addr = __tag_reset(addr);                    \
+       __is_lm_address(__addr) && pfn_valid(virt_to_pfn(__addr));      \
+ })
+--- a/arch/arm64/mm/physaddr.c
++++ b/arch/arm64/mm/physaddr.c
+@@ -9,7 +9,7 @@
+ phys_addr_t __virt_to_phys(unsigned long x)
+ {
+-      WARN(!__is_lm_address(x),
++      WARN(!__is_lm_address(__tag_reset(x)),
+            "virt_to_phys used for non-linear address: %pK (%pS)\n",
+             (void *)x,
+             (void *)x);
diff --git a/queue-5.4/arm64-fix-kernel-address-detection-of-__is_lm_address.patch b/queue-5.4/arm64-fix-kernel-address-detection-of-__is_lm_address.patch
new file mode 100644 (file)
index 0000000..8fac39d
--- /dev/null
@@ -0,0 +1,49 @@
+From 519ea6f1c82fcdc9842908155ae379de47818778 Mon Sep 17 00:00:00 2001
+From: Vincenzo Frascino <vincenzo.frascino@arm.com>
+Date: Tue, 26 Jan 2021 13:40:56 +0000
+Subject: arm64: Fix kernel address detection of __is_lm_address()
+
+From: Vincenzo Frascino <vincenzo.frascino@arm.com>
+
+commit 519ea6f1c82fcdc9842908155ae379de47818778 upstream.
+
+Currently, the __is_lm_address() check just masks out the top 12 bits
+of the address, but if they are 0, it still yields a true result.
+This has as a side effect that virt_addr_valid() returns true even for
+invalid virtual addresses (e.g. 0x0).
+
+Fix the detection checking that it's actually a kernel address starting
+at PAGE_OFFSET.
+
+Fixes: 68dd8ef32162 ("arm64: memory: Fix virt_addr_valid() using __is_lm_address()")
+Cc: <stable@vger.kernel.org> # 5.4.x
+Cc: Will Deacon <will@kernel.org>
+Suggested-by: Catalin Marinas <catalin.marinas@arm.com>
+Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Signed-off-by: Vincenzo Frascino <vincenzo.frascino@arm.com>
+Link: https://lore.kernel.org/r/20210126134056.45747-1-vincenzo.frascino@arm.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/include/asm/memory.h |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/arm64/include/asm/memory.h
++++ b/arch/arm64/include/asm/memory.h
+@@ -247,11 +247,11 @@ static inline const void *__tag_set(cons
+ /*
+- * The linear kernel range starts at the bottom of the virtual address
+- * space. Testing the top bit for the start of the region is a
+- * sufficient check and avoids having to worry about the tag.
++ * Check whether an arbitrary address is within the linear map, which
++ * lives in the [PAGE_OFFSET, PAGE_END) interval at the bottom of the
++ * kernel's TTBR1 address range.
+  */
+-#define __is_lm_address(addr) (!(((u64)addr) & BIT(vabits_actual - 1)))
++#define __is_lm_address(addr) (((u64)(addr) ^ PAGE_OFFSET) < (PAGE_END - PAGE_OFFSET))
+ #define __lm_to_phys(addr)    (((addr) & ~PAGE_OFFSET) + PHYS_OFFSET)
+ #define __kimg_to_phys(addr)  ((addr) - kimage_voffset)
index 5aa3ceb83ed42ab8927708c19e09a0841ac9ec00..38cf4853554d91af7df54bc9ab4022f1da66c0f7 100644 (file)
@@ -2,3 +2,7 @@ net-dsa-bcm_sf2-put-device-node-before-return.patch
 net-switchdev-don-t-set-port_obj_info-handled-true-when-eopnotsupp.patch
 ibmvnic-ensure-that-crq-entry-read-are-correctly-ordered.patch
 revert-revert-block-end-bio-with-blk_sts_again-in-case-of-non-mq-devs-and-req_nowait.patch
+acpi-thermal-do-not-call-acpi_thermal_check-directly.patch
+arm64-fix-kernel-address-detection-of-__is_lm_address.patch
+arm64-do-not-pass-tagged-addresses-to-__is_lm_address.patch
+tcp-make-tcp_user_timeout-accurate-for-zero-window-probes.patch
diff --git a/queue-5.4/tcp-make-tcp_user_timeout-accurate-for-zero-window-probes.patch b/queue-5.4/tcp-make-tcp_user_timeout-accurate-for-zero-window-probes.patch
new file mode 100644 (file)
index 0000000..d134529
--- /dev/null
@@ -0,0 +1,92 @@
+From 344db93ae3ee69fc137bd6ed89a8ff1bf5b0db08 Mon Sep 17 00:00:00 2001
+From: Enke Chen <enchen@paloaltonetworks.com>
+Date: Fri, 22 Jan 2021 11:13:06 -0800
+Subject: tcp: make TCP_USER_TIMEOUT accurate for zero window probes
+
+From: Enke Chen <enchen@paloaltonetworks.com>
+
+commit 344db93ae3ee69fc137bd6ed89a8ff1bf5b0db08 upstream.
+
+The TCP_USER_TIMEOUT is checked by the 0-window probe timer. As the
+timer has backoff with a max interval of about two minutes, the
+actual timeout for TCP_USER_TIMEOUT can be off by up to two minutes.
+
+In this patch the TCP_USER_TIMEOUT is made more accurate by taking it
+into account when computing the timer value for the 0-window probes.
+
+This patch is similar to and builds on top of the one that made
+TCP_USER_TIMEOUT accurate for RTOs in commit b701a99e431d ("tcp: Add
+tcp_clamp_rto_to_user_timeout() helper to improve accuracy").
+
+Fixes: 9721e709fa68 ("tcp: simplify window probe aborting on USER_TIMEOUT")
+Signed-off-by: Enke Chen <enchen@paloaltonetworks.com>
+Reviewed-by: Neal Cardwell <ncardwell@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://lore.kernel.org/r/20210122191306.GA99540@localhost.localdomain
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/tcp.h     |    1 +
+ net/ipv4/tcp_input.c  |    1 +
+ net/ipv4/tcp_output.c |    2 ++
+ net/ipv4/tcp_timer.c  |   18 ++++++++++++++++++
+ 4 files changed, 22 insertions(+)
+
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -619,6 +619,7 @@ static inline void tcp_clear_xmit_timers
+ unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu);
+ unsigned int tcp_current_mss(struct sock *sk);
++u32 tcp_clamp_probe0_to_user_timeout(const struct sock *sk, u32 when);
+ /* Bound MSS / TSO packet size with the half of the window */
+ static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize)
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -3295,6 +3295,7 @@ static void tcp_ack_probe(struct sock *s
+       } else {
+               unsigned long when = tcp_probe0_when(sk, TCP_RTO_MAX);
++              when = tcp_clamp_probe0_to_user_timeout(sk, when);
+               tcp_reset_xmit_timer(sk, ICSK_TIME_PROBE0,
+                                    when, TCP_RTO_MAX, NULL);
+       }
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -3850,6 +3850,8 @@ void tcp_send_probe0(struct sock *sk)
+                */
+               timeout = TCP_RESOURCE_PROBE_INTERVAL;
+       }
++
++      timeout = tcp_clamp_probe0_to_user_timeout(sk, timeout);
+       tcp_reset_xmit_timer(sk, ICSK_TIME_PROBE0, timeout, TCP_RTO_MAX, NULL);
+ }
+--- a/net/ipv4/tcp_timer.c
++++ b/net/ipv4/tcp_timer.c
+@@ -40,6 +40,24 @@ static u32 tcp_clamp_rto_to_user_timeout
+       return min_t(u32, icsk->icsk_rto, msecs_to_jiffies(remaining));
+ }
++u32 tcp_clamp_probe0_to_user_timeout(const struct sock *sk, u32 when)
++{
++      struct inet_connection_sock *icsk = inet_csk(sk);
++      u32 remaining;
++      s32 elapsed;
++
++      if (!icsk->icsk_user_timeout || !icsk->icsk_probes_tstamp)
++              return when;
++
++      elapsed = tcp_jiffies32 - icsk->icsk_probes_tstamp;
++      if (unlikely(elapsed < 0))
++              elapsed = 0;
++      remaining = msecs_to_jiffies(icsk->icsk_user_timeout) - elapsed;
++      remaining = max_t(u32, remaining, TCP_TIMEOUT_MIN);
++
++      return min_t(u32, remaining, when);
++}
++
+ /**
+  *  tcp_write_err() - close socket and save error info
+  *  @sk:  The socket the error has appeared on.