* [PATCH v2 05/19 5.15.y] minmax: avoid overly complicated constant expressions in VM code
From: Eliav Farber @ 2025-10-03 12:59 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Linus Torvalds, Lorenzo Stoakes, David Laight
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: Linus Torvalds <torvalds@linux-foundation.org>
[ Upstream commit 3a7e02c040b130b5545e4b115aada7bacd80a2b6 ]
The minmax infrastructure is overkill for simple constants, and can
cause huge expansions because those simple constants are then used by
other things.
For example, 'pageblock_order' is a core VM constant, but because it was
implemented using 'min_t()' and all the type-checking that involves, it
actually expanded to something like 2.5kB of preprocessor noise.
And when that simple constant was then used inside other expansions:
#define pageblock_nr_pages (1UL << pageblock_order)
#define pageblock_start_pfn(pfn) ALIGN_DOWN((pfn), pageblock_nr_pages)
and we then use that inside a 'max()' macro:
case ISOLATE_SUCCESS:
update_cached = false;
last_migrated_pfn = max(cc->zone->zone_start_pfn,
pageblock_start_pfn(cc->migrate_pfn - 1));
the end result was that one statement expanding to 253kB in size.
There are probably other cases of this, but this one case certainly
stood out.
I've added 'MIN_T()' and 'MAX_T()' macros for this kind of "core simple
constant with specific type" use. These macros skip the type checking,
and as such need to be very sparingly used only for obvious cases that
have active issues like this.
Reported-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Link: https://lore.kernel.org/all/36aa2cad-1db1-4abf-8dd2-fb20484aabc3@lucifer.local/
Cc: David Laight <David.Laight@aculab.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
include/linux/minmax.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index 2ec559284a9f..a7ef65f78933 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -270,4 +270,11 @@ static inline bool in_range32(u32 val, u32 start, u32 len)
#define swap(a, b) \
do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
+/*
+ * Use these carefully: no type checking, and uses the arguments
+ * multiple times. Use for obvious constants only.
+ */
+#define MIN_T(type,a,b) __cmp(min,(type)(a),(type)(b))
+#define MAX_T(type,a,b) __cmp(max,(type)(a),(type)(b))
+
#endif /* _LINUX_MINMAX_H */
--
2.47.3
^ permalink raw reply related
* [PATCH v2 06/19 5.15.y] minmax: add a few more MIN_T/MAX_T users
From: Eliav Farber @ 2025-10-03 12:59 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Linus Torvalds, David Laight, Lorenzo Stoakes
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: Linus Torvalds <torvalds@linux-foundation.org>
[ Upstream commit 4477b39c32fdc03363affef4b11d48391e6dc9ff ]
Commit 3a7e02c040b1 ("minmax: avoid overly complicated constant
expressions in VM code") added the simpler MIN_T/MAX_T macros in order
to avoid some excessive expansion from the rather complicated regular
min/max macros.
The complexity of those macros stems from two issues:
(a) trying to use them in situations that require a C constant
expression (in static initializers and for array sizes)
(b) the type sanity checking
and MIN_T/MAX_T avoids both of these issues.
Now, in the whole (long) discussion about all this, it was pointed out
that the whole type sanity checking is entirely unnecessary for
min_t/max_t which get a fixed type that the comparison is done in.
But that still leaves min_t/max_t unnecessarily complicated due to
worries about the C constant expression case.
However, it turns out that there really aren't very many cases that use
min_t/max_t for this, and we can just force-convert those.
This does exactly that.
Which in turn will then allow for much simpler implementations of
min_t()/max_t(). All the usual "macros in all upper case will evaluate
the arguments multiple times" rules apply.
We should do all the same things for the regular min/max() vs MIN/MAX()
cases, but that has the added complexity of various drivers defining
their own local versions of MIN/MAX, so that needs another level of
fixes first.
Link: https://lore.kernel.org/all/b47fad1d0cf8449886ad148f8c013dae@AcuMS.aculab.com/
Cc: David Laight <David.Laight@aculab.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
V1 -> V2:
Use `[ Upstream commit <HASH> ]` instead of `commit <HASH> upstream.`
like in all other patches.
arch/x86/mm/pgtable.c | 2 +-
drivers/edac/sb_edac.c | 4 ++--
drivers/gpu/drm/drm_color_mgmt.c | 2 +-
drivers/md/dm-integrity.c | 2 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 2 +-
net/ipv4/proc.c | 2 +-
net/ipv6/proc.c | 2 +-
7 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
index 3481b35cb4ec..e649161eb6fc 100644
--- a/arch/x86/mm/pgtable.c
+++ b/arch/x86/mm/pgtable.c
@@ -107,7 +107,7 @@ static inline void pgd_list_del(pgd_t *pgd)
#define UNSHARED_PTRS_PER_PGD \
(SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
#define MAX_UNSHARED_PTRS_PER_PGD \
- max_t(size_t, KERNEL_PGD_BOUNDARY, PTRS_PER_PGD)
+ MAX_T(size_t, KERNEL_PGD_BOUNDARY, PTRS_PER_PGD)
static void pgd_set_mm(pgd_t *pgd, struct mm_struct *mm)
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 1522d4aa2ca6..714020e7405a 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -109,8 +109,8 @@ static const u32 knl_interleave_list[] = {
0x104, 0x10c, 0x114, 0x11c, /* 20-23 */
};
#define MAX_INTERLEAVE \
- (max_t(unsigned int, ARRAY_SIZE(sbridge_interleave_list), \
- max_t(unsigned int, ARRAY_SIZE(ibridge_interleave_list), \
+ (MAX_T(unsigned int, ARRAY_SIZE(sbridge_interleave_list), \
+ MAX_T(unsigned int, ARRAY_SIZE(ibridge_interleave_list), \
ARRAY_SIZE(knl_interleave_list))))
struct interleave_pkg {
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index bb14f488c8f6..1ff572d8744e 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -528,7 +528,7 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
{
struct drm_device *dev = plane->dev;
struct drm_property *prop;
- struct drm_prop_enum_list enum_list[max_t(int, DRM_COLOR_ENCODING_MAX,
+ struct drm_prop_enum_list enum_list[MAX_T(int, DRM_COLOR_ENCODING_MAX,
DRM_COLOR_RANGE_MAX)];
int i, len;
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index e9d553eea9cd..8e2b00536c3e 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -2536,7 +2536,7 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start,
unlikely(from_replay) &&
#endif
ic->internal_hash) {
- char test_tag[max_t(size_t, HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
+ char test_tag[MAX_T(size_t, HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
integrity_sector_checksum(ic, sec + ((l - j) << ic->sb->log2_sectors_per_block),
(char *)access_journal_data(ic, i, l), test_tag);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 2478caeec763..21cc8cd9e023 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2805,7 +2805,7 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
u32 channels_to_check = tx_channel_count > rx_channel_count ?
tx_channel_count : rx_channel_count;
u32 chan;
- int status[max_t(u32, MTL_MAX_TX_QUEUES, MTL_MAX_RX_QUEUES)];
+ int status[MAX_T(u32, MTL_MAX_TX_QUEUES, MTL_MAX_RX_QUEUES)];
/* Make sure we never check beyond our status buffer. */
if (WARN_ON_ONCE(channels_to_check > ARRAY_SIZE(status)))
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index 4b9280a3b673..d849f61b7519 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -43,7 +43,7 @@
#include <net/sock.h>
#include <net/raw.h>
-#define TCPUDP_MIB_MAX max_t(u32, UDP_MIB_MAX, TCP_MIB_MAX)
+#define TCPUDP_MIB_MAX MAX_T(u32, UDP_MIB_MAX, TCP_MIB_MAX)
/*
* Report socket allocation statistics [mea@utu.fi]
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index d6306aa46bb1..e07c43bd5cb0 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -27,7 +27,7 @@
#include <net/ipv6.h>
#define MAX4(a, b, c, d) \
- max_t(u32, max_t(u32, a, b), max_t(u32, c, d))
+ MAX_T(u32, MAX_T(u32, a, b), MAX_T(u32, c, d))
#define SNMP_MIB_MAX MAX4(UDP_MIB_MAX, TCP_MIB_MAX, \
IPSTATS_MIB_MAX, ICMP_MIB_MAX)
--
2.47.3
^ permalink raw reply related
* [PATCH v2 07/19 5.15.y] minmax: simplify and clarify min_t()/max_t() implementation
From: Eliav Farber @ 2025-10-03 12:59 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Linus Torvalds, David Laight, Lorenzo Stoakes
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: Linus Torvalds <torvalds@linux-foundation.org>
[ Upstream commit 017fa3e89187848fd056af757769c9e66ac3e93d ]
This simplifies the min_t() and max_t() macros by no longer making them
work in the context of a C constant expression.
That means that you can no longer use them for static initializers or
for array sizes in type definitions, but there were only a couple of
such uses, and all of them were converted (famous last words) to use
MIN_T/MAX_T instead.
Cc: David Laight <David.Laight@aculab.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
V1 -> V2:
Use `[ Upstream commit <HASH> ]` instead of `commit <HASH> upstream.`
like in all other patches.
include/linux/minmax.h | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index a7ef65f78933..9c2848abc804 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -45,17 +45,20 @@
#define __cmp(op, x, y) ((x) __cmp_op_##op (y) ? (x) : (y))
-#define __cmp_once(op, x, y, unique_x, unique_y) ({ \
- typeof(x) unique_x = (x); \
- typeof(y) unique_y = (y); \
+#define __cmp_once_unique(op, type, x, y, ux, uy) \
+ ({ type ux = (x); type uy = (y); __cmp(op, ux, uy); })
+
+#define __cmp_once(op, type, x, y) \
+ __cmp_once_unique(op, type, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_))
+
+#define __careful_cmp_once(op, x, y) ({ \
static_assert(__types_ok(x, y), \
#op "(" #x ", " #y ") signedness error, fix types or consider u" #op "() before " #op "_t()"); \
- __cmp(op, unique_x, unique_y); })
+ __cmp_once(op, __auto_type, x, y); })
#define __careful_cmp(op, x, y) \
__builtin_choose_expr(__is_constexpr((x) - (y)), \
- __cmp(op, x, y), \
- __cmp_once(op, x, y, __UNIQUE_ID(__x), __UNIQUE_ID(__y)))
+ __cmp(op, x, y), __careful_cmp_once(op, x, y))
#define __clamp(val, lo, hi) \
((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val)))
@@ -158,7 +161,7 @@
* @x: first value
* @y: second value
*/
-#define min_t(type, x, y) __careful_cmp(min, (type)(x), (type)(y))
+#define min_t(type, x, y) __cmp_once(min, type, x, y)
/**
* max_t - return maximum of two values, using the specified type
@@ -166,7 +169,7 @@
* @x: first value
* @y: second value
*/
-#define max_t(type, x, y) __careful_cmp(max, (type)(x), (type)(y))
+#define max_t(type, x, y) __cmp_once(max, type, x, y)
/*
* Do not check the array parameter using __must_be_array().
--
2.47.3
^ permalink raw reply related
* [PATCH v2 08/19 5.15.y] minmax: make generic MIN() and MAX() macros available everywhere
From: Eliav Farber @ 2025-10-03 12:59 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Linus Torvalds, David Laight, Lorenzo Stoakes
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: Linus Torvalds <torvalds@linux-foundation.org>
[ Upstream commit 1a251f52cfdc417c84411a056bc142cbd77baef4 ]
This just standardizes the use of MIN() and MAX() macros, with the very
traditional semantics. The goal is to use these for C constant
expressions and for top-level / static initializers, and so be able to
simplify the min()/max() macros.
These macro names were used by various kernel code - they are very
traditional, after all - and all such users have been fixed up, with a
few different approaches:
- trivial duplicated macro definitions have been removed
Note that 'trivial' here means that it's obviously kernel code that
already included all the major kernel headers, and thus gets the new
generic MIN/MAX macros automatically.
- non-trivial duplicated macro definitions are guarded with #ifndef
This is the "yes, they define their own versions, but no, the include
situation is not entirely obvious, and maybe they don't get the
generic version automatically" case.
- strange use case #1
A couple of drivers decided that the way they want to describe their
versioning is with
#define MAJ 1
#define MIN 2
#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN)
which adds zero value and I just did my Alexander the Great
impersonation, and rewrote that pointless Gordian knot as
#define DRV_VERSION "1.2"
instead.
- strange use case #2
A couple of drivers thought that it's a good idea to have a random
'MIN' or 'MAX' define for a value or index into a table, rather than
the traditional macro that takes arguments.
These values were re-written as C enum's instead. The new
function-line macros only expand when followed by an open
parenthesis, and thus don't clash with enum use.
Happily, there weren't really all that many of these cases, and a lot of
users already had the pattern of using '#ifndef' guarding (or in one
case just using '#undef MIN') before defining their own private version
that does the same thing. I left such cases alone.
Cc: David Laight <David.Laight@aculab.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
arch/um/drivers/mconsole_user.c | 2 ++
drivers/edac/skx_common.h | 1 -
drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++
.../drm/amd/display/modules/hdcp/hdcp_ddc.c | 2 ++
.../drm/amd/pm/powerplay/hwmgr/ppevvmath.h | 14 +++++++----
.../amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2 ++
drivers/gpu/drm/radeon/evergreen_cs.c | 2 ++
drivers/hwmon/adt7475.c | 24 +++++++++----------
drivers/media/dvb-frontends/stv0367_priv.h | 3 +++
drivers/net/fjes/fjes_main.c | 4 +---
drivers/nfc/pn544/i2c.c | 2 --
drivers/platform/x86/sony-laptop.c | 1 -
drivers/scsi/isci/init.c | 6 +----
.../pci/hive_isp_css_include/math_support.h | 5 ----
include/linux/minmax.h | 2 ++
kernel/trace/preemptirq_delay_test.c | 2 --
lib/btree.c | 1 -
lib/decompress_unlzma.c | 2 ++
lib/zstd/zstd_internal.h | 2 --
mm/zsmalloc.c | 1 -
tools/testing/selftests/vm/mremap_test.c | 2 ++
21 files changed, 43 insertions(+), 39 deletions(-)
diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
index e24298a734be..a04cd13c6315 100644
--- a/arch/um/drivers/mconsole_user.c
+++ b/arch/um/drivers/mconsole_user.c
@@ -71,7 +71,9 @@ static struct mconsole_command *mconsole_parse(struct mc_request *req)
return NULL;
}
+#ifndef MIN
#define MIN(a,b) ((a)<(b) ? (a):(b))
+#endif
#define STRINGX(x) #x
#define STRING(x) STRINGX(x)
diff --git a/drivers/edac/skx_common.h b/drivers/edac/skx_common.h
index 13f761930b4f..1a78f18cf7fe 100644
--- a/drivers/edac/skx_common.h
+++ b/drivers/edac/skx_common.h
@@ -44,7 +44,6 @@
#define I10NM_NUM_CHANNELS MAX(I10NM_NUM_DDR_CHANNELS, I10NM_NUM_HBM_CHANNELS)
#define I10NM_NUM_DIMMS MAX(I10NM_NUM_DDR_DIMMS, I10NM_NUM_HBM_DIMMS)
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define NUM_IMC MAX(SKX_NUM_IMC, I10NM_NUM_IMC)
#define NUM_CHANNELS MAX(SKX_NUM_CHANNELS, I10NM_NUM_CHANNELS)
#define NUM_DIMMS MAX(SKX_NUM_DIMMS, I10NM_NUM_DIMMS)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index dbef22f56482..1ee8663fd866 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1277,7 +1277,9 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
#define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter));
+#ifndef MIN
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
+#endif
/* Common functions */
bool amdgpu_device_has_job_running(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c
index 1b2df97226a3..40286e8dd4e1 100644
--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c
+++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c
@@ -25,7 +25,9 @@
#include "hdcp.h"
+#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
#define HDCP_I2C_ADDR 0x3a /* 0x74 >> 1*/
#define KSV_READ_SIZE 0xf /* 0x6803b - 0x6802c */
#define HDCP_MAX_AUX_TRANSACTION_SIZE 16
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h
index dac29fe6cfc6..abbdb7731996 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h
@@ -22,12 +22,18 @@
*/
#include <asm/div64.h>
-#define SHIFT_AMOUNT 16 /* We multiply all original integers with 2^SHIFT_AMOUNT to get the fInt representation */
+enum ppevvmath_constants {
+ /* We multiply all original integers with 2^SHIFT_AMOUNT to get the fInt representation */
+ SHIFT_AMOUNT = 16,
-#define PRECISION 5 /* Change this value to change the number of decimal places in the final output - 5 is a good default */
+ /* Change this value to change the number of decimal places in the final output - 5 is a good default */
+ PRECISION = 5,
-#define SHIFTED_2 (2 << SHIFT_AMOUNT)
-#define MAX (1 << (SHIFT_AMOUNT - 1)) - 1 /* 32767 - Might change in the future */
+ SHIFTED_2 = (2 << SHIFT_AMOUNT),
+
+ /* 32767 - Might change in the future */
+ MAX = (1 << (SHIFT_AMOUNT - 1)) - 1,
+};
/* -------------------------------------------------------------------------------
* NEW TYPE - fINT
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index d4fde146bd4c..95894c25881a 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -1964,7 +1964,9 @@ static void sienna_cichlid_get_override_pcie_settings(struct smu_context *smu,
}
}
+#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu,
uint32_t pcie_gen_cap,
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index 820c2c3641d3..1311f10fad66 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -33,8 +33,10 @@
#include "evergreen_reg_safe.h"
#include "cayman_reg_safe.h"
+#ifndef MIN
#define MAX(a,b) (((a)>(b))?(a):(b))
#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
#define REG_SAFE_BM_SIZE ARRAY_SIZE(evergreen_reg_safe_bm)
diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c
index b4c0f01f52c4..1e0678eb0077 100644
--- a/drivers/hwmon/adt7475.c
+++ b/drivers/hwmon/adt7475.c
@@ -23,23 +23,23 @@
#include <linux/util_macros.h>
/* Indexes for the sysfs hooks */
-
-#define INPUT 0
-#define MIN 1
-#define MAX 2
-#define CONTROL 3
-#define OFFSET 3
-#define AUTOMIN 4
-#define THERM 5
-#define HYSTERSIS 6
-
+enum adt_sysfs_id {
+ INPUT = 0,
+ MIN = 1,
+ MAX = 2,
+ CONTROL = 3,
+ OFFSET = 3, // Dup
+ AUTOMIN = 4,
+ THERM = 5,
+ HYSTERSIS = 6,
/*
* These are unique identifiers for the sysfs functions - unlike the
* numbers above, these are not also indexes into an array
*/
+ ALARM = 9,
+ FAULT = 10,
+};
-#define ALARM 9
-#define FAULT 10
/* 7475 Common Registers */
diff --git a/drivers/media/dvb-frontends/stv0367_priv.h b/drivers/media/dvb-frontends/stv0367_priv.h
index 617f605947b2..7f056d1cce82 100644
--- a/drivers/media/dvb-frontends/stv0367_priv.h
+++ b/drivers/media/dvb-frontends/stv0367_priv.h
@@ -25,8 +25,11 @@
#endif
/* MACRO definitions */
+#ifndef MIN
#define MAX(X, Y) ((X) >= (Y) ? (X) : (Y))
#define MIN(X, Y) ((X) <= (Y) ? (X) : (Y))
+#endif
+
#define INRANGE(X, Y, Z) \
((((X) <= (Y)) && ((Y) <= (Z))) || \
(((Z) <= (Y)) && ((Y) <= (X))) ? 1 : 0)
diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c
index 1d1808afd529..792c22ba5b00 100644
--- a/drivers/net/fjes/fjes_main.c
+++ b/drivers/net/fjes/fjes_main.c
@@ -14,9 +14,7 @@
#include "fjes.h"
#include "fjes_trace.h"
-#define MAJ 1
-#define MIN 2
-#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN)
+#define DRV_VERSION "1.2"
#define DRV_NAME "fjes"
char fjes_driver_name[] = DRV_NAME;
char fjes_driver_version[] = DRV_VERSION;
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c
index 37d26f01986b..fd7026206f58 100644
--- a/drivers/nfc/pn544/i2c.c
+++ b/drivers/nfc/pn544/i2c.c
@@ -126,8 +126,6 @@ struct pn544_i2c_fw_secure_blob {
#define PN544_FW_CMD_RESULT_COMMAND_REJECTED 0xE0
#define PN544_FW_CMD_RESULT_CHUNK_ERROR 0xE6
-#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
-
#define PN544_FW_WRITE_BUFFER_MAX_LEN 0x9f7
#define PN544_FW_I2C_MAX_PAYLOAD PN544_HCI_I2C_LLC_MAX_SIZE
#define PN544_FW_I2C_WRITE_FRAME_HEADER_LEN 8
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 336dee9485d4..3c27d6b66bb4 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -757,7 +757,6 @@ static union acpi_object *__call_snc_method(acpi_handle handle, char *method,
return result;
}
-#define MIN(a, b) (a > b ? b : a)
static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value,
void *buffer, size_t buflen)
{
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index bd73f6925a9d..73144b2966ba 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -65,11 +65,7 @@
#include "task.h"
#include "probe_roms.h"
-#define MAJ 1
-#define MIN 2
-#define BUILD 0
-#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
- __stringify(BUILD)
+#define DRV_VERSION "1.2.0"
MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/staging/media/atomisp/pci/hive_isp_css_include/math_support.h b/drivers/staging/media/atomisp/pci/hive_isp_css_include/math_support.h
index a444ec14ff9d..1c17a87a8572 100644
--- a/drivers/staging/media/atomisp/pci/hive_isp_css_include/math_support.h
+++ b/drivers/staging/media/atomisp/pci/hive_isp_css_include/math_support.h
@@ -31,11 +31,6 @@
/* A => B */
#define IMPLIES(a, b) (!(a) || (b))
-/* for preprocessor and array sizing use MIN and MAX
- otherwise use min and max */
-#define MAX(a, b) (((a) > (b)) ? (a) : (b))
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-
#define ROUND_DIV(a, b) (((b) != 0) ? ((a) + ((b) >> 1)) / (b) : 0)
#define CEIL_DIV(a, b) (((b) != 0) ? ((a) + (b) - 1) / (b) : 0)
#define CEIL_MUL(a, b) (CEIL_DIV(a, b) * (b))
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index 9c2848abc804..fc384714da45 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -277,6 +277,8 @@ static inline bool in_range32(u32 val, u32 start, u32 len)
* Use these carefully: no type checking, and uses the arguments
* multiple times. Use for obvious constants only.
*/
+#define MIN(a,b) __cmp(min,a,b)
+#define MAX(a,b) __cmp(max,a,b)
#define MIN_T(type,a,b) __cmp(min,(type)(a),(type)(b))
#define MAX_T(type,a,b) __cmp(max,(type)(a),(type)(b))
diff --git a/kernel/trace/preemptirq_delay_test.c b/kernel/trace/preemptirq_delay_test.c
index 8af92dbe98f0..acb0c971a408 100644
--- a/kernel/trace/preemptirq_delay_test.c
+++ b/kernel/trace/preemptirq_delay_test.c
@@ -34,8 +34,6 @@ MODULE_PARM_DESC(cpu_affinity, "Cpu num test is running on");
static struct completion done;
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
-
static void busy_wait(ulong time)
{
u64 start, end;
diff --git a/lib/btree.c b/lib/btree.c
index b4cf08a5c267..b12f99d4c45c 100644
--- a/lib/btree.c
+++ b/lib/btree.c
@@ -43,7 +43,6 @@
#include <linux/slab.h>
#include <linux/module.h>
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define NODESIZE MAX(L1_CACHE_BYTES, 128)
struct btree_geo {
diff --git a/lib/decompress_unlzma.c b/lib/decompress_unlzma.c
index 20a858031f12..9d34d35908da 100644
--- a/lib/decompress_unlzma.c
+++ b/lib/decompress_unlzma.c
@@ -37,7 +37,9 @@
#include <linux/decompress/mm.h>
+#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
static long long INIT read_int(unsigned char *ptr, int size)
{
diff --git a/lib/zstd/zstd_internal.h b/lib/zstd/zstd_internal.h
index dac753397f86..927ed4e8c11c 100644
--- a/lib/zstd/zstd_internal.h
+++ b/lib/zstd/zstd_internal.h
@@ -36,8 +36,6 @@
/*-*************************************
* shared macros
***************************************/
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define CHECK_F(f) \
{ \
size_t const errcod = f; \
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 79f389d620c9..fd01f6922874 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -126,7 +126,6 @@
#define ISOLATED_BITS 3
#define MAGIC_VAL_BITS 8
-#define MAX(a, b) ((a) >= (b) ? (a) : (b))
/* ZS_MIN_ALLOC_SIZE must be multiple of ZS_ALIGN */
#define ZS_MIN_ALLOC_SIZE \
MAX(32, (ZS_MAX_PAGES_PER_ZSPAGE << PAGE_SHIFT >> OBJ_INDEX_BITS))
diff --git a/tools/testing/selftests/vm/mremap_test.c b/tools/testing/selftests/vm/mremap_test.c
index 58775dab3cc6..92fb74865f26 100644
--- a/tools/testing/selftests/vm/mremap_test.c
+++ b/tools/testing/selftests/vm/mremap_test.c
@@ -22,7 +22,9 @@
#define VALIDATION_DEFAULT_THRESHOLD 4 /* 4MB */
#define VALIDATION_NO_THRESHOLD 0 /* Verify the entire region */
+#ifndef MIN
#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
+#endif
struct config {
unsigned long long src_alignment;
--
2.47.3
^ permalink raw reply related
* [PATCH v2 09/19 5.15.y] minmax: don't use max() in situations that want a C constant expression
From: Eliav Farber @ 2025-10-03 12:59 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Linus Torvalds, David Laight, Lorenzo Stoakes
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: Linus Torvalds <torvalds@linux-foundation.org>
[ Upstream commit cb04e8b1d2f24c4c2c92f7b7529031fc35a16fed ]
We only had a couple of array[] declarations, and changing them to just
use 'MAX()' instead of 'max()' fixes the issue.
This will allow us to simplify our min/max macros enormously, since they
can now unconditionally use temporary variables to avoid using the
argument values multiple times.
Cc: David Laight <David.Laight@aculab.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
drivers/input/touchscreen/cyttsp4_core.c | 2 +-
drivers/irqchip/irq-sun6i-r.c | 2 +-
drivers/md/dm-integrity.c | 2 +-
fs/btrfs/tree-checker.c | 2 +-
lib/vsprintf.c | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c
index dccbcb942fe5..936d69da3bda 100644
--- a/drivers/input/touchscreen/cyttsp4_core.c
+++ b/drivers/input/touchscreen/cyttsp4_core.c
@@ -871,7 +871,7 @@ static void cyttsp4_get_mt_touches(struct cyttsp4_mt_data *md, int num_cur_tch)
struct cyttsp4_touch tch;
int sig;
int i, j, t = 0;
- int ids[max(CY_TMA1036_MAX_TCH, CY_TMA4XX_MAX_TCH)];
+ int ids[MAX(CY_TMA1036_MAX_TCH, CY_TMA4XX_MAX_TCH)];
memset(ids, 0, si->si_ofs.tch_abs[CY_TCH_T].max * sizeof(int));
for (i = 0; i < num_cur_tch; i++) {
diff --git a/drivers/irqchip/irq-sun6i-r.c b/drivers/irqchip/irq-sun6i-r.c
index 4cd3e533740b..74b1bd331425 100644
--- a/drivers/irqchip/irq-sun6i-r.c
+++ b/drivers/irqchip/irq-sun6i-r.c
@@ -268,7 +268,7 @@ static const struct irq_domain_ops sun6i_r_intc_domain_ops = {
static int sun6i_r_intc_suspend(void)
{
- u32 buf[BITS_TO_U32(max(SUN6I_NR_TOP_LEVEL_IRQS, SUN6I_NR_MUX_BITS))];
+ u32 buf[BITS_TO_U32(MAX(SUN6I_NR_TOP_LEVEL_IRQS, SUN6I_NR_MUX_BITS))];
int i;
/* Wake IRQs are enabled during system sleep and shutdown. */
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index 8e2b00536c3e..9e2bbfe328f0 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -1705,7 +1705,7 @@ static void integrity_metadata(struct work_struct *w)
struct bio *bio = dm_bio_from_per_bio_data(dio, sizeof(struct dm_integrity_io));
char *checksums;
unsigned extra_space = unlikely(digest_size > ic->tag_size) ? digest_size - ic->tag_size : 0;
- char checksums_onstack[max((size_t)HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
+ char checksums_onstack[MAX(HASH_MAX_DIGESTSIZE, MAX_TAG_SIZE)];
sector_t sector;
unsigned sectors_to_process;
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
index 51e04efe3e20..8f96ddaceb9a 100644
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -608,7 +608,7 @@ static int check_dir_item(struct extent_buffer *leaf,
*/
if (key->type == BTRFS_DIR_ITEM_KEY ||
key->type == BTRFS_XATTR_ITEM_KEY) {
- char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)];
+ char namebuf[MAX(BTRFS_NAME_LEN, XATTR_NAME_MAX)];
read_extent_buffer(leaf, namebuf,
(unsigned long)(di + 1), name_len);
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index d86abdc77c26..e46eb93c115d 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1100,7 +1100,7 @@ char *resource_string(char *buf, char *end, struct resource *res,
#define FLAG_BUF_SIZE (2 * sizeof(res->flags))
#define DECODED_BUF_SIZE sizeof("[mem - 64bit pref window disabled]")
#define RAW_BUF_SIZE sizeof("[mem - flags 0x]")
- char sym[max(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE,
+ char sym[MAX(2*RSRC_BUF_SIZE + DECODED_BUF_SIZE,
2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)];
char *p = sym, *pend = sym + sizeof(sym);
--
2.47.3
^ permalink raw reply related
* [PATCH v2 10/19 5.15.y] minmax: simplify min()/max()/clamp() implementation
From: Eliav Farber @ 2025-10-03 12:59 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Linus Torvalds, David Laight, Lorenzo Stoakes
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: Linus Torvalds <torvalds@linux-foundation.org>
[ Upstream commit dc1c8034e31b14a2e5e212104ec508aec44ce1b9 ]
Now that we no longer have any C constant expression contexts (ie array
size declarations or static initializers) that use min() or max(), we
can simpify the implementation by not having to worry about the result
staying as a C constant expression.
So now we can unconditionally just use temporary variables of the right
type, and get rid of the excessive expansion that used to come from the
use of
__builtin_choose_expr(__is_constexpr(...), ..
to pick the specialized code for constant expressions.
Another expansion simplification is to pass the temporary variables (in
addition to the original expression) to our __types_ok() macro. That
may superficially look like it complicates the macro, but when we only
want the type of the expression, expanding the temporary variable names
is much simpler and smaller than expanding the potentially complicated
original expression.
As a result, on my machine, doing a
$ time make drivers/staging/media/atomisp/pci/isp/kernels/ynr/ynr_1.0/ia_css_ynr.host.i
goes from
real 0m16.621s
user 0m15.360s
sys 0m1.221s
to
real 0m2.532s
user 0m2.091s
sys 0m0.452s
because the token expansion goes down dramatically.
In particular, the longest line expansion (which was line 71 of that
'ia_css_ynr.host.c' file) shrinks from 23,338kB (yes, 23MB for one
single line) to "just" 1,444kB (now "only" 1.4MB).
And yes, that line is still the line from hell, because it's doing
multiple levels of "min()/max()" expansion thanks to some of them being
hidden inside the uDIGIT_FITTING() macro.
Lorenzo has a nice cleanup patch that makes that driver use inline
functions instead of macros for sDIGIT_FITTING() and uDIGIT_FITTING(),
which will fix that line once and for all, but the 16-fold reduction in
this case does show why we need to simplify these helpers.
Cc: David Laight <David.Laight@aculab.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
include/linux/minmax.h | 43 ++++++++++++++++++++----------------------
1 file changed, 20 insertions(+), 23 deletions(-)
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index fc384714da45..e3e4353df983 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -35,10 +35,10 @@
#define __is_noneg_int(x) \
(__builtin_choose_expr(__is_constexpr(x) && __is_signed(x), x, -1) >= 0)
-#define __types_ok(x, y) \
- (__is_signed(x) == __is_signed(y) || \
- __is_signed((x) + 0) == __is_signed((y) + 0) || \
- __is_noneg_int(x) || __is_noneg_int(y))
+#define __types_ok(x, y, ux, uy) \
+ (__is_signed(ux) == __is_signed(uy) || \
+ __is_signed((ux) + 0) == __is_signed((uy) + 0) || \
+ __is_noneg_int(x) || __is_noneg_int(y))
#define __cmp_op_min <
#define __cmp_op_max >
@@ -51,34 +51,31 @@
#define __cmp_once(op, type, x, y) \
__cmp_once_unique(op, type, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_))
-#define __careful_cmp_once(op, x, y) ({ \
- static_assert(__types_ok(x, y), \
+#define __careful_cmp_once(op, x, y, ux, uy) ({ \
+ __auto_type ux = (x); __auto_type uy = (y); \
+ static_assert(__types_ok(x, y, ux, uy), \
#op "(" #x ", " #y ") signedness error, fix types or consider u" #op "() before " #op "_t()"); \
- __cmp_once(op, __auto_type, x, y); })
+ __cmp(op, ux, uy); })
-#define __careful_cmp(op, x, y) \
- __builtin_choose_expr(__is_constexpr((x) - (y)), \
- __cmp(op, x, y), __careful_cmp_once(op, x, y))
+#define __careful_cmp(op, x, y) \
+ __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_))
#define __clamp(val, lo, hi) \
((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val)))
-#define __clamp_once(val, lo, hi, unique_val, unique_lo, unique_hi) ({ \
- typeof(val) unique_val = (val); \
- typeof(lo) unique_lo = (lo); \
- typeof(hi) unique_hi = (hi); \
+#define __clamp_once(val, lo, hi, uval, ulo, uhi) ({ \
+ __auto_type uval = (val); \
+ __auto_type ulo = (lo); \
+ __auto_type uhi = (hi); \
static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \
(lo) <= (hi), true), \
"clamp() low limit " #lo " greater than high limit " #hi); \
- static_assert(__types_ok(val, lo), "clamp() 'lo' signedness error"); \
- static_assert(__types_ok(val, hi), "clamp() 'hi' signedness error"); \
- __clamp(unique_val, unique_lo, unique_hi); })
-
-#define __careful_clamp(val, lo, hi) ({ \
- __builtin_choose_expr(__is_constexpr((val) - (lo) + (hi)), \
- __clamp(val, lo, hi), \
- __clamp_once(val, lo, hi, __UNIQUE_ID(__val), \
- __UNIQUE_ID(__lo), __UNIQUE_ID(__hi))); })
+ static_assert(__types_ok(uval, lo, uval, ulo), "clamp() 'lo' signedness error"); \
+ static_assert(__types_ok(uval, hi, uval, uhi), "clamp() 'hi' signedness error"); \
+ __clamp(uval, ulo, uhi); })
+
+#define __careful_clamp(val, lo, hi) \
+ __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_))
/**
* min - return minimum of two values of the same or compatible types
--
2.47.3
^ permalink raw reply related
* [PATCH v2 11/19 5.15.y] minmax: improve macro expansion and type checking
From: Eliav Farber @ 2025-10-03 12:59 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Linus Torvalds, Arnd Bergmann, David Laight, Lorenzo Stoakes
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: Linus Torvalds <torvalds@linux-foundation.org>
[ Upstream commit 22f5468731491e53356ba7c028f0fdea20b18e2c ]
This clarifies the rules for min()/max()/clamp() type checking and makes
them a much more efficient macro expansion.
In particular, we now look at the type and range of the inputs to see
whether they work together, generating a mask of acceptable comparisons,
and then just verifying that the inputs have a shared case:
- an expression with a signed type can be used for
(1) signed comparisons
(2) unsigned comparisons if it is statically known to have a
non-negative value
- an expression with an unsigned type can be used for
(3) unsigned comparison
(4) signed comparisons if the type is smaller than 'int' and thus
the C integer promotion rules will make it signed anyway
Here rule (1) and (3) are obvious, and rule (2) is important in order to
allow obvious trivial constants to be used together with unsigned
values.
Rule (4) is not necessarily a good idea, but matches what we used to do,
and we have extant cases of this situation in the kernel. Notably with
bcachefs having an expression like
min(bch2_bucket_sectors_dirty(a), ca->mi.bucket_size)
where bch2_bucket_sectors_dirty() returns an 's64', and
'ca->mi.bucket_size' is of type 'u16'.
Technically that bcachefs comparison is clearly sensible on a C type
level, because the 'u16' will go through the normal C integer promotion,
and become 'int', and then we're comparing two signed values and
everything looks sane.
However, it's not entirely clear that a 'min(s64,u16)' operation makes a
lot of conceptual sense, and it's possible that we will remove rule (4).
After all, the _reason_ we have these complicated type checks is exactly
that the C type promotion rules are not very intuitive.
But at least for now the rule is in place for backwards compatibility.
Also note that rule (2) existed before, but is hugely relaxed by this
commit. It used to be true only for the simplest compile-time
non-negative integer constants. The new macro model will allow cases
where the compiler can trivially see that an expression is non-negative
even if it isn't necessarily a constant.
For example, the amdgpu driver does
min_t(size_t, sizeof(fru_info->serial), pia[addr] & 0x3F));
because our old 'min()' macro would see that 'pia[addr] & 0x3F' is of
type 'int' and clearly not a C constant expression, so doing a 'min()'
with a 'size_t' is a signedness violation.
Our new 'min()' macro still sees that 'pia[addr] & 0x3F' is of type
'int', but is smart enough to also see that it is clearly non-negative,
and thus would allow that case without any complaints.
Cc: Arnd Bergmann <arnd@kernel.org>
Cc: David Laight <David.Laight@aculab.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
include/linux/compiler.h | 9 +++++
include/linux/minmax.h | 74 ++++++++++++++++++++++++++++++++--------
2 files changed, 68 insertions(+), 15 deletions(-)
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 4f03dfb6de0d..ee9e39d315c8 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -258,6 +258,15 @@ static inline void *offset_to_ptr(const int *off)
*/
#define is_signed_type(type) (((type)(-1)) < (__force type)1)
+/*
+ * Useful shorthand for "is this condition known at compile-time?"
+ *
+ * Note that the condition may involve non-constant values,
+ * but the compiler may know enough about the details of the
+ * values to determine that the condition is statically true.
+ */
+#define statically_true(x) (__builtin_constant_p(x) && (x))
+
/*
* This is needed in functions which generate the stack canary, see
* arch/x86/kernel/smpboot.c::start_secondary() for an example.
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index e3e4353df983..41da6f85a407 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -26,19 +26,63 @@
#define __typecheck(x, y) \
(!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
-/* is_signed_type() isn't a constexpr for pointer types */
-#define __is_signed(x) \
- __builtin_choose_expr(__is_constexpr(is_signed_type(typeof(x))), \
- is_signed_type(typeof(x)), 0)
+/*
+ * __sign_use for integer expressions:
+ * bit #0 set if ok for unsigned comparisons
+ * bit #1 set if ok for signed comparisons
+ *
+ * In particular, statically non-negative signed integer
+ * expressions are ok for both.
+ *
+ * NOTE! Unsigned types smaller than 'int' are implicitly
+ * converted to 'int' in expressions, and are accepted for
+ * signed conversions for now. This is debatable.
+ *
+ * Note that 'x' is the original expression, and 'ux' is
+ * the unique variable that contains the value.
+ *
+ * We use 'ux' for pure type checking, and 'x' for when
+ * we need to look at the value (but without evaluating
+ * it for side effects! Careful to only ever evaluate it
+ * with sizeof() or __builtin_constant_p() etc).
+ *
+ * Pointers end up being checked by the normal C type
+ * rules at the actual comparison, and these expressions
+ * only need to be careful to not cause warnings for
+ * pointer use.
+ */
+#define __signed_type_use(x,ux) (2+__is_nonneg(x,ux))
+#define __unsigned_type_use(x,ux) (1+2*(sizeof(ux)<4))
+#define __sign_use(x,ux) (is_signed_type(typeof(ux))? \
+ __signed_type_use(x,ux):__unsigned_type_use(x,ux))
+
+/*
+ * To avoid warnings about casting pointers to integers
+ * of different sizes, we need that special sign type.
+ *
+ * On 64-bit we can just always use 'long', since any
+ * integer or pointer type can just be cast to that.
+ *
+ * This does not work for 128-bit signed integers since
+ * the cast would truncate them, but we do not use s128
+ * types in the kernel (we do use 'u128', but they will
+ * be handled by the !is_signed_type() case).
+ *
+ * NOTE! The cast is there only to avoid any warnings
+ * from when values that aren't signed integer types.
+ */
+#ifdef CONFIG_64BIT
+ #define __signed_type(ux) long
+#else
+ #define __signed_type(ux) typeof(__builtin_choose_expr(sizeof(ux)>4,1LL,1L))
+#endif
+#define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0)
-/* True for a non-negative signed int constant */
-#define __is_noneg_int(x) \
- (__builtin_choose_expr(__is_constexpr(x) && __is_signed(x), x, -1) >= 0)
+#define __types_ok(x,y,ux,uy) \
+ (__sign_use(x,ux) & __sign_use(y,uy))
-#define __types_ok(x, y, ux, uy) \
- (__is_signed(ux) == __is_signed(uy) || \
- __is_signed((ux) + 0) == __is_signed((uy) + 0) || \
- __is_noneg_int(x) || __is_noneg_int(y))
+#define __types_ok3(x,y,z,ux,uy,uz) \
+ (__sign_use(x,ux) & __sign_use(y,uy) & __sign_use(z,uz))
#define __cmp_op_min <
#define __cmp_op_max >
@@ -53,8 +97,8 @@
#define __careful_cmp_once(op, x, y, ux, uy) ({ \
__auto_type ux = (x); __auto_type uy = (y); \
- static_assert(__types_ok(x, y, ux, uy), \
- #op "(" #x ", " #y ") signedness error, fix types or consider u" #op "() before " #op "_t()"); \
+ BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \
+ #op"("#x", "#y") signedness error"); \
__cmp(op, ux, uy); })
#define __careful_cmp(op, x, y) \
@@ -70,8 +114,8 @@
static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \
(lo) <= (hi), true), \
"clamp() low limit " #lo " greater than high limit " #hi); \
- static_assert(__types_ok(uval, lo, uval, ulo), "clamp() 'lo' signedness error"); \
- static_assert(__types_ok(uval, hi, uval, uhi), "clamp() 'hi' signedness error"); \
+ BUILD_BUG_ON_MSG(!__types_ok3(val,lo,hi,uval,ulo,uhi), \
+ "clamp("#val", "#lo", "#hi") signedness error"); \
__clamp(uval, ulo, uhi); })
#define __careful_clamp(val, lo, hi) \
--
2.47.3
^ permalink raw reply related
* [PATCH v2 12/19 5.15.y] minmax: fix up min3() and max3() too
From: Eliav Farber @ 2025-10-03 12:59 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Linus Torvalds, David Laight, Arnd Bergmann
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: Linus Torvalds <torvalds@linux-foundation.org>
[ Upstream commit 21b136cc63d2a9ddd60d4699552b69c214b32964 ]
David Laight pointed out that we should deal with the min3() and max3()
mess too, which still does excessive expansion.
And our current macros are actually rather broken.
In particular, the macros did this:
#define min3(x, y, z) min((typeof(x))min(x, y), z)
#define max3(x, y, z) max((typeof(x))max(x, y), z)
and that not only is a nested expansion of possibly very complex
arguments with all that involves, the typing with that "typeof()" cast
is completely wrong.
For example, imagine what happens in max3() if 'x' happens to be a
'unsigned char', but 'y' and 'z' are 'unsigned long'. The types are
compatible, and there's no warning - but the result is just random
garbage.
No, I don't think we've ever hit that issue in practice, but since we
now have sane infrastructure for doing this right, let's just use it.
It fixes any excessive expansion, and also avoids these kinds of broken
type issues.
Requested-by: David Laight <David.Laight@aculab.com>
Acked-by: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
include/linux/minmax.h | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index 41da6f85a407..98008dd92153 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -152,13 +152,20 @@
#define umax(x, y) \
__careful_cmp(max, (x) + 0u + 0ul + 0ull, (y) + 0u + 0ul + 0ull)
+#define __careful_op3(op, x, y, z, ux, uy, uz) ({ \
+ __auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\
+ BUILD_BUG_ON_MSG(!__types_ok3(x,y,z,ux,uy,uz), \
+ #op"3("#x", "#y", "#z") signedness error"); \
+ __cmp(op, ux, __cmp(op, uy, uz)); })
+
/**
* min3 - return minimum of three values
* @x: first value
* @y: second value
* @z: third value
*/
-#define min3(x, y, z) min((typeof(x))min(x, y), z)
+#define min3(x, y, z) \
+ __careful_op3(min, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_))
/**
* max3 - return maximum of three values
@@ -166,7 +173,8 @@
* @y: second value
* @z: third value
*/
-#define max3(x, y, z) max((typeof(x))max(x, y), z)
+#define max3(x, y, z) \
+ __careful_op3(max, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_))
/**
* min_not_zero - return the minimum that is _not_ zero, unless both are zero
--
2.47.3
^ permalink raw reply related
* [PATCH v2 13/19 5.15.y] minmax.h: add whitespace around operators and after commas
From: Eliav Farber @ 2025-10-03 13:00 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
Jason A. Donenfeld, Jens Axboe, Lorenzo Stoakes, Mateusz Guzik,
Pedro Falcato
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: David Laight <David.Laight@ACULAB.COM>
[ Upstream commit 71ee9b16251ea4bf7c1fe222517c82bdb3220acc ]
Patch series "minmax.h: Cleanups and minor optimisations".
Some tidyups and minor changes to minmax.h.
This patch (of 7):
Link: https://lkml.kernel.org/r/c50365d214e04f9ba256d417c8bebbc0@AcuMS.aculab.com
Link: https://lkml.kernel.org/r/f04b2e1310244f62826267346fde0553@AcuMS.aculab.com
Signed-off-by: David Laight <david.laight@aculab.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Arnd Bergmann <arnd@kernel.org>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Dan Carpenter <dan.carpenter@linaro.org>
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Mateusz Guzik <mjguzik@gmail.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Pedro Falcato <pedro.falcato@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
include/linux/minmax.h | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index 98008dd92153..51b0d988e322 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -51,10 +51,10 @@
* only need to be careful to not cause warnings for
* pointer use.
*/
-#define __signed_type_use(x,ux) (2+__is_nonneg(x,ux))
-#define __unsigned_type_use(x,ux) (1+2*(sizeof(ux)<4))
-#define __sign_use(x,ux) (is_signed_type(typeof(ux))? \
- __signed_type_use(x,ux):__unsigned_type_use(x,ux))
+#define __signed_type_use(x, ux) (2 + __is_nonneg(x, ux))
+#define __unsigned_type_use(x, ux) (1 + 2 * (sizeof(ux) < 4))
+#define __sign_use(x, ux) (is_signed_type(typeof(ux)) ? \
+ __signed_type_use(x, ux) : __unsigned_type_use(x, ux))
/*
* To avoid warnings about casting pointers to integers
@@ -74,15 +74,15 @@
#ifdef CONFIG_64BIT
#define __signed_type(ux) long
#else
- #define __signed_type(ux) typeof(__builtin_choose_expr(sizeof(ux)>4,1LL,1L))
+ #define __signed_type(ux) typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L))
#endif
-#define __is_nonneg(x,ux) statically_true((__signed_type(ux))(x)>=0)
+#define __is_nonneg(x, ux) statically_true((__signed_type(ux))(x) >= 0)
-#define __types_ok(x,y,ux,uy) \
- (__sign_use(x,ux) & __sign_use(y,uy))
+#define __types_ok(x, y, ux, uy) \
+ (__sign_use(x, ux) & __sign_use(y, uy))
-#define __types_ok3(x,y,z,ux,uy,uz) \
- (__sign_use(x,ux) & __sign_use(y,uy) & __sign_use(z,uz))
+#define __types_ok3(x, y, z, ux, uy, uz) \
+ (__sign_use(x, ux) & __sign_use(y, uy) & __sign_use(z, uz))
#define __cmp_op_min <
#define __cmp_op_max >
@@ -97,7 +97,7 @@
#define __careful_cmp_once(op, x, y, ux, uy) ({ \
__auto_type ux = (x); __auto_type uy = (y); \
- BUILD_BUG_ON_MSG(!__types_ok(x,y,ux,uy), \
+ BUILD_BUG_ON_MSG(!__types_ok(x, y, ux, uy), \
#op"("#x", "#y") signedness error"); \
__cmp(op, ux, uy); })
@@ -114,7 +114,7 @@
static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \
(lo) <= (hi), true), \
"clamp() low limit " #lo " greater than high limit " #hi); \
- BUILD_BUG_ON_MSG(!__types_ok3(val,lo,hi,uval,ulo,uhi), \
+ BUILD_BUG_ON_MSG(!__types_ok3(val, lo, hi, uval, ulo, uhi), \
"clamp("#val", "#lo", "#hi") signedness error"); \
__clamp(uval, ulo, uhi); })
@@ -154,7 +154,7 @@
#define __careful_op3(op, x, y, z, ux, uy, uz) ({ \
__auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\
- BUILD_BUG_ON_MSG(!__types_ok3(x,y,z,ux,uy,uz), \
+ BUILD_BUG_ON_MSG(!__types_ok3(x, y, z, ux, uy, uz), \
#op"3("#x", "#y", "#z") signedness error"); \
__cmp(op, ux, __cmp(op, uy, uz)); })
@@ -326,9 +326,9 @@ static inline bool in_range32(u32 val, u32 start, u32 len)
* Use these carefully: no type checking, and uses the arguments
* multiple times. Use for obvious constants only.
*/
-#define MIN(a,b) __cmp(min,a,b)
-#define MAX(a,b) __cmp(max,a,b)
-#define MIN_T(type,a,b) __cmp(min,(type)(a),(type)(b))
-#define MAX_T(type,a,b) __cmp(max,(type)(a),(type)(b))
+#define MIN(a, b) __cmp(min, a, b)
+#define MAX(a, b) __cmp(max, a, b)
+#define MIN_T(type, a, b) __cmp(min, (type)(a), (type)(b))
+#define MAX_T(type, a, b) __cmp(max, (type)(a), (type)(b))
#endif /* _LINUX_MINMAX_H */
--
2.47.3
^ permalink raw reply related
* [PATCH v2 14/19 5.15.y] minmax.h: update some comments
From: Eliav Farber @ 2025-10-03 13:00 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
Jason A. Donenfeld, Jens Axboe, Lorenzo Stoakes, Mateusz Guzik,
Pedro Falcato
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: David Laight <David.Laight@ACULAB.COM>
[ Upstream commit 10666e99204818ef45c702469488353b5bb09ec7 ]
- Change three to several.
- Remove the comment about retaining constant expressions, no longer true.
- Realign to nearer 80 columns and break on major punctiation.
- Add a leading comment to the block before __signed_type() and __is_nonneg()
Otherwise the block explaining the cast is a bit 'floating'.
Reword the rest of that comment to improve readability.
Link: https://lkml.kernel.org/r/85b050c81c1d4076aeb91a6cded45fee@AcuMS.aculab.com
Signed-off-by: David Laight <david.laight@aculab.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Arnd Bergmann <arnd@kernel.org>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Dan Carpenter <dan.carpenter@linaro.org>
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Mateusz Guzik <mjguzik@gmail.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Pedro Falcato <pedro.falcato@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
include/linux/minmax.h | 53 +++++++++++++++++++-----------------------
1 file changed, 24 insertions(+), 29 deletions(-)
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index 51b0d988e322..24e4b372649a 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -8,13 +8,10 @@
#include <linux/types.h>
/*
- * min()/max()/clamp() macros must accomplish three things:
+ * min()/max()/clamp() macros must accomplish several things:
*
* - Avoid multiple evaluations of the arguments (so side-effects like
* "x++" happen only once) when non-constant.
- * - Retain result as a constant expressions when called with only
- * constant expressions (to avoid tripping VLA warnings in stack
- * allocation usage).
* - Perform signed v unsigned type-checking (to generate compile
* errors instead of nasty runtime surprises).
* - Unsigned char/short are always promoted to signed int and can be
@@ -31,25 +28,23 @@
* bit #0 set if ok for unsigned comparisons
* bit #1 set if ok for signed comparisons
*
- * In particular, statically non-negative signed integer
- * expressions are ok for both.
+ * In particular, statically non-negative signed integer expressions
+ * are ok for both.
*
- * NOTE! Unsigned types smaller than 'int' are implicitly
- * converted to 'int' in expressions, and are accepted for
- * signed conversions for now. This is debatable.
+ * NOTE! Unsigned types smaller than 'int' are implicitly converted to 'int'
+ * in expressions, and are accepted for signed conversions for now.
+ * This is debatable.
*
- * Note that 'x' is the original expression, and 'ux' is
- * the unique variable that contains the value.
+ * Note that 'x' is the original expression, and 'ux' is the unique variable
+ * that contains the value.
*
- * We use 'ux' for pure type checking, and 'x' for when
- * we need to look at the value (but without evaluating
- * it for side effects! Careful to only ever evaluate it
- * with sizeof() or __builtin_constant_p() etc).
+ * We use 'ux' for pure type checking, and 'x' for when we need to look at the
+ * value (but without evaluating it for side effects!
+ * Careful to only ever evaluate it with sizeof() or __builtin_constant_p() etc).
*
- * Pointers end up being checked by the normal C type
- * rules at the actual comparison, and these expressions
- * only need to be careful to not cause warnings for
- * pointer use.
+ * Pointers end up being checked by the normal C type rules at the actual
+ * comparison, and these expressions only need to be careful to not cause
+ * warnings for pointer use.
*/
#define __signed_type_use(x, ux) (2 + __is_nonneg(x, ux))
#define __unsigned_type_use(x, ux) (1 + 2 * (sizeof(ux) < 4))
@@ -57,19 +52,19 @@
__signed_type_use(x, ux) : __unsigned_type_use(x, ux))
/*
- * To avoid warnings about casting pointers to integers
- * of different sizes, we need that special sign type.
+ * Check whether a signed value is always non-negative.
*
- * On 64-bit we can just always use 'long', since any
- * integer or pointer type can just be cast to that.
+ * A cast is needed to avoid any warnings from values that aren't signed
+ * integer types (in which case the result doesn't matter).
*
- * This does not work for 128-bit signed integers since
- * the cast would truncate them, but we do not use s128
- * types in the kernel (we do use 'u128', but they will
- * be handled by the !is_signed_type() case).
+ * On 64-bit any integer or pointer type can safely be cast to 'long'.
+ * But on 32-bit we need to avoid warnings about casting pointers to integers
+ * of different sizes without truncating 64-bit values so 'long' or 'long long'
+ * must be used depending on the size of the value.
*
- * NOTE! The cast is there only to avoid any warnings
- * from when values that aren't signed integer types.
+ * This does not work for 128-bit signed integers since the cast would truncate
+ * them, but we do not use s128 types in the kernel (we do use 'u128',
+ * but they are handled by the !is_signed_type() case).
*/
#ifdef CONFIG_64BIT
#define __signed_type(ux) long
--
2.47.3
^ permalink raw reply related
* [PATCH v2 15/19 5.15.y] minmax.h: reduce the #define expansion of min(), max() and clamp()
From: Eliav Farber @ 2025-10-03 13:00 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
Jason A. Donenfeld, Jens Axboe, Lorenzo Stoakes, Mateusz Guzik,
Pedro Falcato
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: David Laight <David.Laight@ACULAB.COM>
[ Upstream commit b280bb27a9f7c91ddab730e1ad91a9c18a051f41 ]
Since the test for signed values being non-negative only relies on
__builtion_constant_p() (not is_constexpr()) it can use the 'ux' variable
instead of the caller supplied expression. This means that the #define
parameters are only expanded twice. Once in the code and once quoted in
the error message.
Link: https://lkml.kernel.org/r/051afc171806425da991908ed8688a98@AcuMS.aculab.com
Signed-off-by: David Laight <david.laight@aculab.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Arnd Bergmann <arnd@kernel.org>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Dan Carpenter <dan.carpenter@linaro.org>
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Mateusz Guzik <mjguzik@gmail.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Pedro Falcato <pedro.falcato@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
include/linux/minmax.h | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index 24e4b372649a..6f7ea669d305 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -46,10 +46,10 @@
* comparison, and these expressions only need to be careful to not cause
* warnings for pointer use.
*/
-#define __signed_type_use(x, ux) (2 + __is_nonneg(x, ux))
-#define __unsigned_type_use(x, ux) (1 + 2 * (sizeof(ux) < 4))
-#define __sign_use(x, ux) (is_signed_type(typeof(ux)) ? \
- __signed_type_use(x, ux) : __unsigned_type_use(x, ux))
+#define __signed_type_use(ux) (2 + __is_nonneg(ux))
+#define __unsigned_type_use(ux) (1 + 2 * (sizeof(ux) < 4))
+#define __sign_use(ux) (is_signed_type(typeof(ux)) ? \
+ __signed_type_use(ux) : __unsigned_type_use(ux))
/*
* Check whether a signed value is always non-negative.
@@ -71,13 +71,13 @@
#else
#define __signed_type(ux) typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L))
#endif
-#define __is_nonneg(x, ux) statically_true((__signed_type(ux))(x) >= 0)
+#define __is_nonneg(ux) statically_true((__signed_type(ux))(ux) >= 0)
-#define __types_ok(x, y, ux, uy) \
- (__sign_use(x, ux) & __sign_use(y, uy))
+#define __types_ok(ux, uy) \
+ (__sign_use(ux) & __sign_use(uy))
-#define __types_ok3(x, y, z, ux, uy, uz) \
- (__sign_use(x, ux) & __sign_use(y, uy) & __sign_use(z, uz))
+#define __types_ok3(ux, uy, uz) \
+ (__sign_use(ux) & __sign_use(uy) & __sign_use(uz))
#define __cmp_op_min <
#define __cmp_op_max >
@@ -92,7 +92,7 @@
#define __careful_cmp_once(op, x, y, ux, uy) ({ \
__auto_type ux = (x); __auto_type uy = (y); \
- BUILD_BUG_ON_MSG(!__types_ok(x, y, ux, uy), \
+ BUILD_BUG_ON_MSG(!__types_ok(ux, uy), \
#op"("#x", "#y") signedness error"); \
__cmp(op, ux, uy); })
@@ -109,7 +109,7 @@
static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \
(lo) <= (hi), true), \
"clamp() low limit " #lo " greater than high limit " #hi); \
- BUILD_BUG_ON_MSG(!__types_ok3(val, lo, hi, uval, ulo, uhi), \
+ BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \
"clamp("#val", "#lo", "#hi") signedness error"); \
__clamp(uval, ulo, uhi); })
@@ -149,7 +149,7 @@
#define __careful_op3(op, x, y, z, ux, uy, uz) ({ \
__auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\
- BUILD_BUG_ON_MSG(!__types_ok3(x, y, z, ux, uy, uz), \
+ BUILD_BUG_ON_MSG(!__types_ok3(ux, uy, uz), \
#op"3("#x", "#y", "#z") signedness error"); \
__cmp(op, ux, __cmp(op, uy, uz)); })
--
2.47.3
^ permalink raw reply related
* [PATCH v2 16/19 5.15.y] minmax.h: use BUILD_BUG_ON_MSG() for the lo < hi test in clamp()
From: Eliav Farber @ 2025-10-03 13:00 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
Jason A. Donenfeld, Jens Axboe, Lorenzo Stoakes, Mateusz Guzik,
Pedro Falcato
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: David Laight <David.Laight@ACULAB.COM>
[ Upstream commit a5743f32baec4728711bbc01d6ac2b33d4c67040 ]
Use BUILD_BUG_ON_MSG(statically_true(ulo > uhi), ...) for the sanity check
of the bounds in clamp(). Gives better error coverage and one less
expansion of the arguments.
Link: https://lkml.kernel.org/r/34d53778977747f19cce2abb287bb3e6@AcuMS.aculab.com
Signed-off-by: David Laight <david.laight@aculab.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Arnd Bergmann <arnd@kernel.org>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Dan Carpenter <dan.carpenter@linaro.org>
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Mateusz Guzik <mjguzik@gmail.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Pedro Falcato <pedro.falcato@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
include/linux/minmax.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index 6f7ea669d305..91aa1b90c1bb 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -106,8 +106,7 @@
__auto_type uval = (val); \
__auto_type ulo = (lo); \
__auto_type uhi = (hi); \
- static_assert(__builtin_choose_expr(__is_constexpr((lo) > (hi)), \
- (lo) <= (hi), true), \
+ BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \
"clamp() low limit " #lo " greater than high limit " #hi); \
BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \
"clamp("#val", "#lo", "#hi") signedness error"); \
--
2.47.3
^ permalink raw reply related
* [PATCH v2 17/19 5.15.y] minmax.h: move all the clamp() definitions after the min/max() ones
From: Eliav Farber @ 2025-10-03 13:00 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
Jason A. Donenfeld, Jens Axboe, Lorenzo Stoakes, Mateusz Guzik,
Pedro Falcato
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: David Laight <David.Laight@ACULAB.COM>
[ Upstream commit c3939872ee4a6b8bdcd0e813c66823b31e6e26f7 ]
At some point the definitions for clamp() got added in the middle of the
ones for min() and max(). Re-order the definitions so they are more
sensibly grouped.
Link: https://lkml.kernel.org/r/8bb285818e4846469121c8abc3dfb6e2@AcuMS.aculab.com
Signed-off-by: David Laight <david.laight@aculab.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Arnd Bergmann <arnd@kernel.org>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Dan Carpenter <dan.carpenter@linaro.org>
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Mateusz Guzik <mjguzik@gmail.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Pedro Falcato <pedro.falcato@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
include/linux/minmax.h | 109 +++++++++++++++++++----------------------
1 file changed, 51 insertions(+), 58 deletions(-)
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index 91aa1b90c1bb..75fb7a6ad4c6 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -99,22 +99,6 @@
#define __careful_cmp(op, x, y) \
__careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_))
-#define __clamp(val, lo, hi) \
- ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val)))
-
-#define __clamp_once(val, lo, hi, uval, ulo, uhi) ({ \
- __auto_type uval = (val); \
- __auto_type ulo = (lo); \
- __auto_type uhi = (hi); \
- BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \
- "clamp() low limit " #lo " greater than high limit " #hi); \
- BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \
- "clamp("#val", "#lo", "#hi") signedness error"); \
- __clamp(uval, ulo, uhi); })
-
-#define __careful_clamp(val, lo, hi) \
- __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_))
-
/**
* min - return minimum of two values of the same or compatible types
* @x: first value
@@ -170,6 +154,22 @@
#define max3(x, y, z) \
__careful_op3(max, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_))
+/**
+ * min_t - return minimum of two values, using the specified type
+ * @type: data type to use
+ * @x: first value
+ * @y: second value
+ */
+#define min_t(type, x, y) __cmp_once(min, type, x, y)
+
+/**
+ * max_t - return maximum of two values, using the specified type
+ * @type: data type to use
+ * @x: first value
+ * @y: second value
+ */
+#define max_t(type, x, y) __cmp_once(max, type, x, y)
+
/**
* min_not_zero - return the minimum that is _not_ zero, unless both are zero
* @x: value1
@@ -180,6 +180,22 @@
typeof(y) __y = (y); \
__x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); })
+#define __clamp(val, lo, hi) \
+ ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val)))
+
+#define __clamp_once(val, lo, hi, uval, ulo, uhi) ({ \
+ __auto_type uval = (val); \
+ __auto_type ulo = (lo); \
+ __auto_type uhi = (hi); \
+ BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \
+ "clamp() low limit " #lo " greater than high limit " #hi); \
+ BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \
+ "clamp("#val", "#lo", "#hi") signedness error"); \
+ __clamp(uval, ulo, uhi); })
+
+#define __careful_clamp(val, lo, hi) \
+ __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_))
+
/**
* clamp - return a value clamped to a given range with strict typechecking
* @val: current value
@@ -191,28 +207,30 @@
*/
#define clamp(val, lo, hi) __careful_clamp(val, lo, hi)
-/*
- * ..and if you can't take the strict
- * types, you can specify one yourself.
- *
- * Or not use min/max/clamp at all, of course.
- */
-
/**
- * min_t - return minimum of two values, using the specified type
- * @type: data type to use
- * @x: first value
- * @y: second value
+ * clamp_t - return a value clamped to a given range using a given type
+ * @type: the type of variable to use
+ * @val: current value
+ * @lo: minimum allowable value
+ * @hi: maximum allowable value
+ *
+ * This macro does no typechecking and uses temporary variables of type
+ * @type to make all the comparisons.
*/
-#define min_t(type, x, y) __cmp_once(min, type, x, y)
+#define clamp_t(type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi))
/**
- * max_t - return maximum of two values, using the specified type
- * @type: data type to use
- * @x: first value
- * @y: second value
+ * clamp_val - return a value clamped to a given range using val's type
+ * @val: current value
+ * @lo: minimum allowable value
+ * @hi: maximum allowable value
+ *
+ * This macro does no typechecking and uses temporary variables of whatever
+ * type the input argument @val is. This is useful when @val is an unsigned
+ * type and @lo and @hi are literals that will otherwise be assigned a signed
+ * integer type.
*/
-#define max_t(type, x, y) __cmp_once(max, type, x, y)
+#define clamp_val(val, lo, hi) clamp_t(typeof(val), val, lo, hi)
/*
* Do not check the array parameter using __must_be_array().
@@ -257,31 +275,6 @@
*/
#define max_array(array, len) __minmax_array(max, array, len)
-/**
- * clamp_t - return a value clamped to a given range using a given type
- * @type: the type of variable to use
- * @val: current value
- * @lo: minimum allowable value
- * @hi: maximum allowable value
- *
- * This macro does no typechecking and uses temporary variables of type
- * @type to make all the comparisons.
- */
-#define clamp_t(type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi))
-
-/**
- * clamp_val - return a value clamped to a given range using val's type
- * @val: current value
- * @lo: minimum allowable value
- * @hi: maximum allowable value
- *
- * This macro does no typechecking and uses temporary variables of whatever
- * type the input argument @val is. This is useful when @val is an unsigned
- * type and @lo and @hi are literals that will otherwise be assigned a signed
- * integer type.
- */
-#define clamp_val(val, lo, hi) clamp_t(typeof(val), val, lo, hi)
-
static inline bool in_range64(u64 val, u64 start, u64 len)
{
return (val - start) < len;
--
2.47.3
^ permalink raw reply related
* [PATCH v2 18/19 5.15.y] minmax.h: simplify the variants of clamp()
From: Eliav Farber @ 2025-10-03 13:00 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
Jason A. Donenfeld, Jens Axboe, Lorenzo Stoakes, Mateusz Guzik,
Pedro Falcato
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: David Laight <David.Laight@ACULAB.COM>
[ Upstream commit 495bba17cdf95e9703af1b8ef773c55ef0dfe703 ]
Always pass a 'type' through to __clamp_once(), pass '__auto_type' from
clamp() itself.
The expansion of __types_ok3() is reasonable so it isn't worth the added
complexity of avoiding it when a fixed type is used for all three values.
Link: https://lkml.kernel.org/r/8f69f4deac014f558bab186444bac2e8@AcuMS.aculab.com
Signed-off-by: David Laight <david.laight@aculab.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Arnd Bergmann <arnd@kernel.org>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Dan Carpenter <dan.carpenter@linaro.org>
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Mateusz Guzik <mjguzik@gmail.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Pedro Falcato <pedro.falcato@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
include/linux/minmax.h | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index 75fb7a6ad4c6..2bbdd5b5e07e 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -183,29 +183,29 @@
#define __clamp(val, lo, hi) \
((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val)))
-#define __clamp_once(val, lo, hi, uval, ulo, uhi) ({ \
- __auto_type uval = (val); \
- __auto_type ulo = (lo); \
- __auto_type uhi = (hi); \
+#define __clamp_once(type, val, lo, hi, uval, ulo, uhi) ({ \
+ type uval = (val); \
+ type ulo = (lo); \
+ type uhi = (hi); \
BUILD_BUG_ON_MSG(statically_true(ulo > uhi), \
"clamp() low limit " #lo " greater than high limit " #hi); \
BUILD_BUG_ON_MSG(!__types_ok3(uval, ulo, uhi), \
"clamp("#val", "#lo", "#hi") signedness error"); \
__clamp(uval, ulo, uhi); })
-#define __careful_clamp(val, lo, hi) \
- __clamp_once(val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_))
+#define __careful_clamp(type, val, lo, hi) \
+ __clamp_once(type, val, lo, hi, __UNIQUE_ID(v_), __UNIQUE_ID(l_), __UNIQUE_ID(h_))
/**
- * clamp - return a value clamped to a given range with strict typechecking
+ * clamp - return a value clamped to a given range with typechecking
* @val: current value
* @lo: lowest allowable value
* @hi: highest allowable value
*
- * This macro does strict typechecking of @lo/@hi to make sure they are of the
- * same type as @val. See the unnecessary pointer comparisons.
+ * This macro checks @val/@lo/@hi to make sure they have compatible
+ * signedness.
*/
-#define clamp(val, lo, hi) __careful_clamp(val, lo, hi)
+#define clamp(val, lo, hi) __careful_clamp(__auto_type, val, lo, hi)
/**
* clamp_t - return a value clamped to a given range using a given type
@@ -217,7 +217,7 @@
* This macro does no typechecking and uses temporary variables of type
* @type to make all the comparisons.
*/
-#define clamp_t(type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi))
+#define clamp_t(type, val, lo, hi) __careful_clamp(type, val, lo, hi)
/**
* clamp_val - return a value clamped to a given range using val's type
@@ -230,7 +230,7 @@
* type and @lo and @hi are literals that will otherwise be assigned a signed
* integer type.
*/
-#define clamp_val(val, lo, hi) clamp_t(typeof(val), val, lo, hi)
+#define clamp_val(val, lo, hi) __careful_clamp(typeof(val), val, lo, hi)
/*
* Do not check the array parameter using __must_be_array().
--
2.47.3
^ permalink raw reply related
* [PATCH v2 19/19 5.15.y] minmax.h: remove some #defines that are only expanded once
From: Eliav Farber @ 2025-10-03 13:00 UTC (permalink / raw)
To: gregkh, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse,
rric, airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, farbere, sashal, quic_akhilpo, ruanjinjie,
David.Laight, herve.codina, linux-arm-kernel, linux-kernel,
linux-um, linux-edac, amd-gfx, dri-devel, linux-arm-msm,
freedreno, linux-hwmon, linux-input, linux-sunxi, linux-media,
netdev, linux-stm32, platform-driver-x86, linux-scsi,
linux-staging, linux-btrfs, linux-ext4, linux-sparse, linux-mm,
netfilter-devel, coreteam, tipc-discussion, linux-kselftest,
stable
Cc: Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
Jason A. Donenfeld, Jens Axboe, Lorenzo Stoakes, Mateusz Guzik,
Pedro Falcato
In-Reply-To: <20251003130006.41681-1-farbere@amazon.com>
From: David Laight <David.Laight@ACULAB.COM>
[ Upstream commit 2b97aaf74ed534fb838d09867d09a3ca5d795208 ]
The bodies of __signed_type_use() and __unsigned_type_use() are much the
same size as their names - so put the bodies in the only line that expands
them.
Similarly __signed_type() is defined separately for 64bit and then used
exactly once just below.
Change the test for __signed_type from CONFIG_64BIT to one based on gcc
defined macros so that the code is valid if it gets used outside of a
kernel build.
Link: https://lkml.kernel.org/r/9386d1ebb8974fbabbed2635160c3975@AcuMS.aculab.com
Signed-off-by: David Laight <david.laight@aculab.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Arnd Bergmann <arnd@kernel.org>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Dan Carpenter <dan.carpenter@linaro.org>
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Mateusz Guzik <mjguzik@gmail.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Pedro Falcato <pedro.falcato@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Eliav Farber <farbere@amazon.com>
---
include/linux/minmax.h | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/include/linux/minmax.h b/include/linux/minmax.h
index 2bbdd5b5e07e..eaaf5c008e4d 100644
--- a/include/linux/minmax.h
+++ b/include/linux/minmax.h
@@ -46,10 +46,8 @@
* comparison, and these expressions only need to be careful to not cause
* warnings for pointer use.
*/
-#define __signed_type_use(ux) (2 + __is_nonneg(ux))
-#define __unsigned_type_use(ux) (1 + 2 * (sizeof(ux) < 4))
#define __sign_use(ux) (is_signed_type(typeof(ux)) ? \
- __signed_type_use(ux) : __unsigned_type_use(ux))
+ (2 + __is_nonneg(ux)) : (1 + 2 * (sizeof(ux) < 4)))
/*
* Check whether a signed value is always non-negative.
@@ -57,7 +55,7 @@
* A cast is needed to avoid any warnings from values that aren't signed
* integer types (in which case the result doesn't matter).
*
- * On 64-bit any integer or pointer type can safely be cast to 'long'.
+ * On 64-bit any integer or pointer type can safely be cast to 'long long'.
* But on 32-bit we need to avoid warnings about casting pointers to integers
* of different sizes without truncating 64-bit values so 'long' or 'long long'
* must be used depending on the size of the value.
@@ -66,12 +64,12 @@
* them, but we do not use s128 types in the kernel (we do use 'u128',
* but they are handled by the !is_signed_type() case).
*/
-#ifdef CONFIG_64BIT
- #define __signed_type(ux) long
+#if __SIZEOF_POINTER__ == __SIZEOF_LONG_LONG__
+#define __is_nonneg(ux) statically_true((long long)(ux) >= 0)
#else
- #define __signed_type(ux) typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L))
+#define __is_nonneg(ux) statically_true( \
+ (typeof(__builtin_choose_expr(sizeof(ux) > 4, 1LL, 1L)))(ux) >= 0)
#endif
-#define __is_nonneg(ux) statically_true((__signed_type(ux))(ux) >= 0)
#define __types_ok(ux, uy) \
(__sign_use(ux) & __sign_use(uy))
--
2.47.3
^ permalink raw reply related
* [PATCH] Input: atmel_mxt_ts - allow reset GPIO to sleep
From: Marek Vasut @ 2025-10-05 2:33 UTC (permalink / raw)
To: linux-input; +Cc: Marek Vasut, Dmitry Torokhov, Nick Dyer
The reset GPIO is not toggled in any critical section where it couldn't
sleep, allow the reset GPIO to sleep. This allows the driver to operate
reset GPIOs connected to I2C GPIO expanders.
Signed-off-by: Marek Vasut <marek.vasut@mailbox.org>
---
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Nick Dyer <nick@shmanahar.org>
Cc: linux-input@vger.kernel.org
---
drivers/input/touchscreen/atmel_mxt_ts.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index fc624101147ec..dd0544cc1bc1a 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -3320,7 +3320,7 @@ static int mxt_probe(struct i2c_client *client)
if (data->reset_gpio) {
/* Wait a while and then de-assert the RESET GPIO line */
msleep(MXT_RESET_GPIO_TIME);
- gpiod_set_value(data->reset_gpio, 0);
+ gpiod_set_value_cansleep(data->reset_gpio, 0);
msleep(MXT_RESET_INVALID_CHG);
}
--
2.51.0
^ permalink raw reply related
* [BUG] Side buttons not detected on Telink 2.4G mouse (ID 320f:226f)
From: Артем Бігдаш @ 2025-10-05 17:57 UTC (permalink / raw)
To: linux-input
Hello,
I am reporting an issue with a wireless mouse that uses a Telink 2.4G
receiver. The side buttons (Forward/Back) are not detected by the
system.
Device Information:
- Name: Redragon King Lite
- lsusb ID: 320f:226f Telink 2.4G Wireless Receiver
- System: Fedora 42, KDE Plasma
Diagnostics:
- Standard tools like `evtest` and `libinput debug-events` show no
events when the side buttons are pressed. The kernel does not seem to
create any evdev events for them.
- However, `hid-recorder` on the correct hidraw interface
(`/dev/hidraw1`) successfully captures the raw HID reports.
Raw HID Reports:
Pressing the first side button (likely Back/Forward) sends this report:
E: ... 8 01 10 00 00 00 00 00 00
Releasing it sends:
E: ... 8 01 00 00 00 00 00 00 00
Pressing the second side button (likely Forward/Back) sends this report:
E: ... 8 01 08 00 00 00 00 00 00
Releasing it sends:
E: ... 8 01 00 00 00 00 00 00 00
It seems the `usbhid` driver does not correctly parse these HID
reports (report ID 1, second byte mask 0x10 and 0x08) into standard
KEY_BACK/KEY_FORWARD events.
Could you please advise if a quirk can be added to the kernel to
support this device correctly? All the necessary diagnostic data
appears to be above.
Thank you for your time and work on the Linux kernel.
Best regards,
Btema2
^ permalink raw reply
* [PATCH] HID: multitouch: add IGNORE_DUPLICATES quirk for ELAN1206 (04f3:30f1)
From: Matt Roberts @ 2025-10-05 19:45 UTC (permalink / raw)
To: linux-input; +Cc: jikos, bentiss, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1901 bytes --]
From: Matthew Roberts <robertsmattb@gmail.com>
Date: Sun, 5 Oct 2025 11:34:17 -0700
Subject: [PATCH] HID: multitouch: add IGNORE_DUPLICATES quirk for ELAN1206
(04f3:30f1)
Some ELAN1206 I2C touchpads intermittently report duplicate tracking IDs.
On recent kernels this can make libinput interpret a one-finger slide as
repeated hold/click events instead of continuous POINTER_MOTION.
Add MT_QUIRK_IGNORE_DUPLICATES for 04f3:30f1 so the driver filters
repeated contacts and reports motion correctly. This restores behavior
comparable to 6.1 LTS kernels where motion and clicks were normal.
Reproducer notes: with hid_multitouch enabled, sliding a single finger
produces repeated GESTURE_HOLD_BEGIN/END in libinput and logs the
"double tracking ID ... in slot 0" error. Attached are short traces:
- elan1206-bug.yaml (libinput record)
- elan1206-bug.evemu (evdev stream)
- elan1206-bug.hidraw0 (HID raw capture)
- elan1206-bug.libinput (debug stream)
System: Fedora 42 (kernel 6.16.9-200.fc42.x86_64,
libinput 1.29.1,
device ELAN1206:00 04F3:30F1)
Signed-off-by: Matthew Roberts <robertsmattb@gmail.com>
---
drivers/hid/hid-multitouch.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 2879e65cf..ed318c80e 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -2150,6 +2150,10 @@ static const struct hid_device_id mt_devices[] = {
HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8,
USB_VENDOR_ID_ELAN, 0x32ae) },
+ /* ELAN1206 touchpad: duplicate tracking IDs cause hold/click storms */
+ { .driver_data = MT_QUIRK_IGNORE_DUPLICATES,
+ HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH, 0x04f3, 0x30f1) },
+
/* Elitegroup panel */
{ .driver_data = MT_CLS_SERIAL,
MT_USB_DEVICE(USB_VENDOR_ID_ELITEGROUP,
--
2.51.0
[-- Attachment #2: elan1206-bug.yaml --]
[-- Type: application/yaml, Size: 34795 bytes --]
[-- Attachment #3: elan1206-bug.evemu --]
[-- Type: application/octet-stream, Size: 24857 bytes --]
# EVEMU 1.3
# Kernel: 6.16.9-200.fc42.x86_64
# DMI: dmi:bvnAmericanMegatrendsInternational,LLC.:bvrUX564EH.313:bd04/21/2022:br5.19:svnASUSTeKCOMPUTERINC.:pnZenBookUX564EH_Q528EH:pvr1.0:rvnASUSTeKCOMPUTERINC.:rnUX564EH:rvr1.0:cvnASUSTeKCOMPUTERINC.:ct31:cvr1.0:sku:
# Input device name: "ELAN1206:00 04F3:30F1 Touchpad"
# Input device ID: bus 0x18 vendor 0x4f3 product 0x30f1 version 0x100
# Size in mm: 124x63
# Supported events:
# Event type 0 (EV_SYN)
# Event code 0 (SYN_REPORT)
# Event code 1 (SYN_CONFIG)
# Event code 2 (SYN_MT_REPORT)
# Event code 3 (SYN_DROPPED)
# Event code 4 ((null))
# Event code 5 ((null))
# Event code 6 ((null))
# Event code 7 ((null))
# Event code 8 ((null))
# Event code 9 ((null))
# Event code 10 ((null))
# Event code 11 ((null))
# Event code 12 ((null))
# Event code 13 ((null))
# Event code 14 ((null))
# Event code 15 (SYN_MAX)
# Event type 1 (EV_KEY)
# Event code 272 (BTN_LEFT)
# Event code 325 (BTN_TOOL_FINGER)
# Event code 328 (BTN_TOOL_QUINTTAP)
# Event code 330 (BTN_TOUCH)
# Event code 333 (BTN_TOOL_DOUBLETAP)
# Event code 334 (BTN_TOOL_TRIPLETAP)
# Event code 335 (BTN_TOOL_QUADTAP)
# Event type 3 (EV_ABS)
# Event code 0 (ABS_X)
# Value 3301
# Min 0
# Max 3987
# Fuzz 0
# Flat 0
# Resolution 32
# Event code 1 (ABS_Y)
# Value 1013
# Min 0
# Max 1960
# Fuzz 0
# Flat 0
# Resolution 31
# Event code 47 (ABS_MT_SLOT)
# Value 0
# Min 0
# Max 4
# Fuzz 0
# Flat 0
# Resolution 0
# Event code 53 (ABS_MT_POSITION_X)
# Value 0
# Min 0
# Max 3987
# Fuzz 0
# Flat 0
# Resolution 32
# Event code 54 (ABS_MT_POSITION_Y)
# Value 0
# Min 0
# Max 1960
# Fuzz 0
# Flat 0
# Resolution 31
# Event code 55 (ABS_MT_TOOL_TYPE)
# Value 0
# Min 0
# Max 2
# Fuzz 0
# Flat 0
# Resolution 0
# Event code 57 (ABS_MT_TRACKING_ID)
# Value 0
# Min 0
# Max 65535
# Fuzz 0
# Flat 0
# Resolution 0
# Event type 4 (EV_MSC)
# Event code 5 (MSC_TIMESTAMP)
# Properties:
# Property type 0 (INPUT_PROP_POINTER)
# Property type 2 (INPUT_PROP_BUTTONPAD)
N: ELAN1206:00 04F3:30F1 Touchpad
I: 0018 04f3 30f1 0100
P: 05 00 00 00 00 00 00 00
B: 00 0b 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 01 00 00 00 00 00
B: 01 20 e5 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 01 00 00 00 00 00 00 00 00
B: 02 00 00 00 00 00 00 00 00
B: 03 03 00 00 00 00 80 e0 02
B: 04 20 00 00 00 00 00 00 00
B: 05 00 00 00 00 00 00 00 00
B: 11 00 00 00 00 00 00 00 00
B: 12 00 00 00 00 00 00 00 00
B: 14 00 00 00 00 00 00 00 00
B: 15 00 00 00 00 00 00 00 00
B: 15 00 00 00 00 00 00 00 00
A: 00 0 3987 0 0 32
A: 01 0 1960 0 0 31
A: 2f 0 4 0 0 0
A: 35 0 3987 0 0 32
A: 36 0 1960 0 0 31
A: 37 0 2 0 0 0
A: 39 0 65535 0 0 0
################################
# Waiting for events #
################################
E: 0.000001 0003 0039 0048 # EV_ABS / ABS_MT_TRACKING_ID 48
E: 0.000001 0003 0037 0000 # EV_ABS / ABS_MT_TOOL_TYPE 0
E: 0.000001 0003 0035 0282 # EV_ABS / ABS_MT_POSITION_X 282
E: 0.000001 0003 0036 1691 # EV_ABS / ABS_MT_POSITION_Y 1691
E: 0.000001 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 0.000001 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 0.000001 0003 0000 0282 # EV_ABS / ABS_X 282
E: 0.000001 0003 0001 1691 # EV_ABS / ABS_Y 1691
E: 0.000001 0004 0005 0000 # EV_MSC / MSC_TIMESTAMP 0
E: 0.000001 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +0ms
E: 0.103853 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 0.103853 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 0.103853 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 0.103853 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +103ms
E: 0.207904 0003 0039 0049 # EV_ABS / ABS_MT_TRACKING_ID 49
E: 0.207904 0003 0035 1102 # EV_ABS / ABS_MT_POSITION_X 1102
E: 0.207904 0003 0036 0509 # EV_ABS / ABS_MT_POSITION_Y 509
E: 0.207904 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 0.207904 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 0.207904 0003 0000 1102 # EV_ABS / ABS_X 1102
E: 0.207904 0003 0001 0509 # EV_ABS / ABS_Y 509
E: 0.207904 0004 0005 288000 # EV_MSC / MSC_TIMESTAMP 288000
E: 0.207904 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 0.311823 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 0.311823 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 0.311823 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 0.311823 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 0.415939 0003 0039 0050 # EV_ABS / ABS_MT_TRACKING_ID 50
E: 0.415939 0003 0035 1089 # EV_ABS / ABS_MT_POSITION_X 1089
E: 0.415939 0003 0036 1736 # EV_ABS / ABS_MT_POSITION_Y 1736
E: 0.415939 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 0.415939 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 0.415939 0003 0000 1089 # EV_ABS / ABS_X 1089
E: 0.415939 0003 0001 1736 # EV_ABS / ABS_Y 1736
E: 0.415939 0004 0005 499000 # EV_MSC / MSC_TIMESTAMP 499000
E: 0.415939 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 0.519933 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 0.519933 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 0.519933 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 0.519933 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 0.624009 0003 0039 0051 # EV_ABS / ABS_MT_TRACKING_ID 51
E: 0.624009 0003 0035 1715 # EV_ABS / ABS_MT_POSITION_X 1715
E: 0.624009 0003 0036 0405 # EV_ABS / ABS_MT_POSITION_Y 405
E: 0.624009 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 0.624009 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 0.624009 0003 0000 1715 # EV_ABS / ABS_X 1715
E: 0.624009 0003 0001 0405 # EV_ABS / ABS_Y 405
E: 0.624009 0004 0005 708000 # EV_MSC / MSC_TIMESTAMP 708000
E: 0.624009 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +105ms
E: 0.727827 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 0.727827 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 0.727827 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 0.727827 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +103ms
E: 0.831992 0003 0039 0052 # EV_ABS / ABS_MT_TRACKING_ID 52
E: 0.831992 0003 0035 1641 # EV_ABS / ABS_MT_POSITION_X 1641
E: 0.831992 0003 0036 1235 # EV_ABS / ABS_MT_POSITION_Y 1235
E: 0.831992 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 0.831992 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 0.831992 0003 0000 1641 # EV_ABS / ABS_X 1641
E: 0.831992 0003 0001 1235 # EV_ABS / ABS_Y 1235
E: 0.831992 0004 0005 917000 # EV_MSC / MSC_TIMESTAMP 917000
E: 0.831992 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 0.935841 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 0.935841 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 0.935841 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 0.935841 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 1.039851 0003 0039 0053 # EV_ABS / ABS_MT_TRACKING_ID 53
E: 1.039851 0003 0035 2276 # EV_ABS / ABS_MT_POSITION_X 2276
E: 1.039851 0003 0036 0992 # EV_ABS / ABS_MT_POSITION_Y 992
E: 1.039851 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 1.039851 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 1.039851 0003 0000 2276 # EV_ABS / ABS_X 2276
E: 1.039851 0003 0001 0992 # EV_ABS / ABS_Y 992
E: 1.039851 0004 0005 1127000 # EV_MSC / MSC_TIMESTAMP 1127000
E: 1.039851 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 1.143819 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 1.143819 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 1.143819 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 1.143819 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 1.248022 0003 0039 0054 # EV_ABS / ABS_MT_TRACKING_ID 54
E: 1.248022 0003 0035 2879 # EV_ABS / ABS_MT_POSITION_X 2879
E: 1.248022 0003 0036 0561 # EV_ABS / ABS_MT_POSITION_Y 561
E: 1.248022 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 1.248022 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 1.248022 0003 0000 2879 # EV_ABS / ABS_X 2879
E: 1.248022 0003 0001 0561 # EV_ABS / ABS_Y 561
E: 1.248022 0004 0005 1336000 # EV_MSC / MSC_TIMESTAMP 1336000
E: 1.248022 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +105ms
E: 1.351708 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 1.351708 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 1.351708 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 1.351708 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +103ms
E: 1.455939 0003 0039 0055 # EV_ABS / ABS_MT_TRACKING_ID 55
E: 1.455939 0003 0035 2644 # EV_ABS / ABS_MT_POSITION_X 2644
E: 1.455939 0003 0036 1683 # EV_ABS / ABS_MT_POSITION_Y 1683
E: 1.455939 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 1.455939 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 1.455939 0003 0000 2644 # EV_ABS / ABS_X 2644
E: 1.455939 0003 0001 1683 # EV_ABS / ABS_Y 1683
E: 1.455939 0004 0005 1546000 # EV_MSC / MSC_TIMESTAMP 1546000
E: 1.455939 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 1.559843 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 1.559843 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 1.559843 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 1.559843 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 1.663994 0003 0039 0056 # EV_ABS / ABS_MT_TRACKING_ID 56
E: 1.663994 0003 0035 3109 # EV_ABS / ABS_MT_POSITION_X 3109
E: 1.663994 0003 0036 0613 # EV_ABS / ABS_MT_POSITION_Y 613
E: 1.663994 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 1.663994 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 1.663994 0003 0000 3109 # EV_ABS / ABS_X 3109
E: 1.663994 0003 0001 0613 # EV_ABS / ABS_Y 613
E: 1.663994 0004 0005 1757000 # EV_MSC / MSC_TIMESTAMP 1757000
E: 1.663994 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 1.767875 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 1.767875 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 1.767875 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 1.767875 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 1.872006 0003 0039 0057 # EV_ABS / ABS_MT_TRACKING_ID 57
E: 1.872006 0003 0035 1091 # EV_ABS / ABS_MT_POSITION_X 1091
E: 1.872006 0003 0036 1523 # EV_ABS / ABS_MT_POSITION_Y 1523
E: 1.872006 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 1.872006 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 1.872006 0003 0000 1091 # EV_ABS / ABS_X 1091
E: 1.872006 0003 0001 1523 # EV_ABS / ABS_Y 1523
E: 1.872006 0004 0005 1966000 # EV_MSC / MSC_TIMESTAMP 1966000
E: 1.872006 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +105ms
E: 1.976005 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 1.976005 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 1.976005 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 1.976005 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 2.079965 0003 0039 0058 # EV_ABS / ABS_MT_TRACKING_ID 58
E: 2.079965 0003 0035 0920 # EV_ABS / ABS_MT_POSITION_X 920
E: 2.079965 0003 0036 0503 # EV_ABS / ABS_MT_POSITION_Y 503
E: 2.079965 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 2.079965 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 2.079965 0003 0000 0920 # EV_ABS / ABS_X 920
E: 2.079965 0003 0001 0503 # EV_ABS / ABS_Y 503
E: 2.079965 0004 0005 2174900 # EV_MSC / MSC_TIMESTAMP 2174900
E: 2.079965 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +103ms
E: 2.183710 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 2.183710 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 2.183710 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 2.183710 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 2.287917 0003 0039 0059 # EV_ABS / ABS_MT_TRACKING_ID 59
E: 2.287917 0003 0035 1480 # EV_ABS / ABS_MT_POSITION_X 1480
E: 2.287917 0003 0036 1337 # EV_ABS / ABS_MT_POSITION_Y 1337
E: 2.287917 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 2.287917 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 2.287917 0003 0000 1480 # EV_ABS / ABS_X 1480
E: 2.287917 0003 0001 1337 # EV_ABS / ABS_Y 1337
E: 2.287917 0004 0005 2384900 # EV_MSC / MSC_TIMESTAMP 2384900
E: 2.287917 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 2.391719 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 2.391719 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 2.391719 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 2.391719 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 2.495982 0003 0039 0060 # EV_ABS / ABS_MT_TRACKING_ID 60
E: 2.495982 0003 0035 2505 # EV_ABS / ABS_MT_POSITION_X 2505
E: 2.495982 0003 0036 0896 # EV_ABS / ABS_MT_POSITION_Y 896
E: 2.495982 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 2.495982 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 2.495982 0003 0000 2505 # EV_ABS / ABS_X 2505
E: 2.495982 0003 0001 0896 # EV_ABS / ABS_Y 896
E: 2.495982 0004 0005 2593900 # EV_MSC / MSC_TIMESTAMP 2593900
E: 2.495982 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 2.600711 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 2.600711 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 2.600711 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 2.600711 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +105ms
E: 2.704019 0003 0039 0061 # EV_ABS / ABS_MT_TRACKING_ID 61
E: 2.704019 0003 0035 3508 # EV_ABS / ABS_MT_POSITION_X 3508
E: 2.704019 0003 0036 0713 # EV_ABS / ABS_MT_POSITION_Y 713
E: 2.704019 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 2.704019 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 2.704019 0003 0000 3508 # EV_ABS / ABS_X 3508
E: 2.704019 0003 0001 0713 # EV_ABS / ABS_Y 713
E: 2.704019 0004 0005 2803900 # EV_MSC / MSC_TIMESTAMP 2803900
E: 2.704019 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 2.807901 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 2.807901 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 2.807901 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 2.807901 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +103ms
E: 2.911827 0003 0039 0062 # EV_ABS / ABS_MT_TRACKING_ID 62
E: 2.911827 0003 0035 2139 # EV_ABS / ABS_MT_POSITION_X 2139
E: 2.911827 0003 0036 1328 # EV_ABS / ABS_MT_POSITION_Y 1328
E: 2.911827 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 2.911827 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 2.911827 0003 0000 2139 # EV_ABS / ABS_X 2139
E: 2.911827 0003 0001 1328 # EV_ABS / ABS_Y 1328
E: 2.911827 0004 0005 3013900 # EV_MSC / MSC_TIMESTAMP 3013900
E: 2.911827 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 3.015842 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 3.015842 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 3.015842 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 3.015842 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 3.119907 0003 0039 0063 # EV_ABS / ABS_MT_TRACKING_ID 63
E: 3.119907 0003 0035 0868 # EV_ABS / ABS_MT_POSITION_X 868
E: 3.119907 0003 0036 1101 # EV_ABS / ABS_MT_POSITION_Y 1101
E: 3.119907 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 3.119907 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 3.119907 0003 0000 0868 # EV_ABS / ABS_X 868
E: 3.119907 0003 0001 1101 # EV_ABS / ABS_Y 1101
E: 3.119907 0004 0005 3223900 # EV_MSC / MSC_TIMESTAMP 3223900
E: 3.119907 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 3.223828 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 3.223828 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 3.223828 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 3.223828 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 3.327959 0003 0039 0064 # EV_ABS / ABS_MT_TRACKING_ID 64
E: 3.327959 0003 0035 1783 # EV_ABS / ABS_MT_POSITION_X 1783
E: 3.327959 0003 0036 1035 # EV_ABS / ABS_MT_POSITION_Y 1035
E: 3.327959 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 3.327959 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 3.327959 0003 0000 1783 # EV_ABS / ABS_X 1783
E: 3.327959 0003 0001 1035 # EV_ABS / ABS_Y 1035
E: 3.327959 0004 0005 3433900 # EV_MSC / MSC_TIMESTAMP 3433900
E: 3.327959 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 3.432038 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 3.432038 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 3.432038 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 3.432038 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +105ms
E: 3.535977 0003 0039 0065 # EV_ABS / ABS_MT_TRACKING_ID 65
E: 3.535977 0003 0035 2871 # EV_ABS / ABS_MT_POSITION_X 2871
E: 3.535977 0003 0036 0492 # EV_ABS / ABS_MT_POSITION_Y 492
E: 3.535977 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 3.535977 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 3.535977 0003 0000 2871 # EV_ABS / ABS_X 2871
E: 3.535977 0003 0001 0492 # EV_ABS / ABS_Y 492
E: 3.535977 0004 0005 3642900 # EV_MSC / MSC_TIMESTAMP 3642900
E: 3.535977 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +103ms
E: 3.639835 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 3.639835 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 3.639835 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 3.639835 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 3.744122 0003 0039 0066 # EV_ABS / ABS_MT_TRACKING_ID 66
E: 3.744122 0003 0035 2379 # EV_ABS / ABS_MT_POSITION_X 2379
E: 3.744122 0003 0036 1455 # EV_ABS / ABS_MT_POSITION_Y 1455
E: 3.744122 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 3.744122 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 3.744122 0003 0000 2379 # EV_ABS / ABS_X 2379
E: 3.744122 0003 0001 1455 # EV_ABS / ABS_Y 1455
E: 3.744122 0004 0005 3852900 # EV_MSC / MSC_TIMESTAMP 3852900
E: 3.744122 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +105ms
E: 3.848030 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 3.848030 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 3.848030 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 3.848030 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 3.951958 0003 0039 0067 # EV_ABS / ABS_MT_TRACKING_ID 67
E: 3.951958 0003 0035 3032 # EV_ABS / ABS_MT_POSITION_X 3032
E: 3.951958 0003 0036 0210 # EV_ABS / ABS_MT_POSITION_Y 210
E: 3.951958 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 3.951958 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 3.951958 0003 0000 3032 # EV_ABS / ABS_X 3032
E: 3.951958 0003 0001 0210 # EV_ABS / ABS_Y 210
E: 3.951958 0004 0005 4062900 # EV_MSC / MSC_TIMESTAMP 4062900
E: 3.951958 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +103ms
E: 4.055836 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 4.055836 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 4.055836 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 4.055836 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 4.160008 0003 0039 0068 # EV_ABS / ABS_MT_TRACKING_ID 68
E: 4.160008 0003 0035 0790 # EV_ABS / ABS_MT_POSITION_X 790
E: 4.160008 0003 0036 1200 # EV_ABS / ABS_MT_POSITION_Y 1200
E: 4.160008 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 4.160008 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 4.160008 0003 0000 0790 # EV_ABS / ABS_X 790
E: 4.160008 0003 0001 1200 # EV_ABS / ABS_Y 1200
E: 4.160008 0004 0005 4271900 # EV_MSC / MSC_TIMESTAMP 4271900
E: 4.160008 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +105ms
E: 4.264019 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 4.264019 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 4.264019 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 4.264019 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 4.367902 0003 0039 0069 # EV_ABS / ABS_MT_TRACKING_ID 69
E: 4.367902 0003 0035 1563 # EV_ABS / ABS_MT_POSITION_X 1563
E: 4.367902 0003 0036 0196 # EV_ABS / ABS_MT_POSITION_Y 196
E: 4.367902 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 4.367902 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 4.367902 0003 0000 1563 # EV_ABS / ABS_X 1563
E: 4.367902 0003 0001 0196 # EV_ABS / ABS_Y 196
E: 4.367902 0004 0005 4481900 # EV_MSC / MSC_TIMESTAMP 4481900
E: 4.367902 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +103ms
E: 4.471992 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 4.471992 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 4.471992 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 4.471992 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 4.575998 0003 0039 0070 # EV_ABS / ABS_MT_TRACKING_ID 70
E: 4.575998 0003 0035 1927 # EV_ABS / ABS_MT_POSITION_X 1927
E: 4.575998 0003 0036 1520 # EV_ABS / ABS_MT_POSITION_Y 1520
E: 4.575998 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 4.575998 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 4.575998 0003 0000 1927 # EV_ABS / ABS_X 1927
E: 4.575998 0003 0001 1520 # EV_ABS / ABS_Y 1520
E: 4.575998 0004 0005 4691900 # EV_MSC / MSC_TIMESTAMP 4691900
E: 4.575998 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 4.679835 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 4.679835 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 4.679835 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 4.679835 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 4.783941 0003 0039 0071 # EV_ABS / ABS_MT_TRACKING_ID 71
E: 4.783941 0003 0035 2590 # EV_ABS / ABS_MT_POSITION_X 2590
E: 4.783941 0003 0036 0273 # EV_ABS / ABS_MT_POSITION_Y 273
E: 4.783941 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 4.783941 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 4.783941 0003 0000 2590 # EV_ABS / ABS_X 2590
E: 4.783941 0003 0001 0273 # EV_ABS / ABS_Y 273
E: 4.783941 0004 0005 4900900 # EV_MSC / MSC_TIMESTAMP 4900900
E: 4.783941 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 4.887840 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 4.887840 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 4.887840 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 4.887840 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 4.991998 0003 0039 0072 # EV_ABS / ABS_MT_TRACKING_ID 72
E: 4.991998 0003 0035 2746 # EV_ABS / ABS_MT_POSITION_X 2746
E: 4.991998 0003 0036 1252 # EV_ABS / ABS_MT_POSITION_Y 1252
E: 4.991998 0001 014a 0001 # EV_KEY / BTN_TOUCH 1
E: 4.991998 0001 0145 0001 # EV_KEY / BTN_TOOL_FINGER 1
E: 4.991998 0003 0000 2746 # EV_ABS / ABS_X 2746
E: 4.991998 0003 0001 1252 # EV_ABS / ABS_Y 1252
E: 4.991998 0004 0005 5110900 # EV_MSC / MSC_TIMESTAMP 5110900
E: 4.991998 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 5.095834 0003 0039 -001 # EV_ABS / ABS_MT_TRACKING_ID -1
E: 5.095834 0001 014a 0000 # EV_KEY / BTN_TOUCH 0
E: 5.095834 0001 0145 0000 # EV_KEY / BTN_TOOL_FINGER 0
E: 5.095834 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
E: 5.199967 0004 0005 5324900 # EV_MSC / MSC_TIMESTAMP 5324900
E: 5.199967 0000 0000 0000 # ------------ SYN_REPORT (0) ---------- +104ms
[-- Attachment #4: elan1206-bug.hidraw0 --]
[-- Type: application/octet-stream, Size: 2624 bytes --]
D: 0
R: 374 05 01 09 02 a1 01 85 01 09 01 a1 00 05 09 19 01 29 02 15 00 25 01 75 01 95 02 81 02 95 06 81 03 05 01 09 30 09 31 09 38 15 81 25 7f 75 08 95 03 81 06 05 0c 0a 38 02 95 01 81 06 75 08 95 03 81 03 c0 06 00 ff 09 01 85 0e 09 c5 15 00 26 ff 00 75 08 95 04 b1 02 c0 05 0d 09 05 a1 01 85 04 09 22 a1 02 15 00 25 01 09 47 09 42 95 02 75 01 81 02 75 01 95 02 81 03 95 01 75 04 25 0f 09 51 81 02 05 01 15 00 26 93 0f 75 10 55 0e 65 13 09 30 35 00 46 f2 01 95 01 81 02 46 f5 00 26 a8 07 26 a8 07 09 31 81 02 05 0d 15 00 25 64 95 03 c0 55 0c 66 01 10 47 ff ff 00 00 27 ff ff 00 00 75 10 95 01 09 56 81 02 09 54 25 7f 95 01 75 08 81 02 05 09 09 01 25 01 75 01 95 01 81 02 95 07 81 03 09 c5 75 08 95 04 81 03 05 0d 85 02 09 55 09 59 75 04 95 02 25 0f b1 02 85 07 09 60 75 01 95 01 15 00 25 01 b1 02 95 0f b1 03 06 00 ff 06 00 ff 85 06 09 c5 15 00 26 ff 00 75 08 96 00 01 b1 02 85 0d 09 c4 15 00 26 ff 00 75 08 95 04 b1 02 85 0c 09 c6 96 40 03 75 08 b1 02 85 0b 09 c7 95 42 75 08 b1 02 c0 05 0d 09 0e a1 01 85 03 09 22 a1 00 09 52 15 00 25 0a 75 10 95 01 b1 02 c0 09 22 a1 00 85 05 09 57 09 58 75 01 95 02 25 03 b1 02 95 0e b1 03 c0 c0
N: ELAN1206:00 04F3:30F1
P: i2c-ELAN1206:00
I: 18 04f3 30f1
D: 0
E: 0.000000 14 04 03 ae 00 51 06 20 b4 01 80 1a 33 00 00
E: 0.207907 14 04 03 36 02 30 02 20 be 01 80 26 54 00 00
E: 0.415997 14 04 03 5a 02 0e 04 54 c6 01 80 21 44 00 00
E: 0.623879 14 04 03 d2 02 55 06 7e ce 01 80 23 44 00 00
E: 0.831981 14 04 03 ec 03 b4 02 b2 d6 01 80 25 44 00 00
E: 1.039956 14 04 03 67 04 92 03 dc de 01 80 24 44 00 00
E: 1.248030 14 04 03 84 04 da 05 10 e7 01 80 24 44 00 00
E: 1.455983 14 04 03 ad 05 46 03 44 ef 01 80 25 44 00 00
E: 1.664005 14 04 03 0e 07 df 01 6e f7 01 80 24 44 00 00
E: 1.872028 14 04 03 fb 05 c5 05 a2 ff 01 80 21 44 00 00
E: 2.080123 14 04 03 11 07 c1 03 cc 07 01 80 20 44 00 00
E: 2.288009 14 04 03 27 08 07 01 00 10 01 80 23 44 00 00
E: 2.495840 14 04 03 57 07 44 05 34 18 01 80 23 45 00 00
E: 2.704006 14 04 03 ce 08 f9 03 5e 20 01 80 20 44 00 00
E: 2.911981 14 04 03 4c 0a 74 00 92 28 01 80 1e 34 00 00
E: 3.120022 14 04 03 d9 09 35 05 bc 30 01 80 20 34 00 00
E: 3.327936 14 04 03 ed 0a 99 03 fa 38 01 80 1e 43 00 00
E: 3.536070 14 04 01 b4 0a 28 01 24 41 01 80 21 34 00 00
E: 3.743720 14 04 03 2a 0c 98 01 b6 45 01 80 21 44 00 00
E: 3.952006 14 04 03 55 0d df 03 82 51 01 80 21 44 00 00
E: 4.160065 14 04 03 ad 0b 4f 03 ac 59 01 80 21 44 00 00
E: 4.367930 14 04 03 7c 06 50 05 e0 61 01 80 23 44 00 00
E: 4.575959 14 04 03 f2 07 b0 02 14 6a 01 80 23 44 00 00
E: 4.783997 14 04 03 3e 0d 2e 02 3e 72 01 80 17 11 00 00
E: 4.992032 14 04 01 3e 0d 2e 02 72 7a 00 00 17 11 00 00
[-- Attachment #5: elan1206-bug.libinput --]
[-- Type: application/octet-stream, Size: 3638 bytes --]
-event15 DEVICE_ADDED ELAN1206:00 04F3:30F1 Touchpad seat0 default group1 cap:pg size 125x63mm tap (dl off) left scroll-nat scroll-2fg-edge click-buttonareas-clickfinger dwt-on dwtp-on
event15 GESTURE_HOLD_BEGIN +0.248s 1
event15 GESTURE_HOLD_END +0.312s 1
event15 GESTURE_HOLD_BEGIN +0.457s 1
event15 GESTURE_HOLD_END +0.520s 1
event15 GESTURE_HOLD_BEGIN +0.664s 1
event15 GESTURE_HOLD_END +0.728s 1
event15 GESTURE_HOLD_BEGIN +0.872s 1
event15 GESTURE_HOLD_END +0.936s 1
event15 GESTURE_HOLD_BEGIN +1.080s 1
event15 GESTURE_HOLD_END +1.144s 1
event15 GESTURE_HOLD_BEGIN +1.288s 1
event15 GESTURE_HOLD_END +1.352s 1
event15 GESTURE_HOLD_BEGIN +1.496s 1
event15 GESTURE_HOLD_END +1.560s 1
event15 GESTURE_HOLD_BEGIN +1.704s 1
event15 GESTURE_HOLD_END +1.768s 1
event15 GESTURE_HOLD_BEGIN +1.912s 1
event15 GESTURE_HOLD_END +1.976s 1
event15 GESTURE_HOLD_BEGIN +2.120s 1
event15 GESTURE_HOLD_END +2.184s 1
event15 GESTURE_HOLD_BEGIN +2.328s 1
event15 GESTURE_HOLD_END +2.392s 1
event15 GESTURE_HOLD_BEGIN +2.536s 1
event15 GESTURE_HOLD_END +2.600s 1
event15 GESTURE_HOLD_BEGIN +2.744s 1
event15 GESTURE_HOLD_END +2.808s 1
event15 GESTURE_HOLD_BEGIN +2.952s 1
event15 GESTURE_HOLD_END +3.016s 1
event15 GESTURE_HOLD_BEGIN +3.160s 1
event15 GESTURE_HOLD_END +3.224s 1
event15 GESTURE_HOLD_BEGIN +3.368s 1
event15 GESTURE_HOLD_END +3.432s 1
event15 GESTURE_HOLD_BEGIN +3.576s 1
event15 GESTURE_HOLD_END +3.640s 1
event15 GESTURE_HOLD_BEGIN +3.784s 1
event15 GESTURE_HOLD_END +3.848s 1
event15 GESTURE_HOLD_BEGIN +4.200s 1
event15 GESTURE_HOLD_END +4.264s 1
event15 GESTURE_HOLD_BEGIN +4.408s 1
event15 GESTURE_HOLD_END +4.472s 1
event15 GESTURE_HOLD_BEGIN +4.616s 1
event15 GESTURE_HOLD_END +4.680s 1
event15 GESTURE_HOLD_BEGIN +4.824s 1
event15 GESTURE_HOLD_END +4.888s 1
event15 GESTURE_HOLD_BEGIN +5.032s 1
event15 GESTURE_HOLD_END +5.096s 1
event15 GESTURE_HOLD_BEGIN +5.240s 1
event15 GESTURE_HOLD_END +5.304s 1
event15 GESTURE_HOLD_BEGIN +5.656s 1
event15 GESTURE_HOLD_END +5.720s 1
event15 GESTURE_HOLD_BEGIN +5.864s 1
event15 GESTURE_HOLD_END +5.928s 1
event15 GESTURE_HOLD_BEGIN +6.072s 1
event15 GESTURE_HOLD_END +6.136s 1
event15 GESTURE_HOLD_BEGIN +6.280s 1
event15 GESTURE_HOLD_END +6.344s 1
event15 GESTURE_HOLD_BEGIN +6.488s 1
event15 GESTURE_HOLD_END +6.552s 1
event15 GESTURE_HOLD_BEGIN +6.696s 1
event15 GESTURE_HOLD_END +6.760s 1
event15 GESTURE_HOLD_BEGIN +6.904s 1
event15 GESTURE_HOLD_END +6.968s 1
event15 GESTURE_HOLD_BEGIN +7.112s 1
event15 GESTURE_HOLD_END +7.176s 1
event15 GESTURE_HOLD_BEGIN +7.320s 1
event15 GESTURE_HOLD_END +7.384s 1
event15 GESTURE_HOLD_BEGIN +7.736s 1
event15 GESTURE_HOLD_END +7.800s 1
event15 GESTURE_HOLD_BEGIN +7.944s 1
event15 GESTURE_HOLD_END +8.008s 1
^ permalink raw reply related
* [PATCH] HID: logitech-hidpp: Add HIDPP_QUIRK_RESET_HI_RES_SCROLL
From: Stuart Hayhurst @ 2025-10-06 1:05 UTC (permalink / raw)
To: Jiri Kosina, linux-input
Cc: Stuart Hayhurst, linux-kernel, Benjamin Tissoires, Bastien Nocera,
Filipe Laíns
The Logitech G502 Hero Wireless's high resolution scrolling resets after
being unplugged without notifying the driver, causing extremely slow
scrolling.
The only indication of this is a battery update packet, so add a quirk to
detect when the device is unplugged and re-enable the scrolling.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=218037
Signed-off-by: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
---
I assume this affects more than just my mouse, but I don't have the hardware
to find out which other mice need this too.
---
drivers/hid/hid-logitech-hidpp.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index aaef405a717e..5e763de4b94f 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -75,6 +75,7 @@ MODULE_PARM_DESC(disable_tap_to_click,
#define HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS BIT(27)
#define HIDPP_QUIRK_HI_RES_SCROLL_1P0 BIT(28)
#define HIDPP_QUIRK_WIRELESS_STATUS BIT(29)
+#define HIDPP_QUIRK_RESET_HI_RES_SCROLL BIT(30)
/* These are just aliases for now */
#define HIDPP_QUIRK_KBD_SCROLL_WHEEL HIDPP_QUIRK_HIDPP_WHEELS
@@ -193,6 +194,7 @@ struct hidpp_device {
void *private_data;
struct work_struct work;
+ struct work_struct reset_hi_res_work;
struct kfifo delayed_work_fifo;
struct input_dev *delayed_input;
@@ -3836,6 +3838,7 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
struct hidpp_report *answer = hidpp->send_receive_buf;
struct hidpp_report *report = (struct hidpp_report *)data;
int ret;
+ int last_online;
/*
* If the mutex is locked then we have a pending answer from a
@@ -3877,6 +3880,7 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
"See: https://gitlab.freedesktop.org/jwrdegoede/logitech-27mhz-keyboard-encryption-setup/\n");
}
+ last_online = hidpp->battery.online;
if (hidpp->capabilities & HIDPP_CAPABILITY_HIDPP20_BATTERY) {
ret = hidpp20_battery_event_1000(hidpp, data, size);
if (ret != 0)
@@ -3901,6 +3905,11 @@ static int hidpp_raw_hidpp_event(struct hidpp_device *hidpp, u8 *data,
return ret;
}
+ if (hidpp->quirks & HIDPP_QUIRK_RESET_HI_RES_SCROLL) {
+ if (last_online == 0 && hidpp->battery.online == 1)
+ schedule_work(&hidpp->reset_hi_res_work);
+ }
+
if (hidpp->quirks & HIDPP_QUIRK_HIDPP_WHEELS) {
ret = hidpp10_wheel_raw_event(hidpp, data, size);
if (ret != 0)
@@ -4274,6 +4283,13 @@ static void hidpp_connect_event(struct work_struct *work)
hidpp->delayed_input = input;
}
+static void hidpp_reset_hi_res_handler(struct work_struct *work)
+{
+ struct hidpp_device *hidpp = container_of(work, struct hidpp_device, reset_hi_res_work);
+
+ hi_res_scroll_enable(hidpp);
+}
+
static DEVICE_ATTR(builtin_power_supply, 0000, NULL, NULL);
static struct attribute *sysfs_attrs[] = {
@@ -4404,6 +4420,7 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id)
}
INIT_WORK(&hidpp->work, hidpp_connect_event);
+ INIT_WORK(&hidpp->reset_hi_res_work, hidpp_reset_hi_res_handler);
mutex_init(&hidpp->send_mutex);
init_waitqueue_head(&hidpp->wait);
@@ -4499,6 +4516,7 @@ static void hidpp_remove(struct hid_device *hdev)
hid_hw_stop(hdev);
cancel_work_sync(&hidpp->work);
+ cancel_work_sync(&hidpp->reset_hi_res_work);
mutex_destroy(&hidpp->send_mutex);
}
@@ -4546,6 +4564,9 @@ static const struct hid_device_id hidpp_devices[] = {
{ /* Keyboard MX5500 (Bluetooth-receiver in HID proxy mode) */
LDJ_DEVICE(0xb30b),
.driver_data = HIDPP_QUIRK_HIDPP_CONSUMER_VENDOR_KEYS },
+ { /* Logitech G502 Lightspeed Wireless Gaming Mouse */
+ LDJ_DEVICE(0x407f),
+ .driver_data = HIDPP_QUIRK_RESET_HI_RES_SCROLL },
{ LDJ_DEVICE(HID_ANY_ID) },
--
2.51.0
^ permalink raw reply related
* Re: [PATCH v2 07/19 5.15.y] minmax: simplify and clarify min_t()/max_t() implementation
From: Greg KH @ 2025-10-06 10:47 UTC (permalink / raw)
To: Eliav Farber
Cc: jdike, richard, anton.ivanov, dave.hansen, luto, peterz, tglx,
mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, james.morse, rric,
airlied, daniel, maarten.lankhorst, mripard, tzimmermann,
robdclark, sean, jdelvare, linux, linus.walleij, dmitry.torokhov,
maz, wens, jernej.skrabec, agk, snitzer, dm-devel, davem, kuba,
mcoquelin.stm32, krzysztof.kozlowski, malattia, hdegoede, mgross,
jejb, martin.petersen, sakari.ailus, clm, josef, dsterba, jack,
tytso, adilger.kernel, dushistov, luc.vanoostenryck, rostedt,
pmladek, senozhatsky, andriy.shevchenko, linux, minchan, ngupta,
akpm, yoshfuji, dsahern, pablo, kadlec, fw, jmaloy, ying.xue,
shuah, willy, sashal, quic_akhilpo, ruanjinjie, David.Laight,
herve.codina, linux-arm-kernel, linux-kernel, linux-um,
linux-edac, amd-gfx, dri-devel, linux-arm-msm, freedreno,
linux-hwmon, linux-input, linux-sunxi, linux-media, netdev,
linux-stm32, platform-driver-x86, linux-scsi, linux-staging,
linux-btrfs, linux-ext4, linux-sparse, linux-mm, netfilter-devel,
coreteam, tipc-discussion, linux-kselftest, stable,
Linus Torvalds, Lorenzo Stoakes
In-Reply-To: <20251003130006.41681-8-farbere@amazon.com>
On Fri, Oct 03, 2025 at 12:59:54PM +0000, Eliav Farber wrote:
> From: Linus Torvalds <torvalds@linux-foundation.org>
>
> [ Upstream commit 017fa3e89187848fd056af757769c9e66ac3e93d ]
>
> This simplifies the min_t() and max_t() macros by no longer making them
> work in the context of a C constant expression.
>
> That means that you can no longer use them for static initializers or
> for array sizes in type definitions, but there were only a couple of
> such uses, and all of them were converted (famous last words) to use
> MIN_T/MAX_T instead.
>
> Cc: David Laight <David.Laight@aculab.com>
> Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> Signed-off-by: Eliav Farber <farbere@amazon.com>
Eliav, your testing infrastructure needs some work, this patch breaks
the build on this kernel tree:
In file included from ./include/linux/kernel.h:16,
from ./include/linux/list.h:9,
from ./include/linux/wait.h:7,
from ./include/linux/wait_bit.h:8,
from ./include/linux/fs.h:6,
from fs/erofs/internal.h:10,
from fs/erofs/zdata.h:9,
from fs/erofs/zdata.c:6:
fs/erofs/zdata.c: In function ‘z_erofs_decompress_pcluster’:
fs/erofs/zdata.h:185:61: error: ISO C90 forbids variable length array ‘pages_onstack’ [-Werror=vla]
185 | min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U)
| ^~~~
./include/linux/minmax.h:49:23: note: in definition of macro ‘__cmp_once_unique’
49 | ({ type ux = (x); type uy = (y); __cmp(op, ux, uy); })
| ^
./include/linux/minmax.h:164:27: note: in expansion of macro ‘__cmp_once’
164 | #define min_t(type, x, y) __cmp_once(min, type, x, y)
| ^~~~~~~~~~
fs/erofs/zdata.h:185:9: note: in expansion of macro ‘min_t’
185 | min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U)
| ^~~~~
fs/erofs/zdata.c:847:36: note: in expansion of macro ‘Z_EROFS_VMAP_ONSTACK_PAGES’
847 | struct page *pages_onstack[Z_EROFS_VMAP_ONSTACK_PAGES];
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
I'll drop this whole series, please do a bit more testing before sending
out a new version.
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH v2 07/19 5.15.y] minmax: simplify and clarify min_t()/max_t() implementation
From: David Laight @ 2025-10-06 20:35 UTC (permalink / raw)
To: Greg KH
Cc: Eliav Farber, dave.hansen, peterz, tglx, mingo, bp, x86, hpa,
james.morse, rric, daniel, maarten.lankhorst, mripard,
tzimmermann, sean, jdelvare, linux, linus.walleij,
dmitry.torokhov, maz, wens, jernej.skrabec, agk, snitzer,
dm-devel, davem, kuba, mcoquelin.stm32, krzysztof.kozlowski,
malattia, hdegoede, mgross, jejb, martin.petersen, sakari.ailus,
clm, josef, dsterba, jack, tytso, adilger.kernel, dushistov,
luc.vanoostenryck, rostedt, pmladek, senozhatsky,
andriy.shevchenko, linux, minchan, ngupta, akpm, yoshfuji,
dsahern, pablo, kadlec, fw, jmaloy, ying.xue, shuah, willy,
sashal, quic_akhilpo, ruanjinjie, David.Laight, herve.codina,
linux-arm-kernel, linux-kernel, linux-um, linux-edac, amd-gfx,
dri-devel, linux-arm-msm, freedreno, linux-hwmon, linux-input,
linux-sunxi, linux-media, netdev, linux-stm32,
platform-driver-x86, linux-scsi, linux-staging, linux-btrfs,
linux-ext4, linux-sparse, linux-mm, netfilter-devel, coreteam,
tipc-discussion, linux-kselftest, stable, Linus Torvalds,
Lorenzo Stoakes
In-Reply-To: <2025100648-capable-register-101b@gregkh>
On Mon, 6 Oct 2025 12:47:45 +0200
Greg KH <gregkh@linuxfoundation.org> wrote:
(I've had to trim the 'To' list to send this...)
> On Fri, Oct 03, 2025 at 12:59:54PM +0000, Eliav Farber wrote:
> > From: Linus Torvalds <torvalds@linux-foundation.org>
> >
> > [ Upstream commit 017fa3e89187848fd056af757769c9e66ac3e93d ]
> >
> > This simplifies the min_t() and max_t() macros by no longer making them
> > work in the context of a C constant expression.
> >
> > That means that you can no longer use them for static initializers or
> > for array sizes in type definitions, but there were only a couple of
> > such uses, and all of them were converted (famous last words) to use
> > MIN_T/MAX_T instead.
> >
> > Cc: David Laight <David.Laight@aculab.com>
> > Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
> > Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> > Signed-off-by: Eliav Farber <farbere@amazon.com>
>
> Eliav, your testing infrastructure needs some work, this patch breaks
> the build on this kernel tree:
>
> In file included from ./include/linux/kernel.h:16,
> from ./include/linux/list.h:9,
> from ./include/linux/wait.h:7,
> from ./include/linux/wait_bit.h:8,
> from ./include/linux/fs.h:6,
> from fs/erofs/internal.h:10,
> from fs/erofs/zdata.h:9,
> from fs/erofs/zdata.c:6:
> fs/erofs/zdata.c: In function ‘z_erofs_decompress_pcluster’:
> fs/erofs/zdata.h:185:61: error: ISO C90 forbids variable length array ‘pages_onstack’ [-Werror=vla]
> 185 | min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U)
> | ^~~~
That constant seems to get (renamed and) changed to 32 in a later patch.
I'm not sure of the rational for the min() at all.
I think THREAD_SIZE is the size of the kernel stack? Or at least related to it.
The default seems to be 8k on x86-64 and 4k or 8k on i386.
So it is pretty much always going to be 96.
Linus added MIN() that can be used for array sizes.
But I'd guess this could just be changed to 32 - need to ask the erofs guys.
David
> ./include/linux/minmax.h:49:23: note: in definition of macro ‘__cmp_once_unique’
> 49 | ({ type ux = (x); type uy = (y); __cmp(op, ux, uy); })
> | ^
> ./include/linux/minmax.h:164:27: note: in expansion of macro ‘__cmp_once’
> 164 | #define min_t(type, x, y) __cmp_once(min, type, x, y)
> | ^~~~~~~~~~
> fs/erofs/zdata.h:185:9: note: in expansion of macro ‘min_t’
> 185 | min_t(unsigned int, THREAD_SIZE / 8 / sizeof(struct page *), 96U)
> | ^~~~~
> fs/erofs/zdata.c:847:36: note: in expansion of macro ‘Z_EROFS_VMAP_ONSTACK_PAGES’
> 847 | struct page *pages_onstack[Z_EROFS_VMAP_ONSTACK_PAGES];
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~
> cc1: all warnings being treated as errors
>
>
> I'll drop this whole series, please do a bit more testing before sending
> out a new version.
>
> thanks,
>
> greg k-h
>
^ permalink raw reply
* [PATCH 3/3] HID: nintendo: Rate limit IMU compensation message
From: Vicki Pfau @ 2025-10-07 1:05 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, linux-input; +Cc: Vicki Pfau
In-Reply-To: <20251007010533.3777922-1-vi@endrift.com>
Some controllers are very bad at updating the IMU, leading to these
messages spamming the syslog. Rate-limiting them helps with this a bit.
Signed-off-by: Vicki Pfau <vi@endrift.com>
---
drivers/hid/hid-nintendo.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
index e3e54f1df44fa..c2849a541f65a 100644
--- a/drivers/hid/hid-nintendo.c
+++ b/drivers/hid/hid-nintendo.c
@@ -1455,10 +1455,10 @@ static void joycon_parse_imu_report(struct joycon_ctlr *ctlr,
ctlr->imu_avg_delta_ms;
ctlr->imu_timestamp_us += 1000 * ctlr->imu_avg_delta_ms;
if (dropped_pkts > JC_IMU_DROPPED_PKT_WARNING) {
- hid_warn(ctlr->hdev,
+ hid_warn_ratelimited(ctlr->hdev,
"compensating for %u dropped IMU reports\n",
dropped_pkts);
- hid_warn(ctlr->hdev,
+ hid_warn_ratelimited(ctlr->hdev,
"delta=%u avg_delta=%u\n",
delta, ctlr->imu_avg_delta_ms);
}
--
2.51.0
^ permalink raw reply related
* [PATCH 2/3] HID: nintendo: Wait longer for initial probe
From: Vicki Pfau @ 2025-10-07 1:05 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, linux-input; +Cc: Vicki Pfau
In-Reply-To: <20251007010533.3777922-1-vi@endrift.com>
Some third-party controllers, such as the PB Tails CHOC, won't always
respond quickly on startup. Since this packet is needed for probe, and only
once during probe, let's just wait an extra second, which makes connecting
consistent.
Signed-off-by: Vicki Pfau <vi@endrift.com>
---
drivers/hid/hid-nintendo.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
index fb4985988615b..e3e54f1df44fa 100644
--- a/drivers/hid/hid-nintendo.c
+++ b/drivers/hid/hid-nintendo.c
@@ -2420,7 +2420,7 @@ static int joycon_read_info(struct joycon_ctlr *ctlr)
struct joycon_input_report *report;
req.subcmd_id = JC_SUBCMD_REQ_DEV_INFO;
- ret = joycon_send_subcmd(ctlr, &req, 0, HZ);
+ ret = joycon_send_subcmd(ctlr, &req, 0, 2 * HZ);
if (ret) {
hid_err(ctlr->hdev, "Failed to get joycon info; ret=%d\n", ret);
return ret;
--
2.51.0
^ permalink raw reply related
* [PATCH 1/3] HID: core: Add printk_ratelimited variants to hid_warn() etc
From: Vicki Pfau @ 2025-10-07 1:05 UTC (permalink / raw)
To: Jiri Kosina, Benjamin Tissoires, linux-input; +Cc: Vicki Pfau
hid_warn_ratelimited() is needed. Add the others as part of the block.
Signed-off-by: Vicki Pfau <vi@endrift.com>
---
include/linux/hid.h | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 2cc4f1e4ea963..bd66cf6164941 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -1261,4 +1261,15 @@ void hid_quirks_exit(__u16 bus);
#define hid_dbg_once(hid, fmt, ...) \
dev_dbg_once(&(hid)->dev, fmt, ##__VA_ARGS__)
+#define hid_err_ratelimited(hid, fmt, ...) \
+ dev_err_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
+#define hid_notice_ratelimited(hid, fmt, ...) \
+ dev_notice_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
+#define hid_warn_ratelimited(hid, fmt, ...) \
+ dev_warn_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
+#define hid_info_ratelimited(hid, fmt, ...) \
+ dev_info_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
+#define hid_dbg_ratelimited(hid, fmt, ...) \
+ dev_dbg_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
+
#endif
--
2.51.0
^ permalink raw reply related
* Re: hid_multitouch - random non-responsive, multitouch, scrolling and zooming
From: Steven Haigh @ 2025-10-07 1:42 UTC (permalink / raw)
To: Benjamin Tissoires; +Cc: Stéphane Chatty, Peter Hutterer, linux-input
In-Reply-To: <d058871a-a2c6-4197-a77c-08edb0ce70b4@app.fastmail.com>
[-- Attachment #1: Type: text/plain, Size: 3645 bytes --]
On 6/10/25 19:30, Benjamin Tissoires wrote:
> Hi Steven,
>
> On Sat, Oct 4, 2025, at 12:23 PM, Steven Haigh wrote:
>> Hi guys,
>>
>> Firstly, I apologise for contacting you directly - I couldn't find a bug
>> reporting / method to try to debug this issue.
>
> No worries. Though usually it's best to Cc the LKML with linux-input@vger.kernel.org. So unless you prefer not to, I'd like to include this in feature emails so that other will benefit from the same.
Thanks, I've added that address to this reply.
>>
>> I have a Dell Inspiron 5515 which has a touchpad that seems to be
>> controled via hid_multitouch.
>>
>> While using it in Fedora (Currently the F43 beta with kernel 6.17), I
>> have random times where the keypad stops responding, or gets locked into
>> zoom mode, or scroll mode.
>>
>> When it gets like this, I can't move the cursor and basically smooshing
>> the touchpad with clicks or other input seems to be the only way I've
>> found it to recover.
>
> This remembers me about https://gitlab.freedesktop.org/libinput/libinput/-/issues/1194
>
> TL;DR is that there is a bug in the hid-multitouch driver that doesn't entirely mimic the Windows driver, and some touches might get stuck because the firmware forgets to send the releases. I have a better kernel fix for that but because we are in the middle of the v6.18 kernel merge window, I can not post and merge it yet.
From the description of this, it sounds very much like the problem.
It's been driving me nuts for quite a long time - to the point where I
just close the laptop and go use a desktop sometimes. I figured I'd
finally try to get a fix instead - because if it affects me, it will
affect others at some point.
Logically, yes, it does make sense that the trackpad is thinking there
are touches that just don't exist. I also thought that because I have
bigger hands than average, that maybe its also detecting a single touch
as double sometimes - but your description seems to be more fitting to
the situation.
> Meanwhile, for people having the DLL0945 I've opened a temporary stop gap through https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/204
>
> There is a high chance this works for you too (I've tested this on 3 different laptops with different DLL* numbers), but to be sure it's not messing with your system, can you send me the full output of `sudo libinput record` with the touchpad node?
I've followed the "installing from CI" instructions with the artifacts
from that Merge Request and run the install.sh.
I can see the firmware files in /usr/local/lib/firmware/hid/bpf
I rebooted, but I don't see anything in /sys/fs/bpf/hid
I thought that maybe they need to be in the initramfs, so ran `dracut
--regenerate-all -f` and rebooted again - but still nothing in
/sys/fs/bpf/hid.
Do I need to do something else here?
I ran `libinput record -o recording.yml /dev/event/input6` and have
attached the compressed output. Annoyingly, it seems like the touchpad
is working fine at the moment - so it may confirm the hardware
information, but not a recording of the problem right now.
>>
>> This seems to be worse if the kernel clock is not synced via NTP - I
>> have no idea why.
>>
>> Are you able to give me some hints / pointers in how I could start to
>> debug this?
>
> Hopefully this is the exact same bug, and we already have a fix (and a temporary band aid).
>
> Cheers,
> Benjamin
>
>>
>> evtest shows the devices as:
>> /dev/input/event5: DELL0A78:00 27C6:0D42 Mouse
>> /dev/input/event6: DELL0A78:00 27C6:0D42 Touchpad
--
Steven Haigh
📧 netwiz@crc.id.au
💻 https://crc.id.au
[-- Attachment #2: recording.yml.xz --]
[-- Type: application/x-xz, Size: 54172 bytes --]
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox