]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Jul 2023 17:50:57 +0000 (19:50 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Jul 2023 17:50:57 +0000 (19:50 +0200)
added patches:
workqueue-clean-up-work_-constant-types-clarify-masking.patch

queue-5.15/series
queue-5.15/workqueue-clean-up-work_-constant-types-clarify-masking.patch [new file with mode: 0644]

index 7e9cd2a4544e536110b64f2078aaeab1cdab0510..ac0d9c24a17c374960acdc736f6474c992c95630 100644 (file)
@@ -387,6 +387,7 @@ block-partition-fix-signedness-issue-for-amiga-partitions.patch
 io_uring-use-io_schedule-in-cqring-wait.patch
 io_uring-add-reschedule-point-to-handle_tw_list.patch
 net-lan743x-don-t-sleep-in-atomic-context.patch
+workqueue-clean-up-work_-constant-types-clarify-masking.patch
 drm-panel-simple-add-connector_type-for-innolux_at04.patch
 drm-bridge-ti-sn65dsi86-fix-auxiliary-bus-lifetime.patch
 drm-panel-simple-add-powertip-ph800480t013-drm_displ.patch
diff --git a/queue-5.15/workqueue-clean-up-work_-constant-types-clarify-masking.patch b/queue-5.15/workqueue-clean-up-work_-constant-types-clarify-masking.patch
new file mode 100644 (file)
index 0000000..6b0d9cd
--- /dev/null
@@ -0,0 +1,140 @@
+From afa4bb778e48d79e4a642ed41e3b4e0de7489a6c Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Fri, 23 Jun 2023 12:08:14 -0700
+Subject: workqueue: clean up WORK_* constant types, clarify masking
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit afa4bb778e48d79e4a642ed41e3b4e0de7489a6c upstream.
+
+Dave Airlie reports that gcc-13.1.1 has started complaining about some
+of the workqueue code in 32-bit arm builds:
+
+  kernel/workqueue.c: In function ‘get_work_pwq’:
+  kernel/workqueue.c:713:24: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
+    713 |                 return (void *)(data & WORK_STRUCT_WQ_DATA_MASK);
+        |                        ^
+  [ ... a couple of other cases ... ]
+
+and while it's not immediately clear exactly why gcc started complaining
+about it now, I suspect it's some C23-induced enum type handlign fixup in
+gcc-13 is the cause.
+
+Whatever the reason for starting to complain, the code and data types
+are indeed disgusting enough that the complaint is warranted.
+
+The wq code ends up creating various "helper constants" (like that
+WORK_STRUCT_WQ_DATA_MASK) using an enum type, which is all kinds of
+confused.  The mask needs to be 'unsigned long', not some unspecified
+enum type.
+
+To make matters worse, the actual "mask and cast to a pointer" is
+repeated a couple of times, and the cast isn't even always done to the
+right pointer, but - as the error case above - to a 'void *' with then
+the compiler finishing the job.
+
+That's now how we roll in the kernel.
+
+So create the masks using the proper types rather than some ambiguous
+enumeration, and use a nice helper that actually does the type
+conversion in one well-defined place.
+
+Incidentally, this magically makes clang generate better code.  That,
+admittedly, is really just a sign of clang having been seriously
+confused before, and cleaning up the typing unconfuses the compiler too.
+
+Reported-by: Dave Airlie <airlied@gmail.com>
+Link: https://lore.kernel.org/lkml/CAPM=9twNnV4zMCvrPkw3H-ajZOH-01JVh_kDrxdPYQErz8ZTdA@mail.gmail.com/
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Tejun Heo <tj@kernel.org>
+Cc: Nick Desaulniers <ndesaulniers@google.com>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/workqueue.h |   15 ++++++++-------
+ kernel/workqueue.c        |   13 ++++++++-----
+ 2 files changed, 16 insertions(+), 12 deletions(-)
+
+--- a/include/linux/workqueue.h
++++ b/include/linux/workqueue.h
+@@ -68,7 +68,6 @@ enum {
+       WORK_OFFQ_FLAG_BASE     = WORK_STRUCT_COLOR_SHIFT,
+       __WORK_OFFQ_CANCELING   = WORK_OFFQ_FLAG_BASE,
+-      WORK_OFFQ_CANCELING     = (1 << __WORK_OFFQ_CANCELING),
+       /*
+        * When a work item is off queue, its high bits point to the last
+@@ -79,12 +78,6 @@ enum {
+       WORK_OFFQ_POOL_SHIFT    = WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS,
+       WORK_OFFQ_LEFT          = BITS_PER_LONG - WORK_OFFQ_POOL_SHIFT,
+       WORK_OFFQ_POOL_BITS     = WORK_OFFQ_LEFT <= 31 ? WORK_OFFQ_LEFT : 31,
+-      WORK_OFFQ_POOL_NONE     = (1LU << WORK_OFFQ_POOL_BITS) - 1,
+-
+-      /* convenience constants */
+-      WORK_STRUCT_FLAG_MASK   = (1UL << WORK_STRUCT_FLAG_BITS) - 1,
+-      WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK,
+-      WORK_STRUCT_NO_POOL     = (unsigned long)WORK_OFFQ_POOL_NONE << WORK_OFFQ_POOL_SHIFT,
+       /* bit mask for work_busy() return values */
+       WORK_BUSY_PENDING       = 1 << 0,
+@@ -94,6 +87,14 @@ enum {
+       WORKER_DESC_LEN         = 24,
+ };
++/* Convenience constants - of type 'unsigned long', not 'enum'! */
++#define WORK_OFFQ_CANCELING   (1ul << __WORK_OFFQ_CANCELING)
++#define WORK_OFFQ_POOL_NONE   ((1ul << WORK_OFFQ_POOL_BITS) - 1)
++#define WORK_STRUCT_NO_POOL   (WORK_OFFQ_POOL_NONE << WORK_OFFQ_POOL_SHIFT)
++
++#define WORK_STRUCT_FLAG_MASK    ((1ul << WORK_STRUCT_FLAG_BITS) - 1)
++#define WORK_STRUCT_WQ_DATA_MASK (~WORK_STRUCT_FLAG_MASK)
++
+ struct work_struct {
+       atomic_long_t data;
+       struct list_head entry;
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -697,12 +697,17 @@ static void clear_work_data(struct work_
+       set_work_data(work, WORK_STRUCT_NO_POOL, 0);
+ }
++static inline struct pool_workqueue *work_struct_pwq(unsigned long data)
++{
++      return (struct pool_workqueue *)(data & WORK_STRUCT_WQ_DATA_MASK);
++}
++
+ static struct pool_workqueue *get_work_pwq(struct work_struct *work)
+ {
+       unsigned long data = atomic_long_read(&work->data);
+       if (data & WORK_STRUCT_PWQ)
+-              return (void *)(data & WORK_STRUCT_WQ_DATA_MASK);
++              return work_struct_pwq(data);
+       else
+               return NULL;
+ }
+@@ -730,8 +735,7 @@ static struct worker_pool *get_work_pool
+       assert_rcu_or_pool_mutex();
+       if (data & WORK_STRUCT_PWQ)
+-              return ((struct pool_workqueue *)
+-                      (data & WORK_STRUCT_WQ_DATA_MASK))->pool;
++              return work_struct_pwq(data)->pool;
+       pool_id = data >> WORK_OFFQ_POOL_SHIFT;
+       if (pool_id == WORK_OFFQ_POOL_NONE)
+@@ -752,8 +756,7 @@ static int get_work_pool_id(struct work_
+       unsigned long data = atomic_long_read(&work->data);
+       if (data & WORK_STRUCT_PWQ)
+-              return ((struct pool_workqueue *)
+-                      (data & WORK_STRUCT_WQ_DATA_MASK))->pool->id;
++              return work_struct_pwq(data)->pool->id;
+       return data >> WORK_OFFQ_POOL_SHIFT;
+ }