Linux Input/HID development
 help / color / mirror / Atom feed
* Re: [PATCH v5 1/3] dt-bindings: touchscreen: convert eeti bindings to json schema
From: Sebastian Reichel @ 2025-09-20 20:39 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: linux-kernel, linux-amarula, Conor Dooley, Dmitry Torokhov,
	Krzysztof Kozlowski, Rob Herring, devicetree, linux-input
In-Reply-To: <20250919075823.2557865-1-dario.binacchi@amarulasolutions.com>

[-- Attachment #1: Type: text/plain, Size: 5413 bytes --]

Hi,

On Fri, Sep 19, 2025 at 09:58:09AM +0200, Dario Binacchi wrote:
> Convert EETI touchscreen controller device tree binding to json-schema.
> 
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> ---
> 
> Changes in v5:
> - Move bindings into eeti,exc3000.yaml
> - Remove eeti.yaml
> 
> Changes in v2:
> - Added in v2
> 
>  .../input/touchscreen/eeti,exc3000.yaml       | 41 ++++++++++++++++---
>  .../bindings/input/touchscreen/eeti.txt       | 30 --------------
>  2 files changed, 36 insertions(+), 35 deletions(-)
>  delete mode 100644 Documentation/devicetree/bindings/input/touchscreen/eeti.txt
> 
> diff --git a/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml b/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml
> index 1c7ae05a8c15..13b865d3ee58 100644
> --- a/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml
> +++ b/Documentation/devicetree/bindings/input/touchscreen/eeti,exc3000.yaml
> @@ -9,15 +9,13 @@ title: EETI EXC3000 series touchscreen controller
>  maintainers:
>    - Dmitry Torokhov <dmitry.torokhov@gmail.com>
>  
> -allOf:
> -  - $ref: touchscreen.yaml#
> -
>  properties:
>    compatible:
>      oneOf:
>        - const: eeti,exc3000
>        - const: eeti,exc80h60
>        - const: eeti,exc80h84
> +      - const: eeti,exc3000-i2c

I think this should be

- const: eeti,exc3000-i2c
  deprecated: true

The compatible is obviously not something that should be used
anymore.

>        - items:
>            - enum:
>                - eeti,exc81w32
> @@ -30,18 +28,34 @@ properties:
>      maxItems: 1
>    vdd-supply:
>      description: Power supply regulator for the chip
> +  attn-gpios:
> +    maxItems: 1
> +    description: Phandle to a GPIO to check whether interrupt is still
> +                 latched. This is necessary for platforms that lack
> +                 support for level-triggered IRQs.

  deprecated: true

(see below)

>    touchscreen-size-x: true
>    touchscreen-size-y: true
>    touchscreen-inverted-x: true
>    touchscreen-inverted-y: true
>    touchscreen-swapped-x-y: true
>  
> +allOf:
> +  - $ref: touchscreen.yaml#
> +  - if:
> +      not:
> +        properties:
> +          compatible:
> +            contains:
> +              const: eeti,exc3000-i2c
> +    then:
> +      required:
> +        - touchscreen-size-x
> +        - touchscreen-size-y

And I think it makes sense to add this to disallow using this ugly
hack with the normal compatibles:

else:
  attn-gpios: false

Looking at the only user (pxa300-raumfeld-controller), it supplies
the same GPIO as IRQ and as GPIO, so it is actually a software
limitation. Instead of implementing the software level based IRQ
handling in the gpio driver, it was hacked into the EETI driver.

Looks like this legacy platform is pretty much dead, otherwise I
would have suggested to simply switch it to the new binding/driver.

Greetings,

-- Sebastian

>  required:
>    - compatible
>    - reg
>    - interrupts
> -  - touchscreen-size-x
> -  - touchscreen-size-y
>  
>  additionalProperties: false
>  
> @@ -51,6 +65,7 @@ examples:
>      i2c {
>          #address-cells = <1>;
>          #size-cells = <0>;
> +
>          touchscreen@2a {
>                  compatible = "eeti,exc3000";
>                  reg = <0x2a>;
> @@ -62,3 +77,19 @@ examples:
>                  touchscreen-swapped-x-y;
>          };
>      };
> +
> +  - |
> +    #include <dt-bindings/gpio/gpio.h>
> +    #include "dt-bindings/interrupt-controller/irq.h"
> +    i2c {
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        touchscreen@2a {
> +            compatible = "eeti,exc3000-i2c";
> +            reg = <0x2a>;
> +            interrupt-parent = <&gpio>;
> +            interrupts = <123 IRQ_TYPE_EDGE_RISING>;
> +            attn-gpios = <&gpio 123 GPIO_ACTIVE_HIGH>;
> +        };
> +    };

I would also drop the example, nobody should use this :)

> diff --git a/Documentation/devicetree/bindings/input/touchscreen/eeti.txt b/Documentation/devicetree/bindings/input/touchscreen/eeti.txt
> deleted file mode 100644
> index 32b3712c916e..000000000000
> --- a/Documentation/devicetree/bindings/input/touchscreen/eeti.txt
> +++ /dev/null
> @@ -1,30 +0,0 @@
> -Bindings for EETI touchscreen controller
> -
> -Required properties:
> -- compatible:	should be "eeti,exc3000-i2c"
> -- reg:		I2C address of the chip. Should be set to <0xa>
> -- interrupts:	interrupt to which the chip is connected
> -
> -Optional properties:
> -- attn-gpios:	A handle to a GPIO to check whether interrupt is still
> -		latched. This is necessary for platforms that lack
> -		support for level-triggered IRQs.
> -
> -The following optional properties described in touchscreen.txt are
> -also supported:
> -
> -- touchscreen-inverted-x
> -- touchscreen-inverted-y
> -- touchscreen-swapped-x-y
> -
> -Example:
> -
> -i2c-master {
> -	touchscreen@a {
> -		compatible = "eeti,exc3000-i2c";
> -		reg = <0xa>;
> -		interrupt-parent = <&gpio>;
> -		interrupts = <123 IRQ_TYPE_EDGE_RISING>;
> -		attn-gpios = <&gpio 123 GPIO_ACTIVE_HIGH>;
> -	};
> -};
> -- 
> 2.43.0
> 
> base-commit: 8b789f2b7602a818e7c7488c74414fae21392b63
> branch: drop-touchscreen.txt
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply

* Re: [PATCH v1 2/2] Input: add support for the STM FTS2BA61Y touchscreen
From: kernel test robot @ 2025-09-20 18:36 UTC (permalink / raw)
  To: Eric Gonçalves, Henrik Rydberg, Dmitry Torokhov, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley
  Cc: oe-kbuild-all, Ivaylo Ivanov, devicetree, linux-input,
	linux-kernel
In-Reply-To: <20250920014450.37787-3-ghatto404@gmail.com>

Hi Eric,

kernel test robot noticed the following build errors:

[auto build test ERROR on dtor-input/next]
[also build test ERROR on dtor-input/for-linus robh/for-next linus/master v6.17-rc6 next-20250919]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Eric-Gon-alves/dt-bindings-input-Add-ST-Microelectronics-FTS2BA61Y-touchscreen/20250920-094849
base:   https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
patch link:    https://lore.kernel.org/r/20250920014450.37787-3-ghatto404%40gmail.com
patch subject: [PATCH v1 2/2] Input: add support for the STM FTS2BA61Y touchscreen
config: sh-allmodconfig (https://download.01.org/0day-ci/archive/20250921/202509210247.oVPW8pop-lkp@intel.com/config)
compiler: sh4-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250921/202509210247.oVPW8pop-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202509210247.oVPW8pop-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/input/touchscreen/fts2ba61y.c: In function 'fts2ba61y_wait_for_ready':
>> drivers/input/touchscreen/fts2ba61y.c:250:25: error: implicit declaration of function 'FIELD_GET' [-Wimplicit-function-declaration]
     250 |                 stype = FIELD_GET(FTS2BA61Y_MASK_STYPE, buffer[0]);
         |                         ^~~~~~~~~
   drivers/input/touchscreen/fts2ba61y.c: In function 'fts2ba61y_irq_handler':
>> drivers/input/touchscreen/fts2ba61y.c:442:9: error: implicit declaration of function 'usleep'; did you mean 'fsleep'? [-Wimplicit-function-declaration]
     442 |         usleep(1);
         |         ^~~~~~
         |         fsleep


vim +/FIELD_GET +250 drivers/input/touchscreen/fts2ba61y.c

   239	
   240	static int fts2ba61y_wait_for_ready(struct fts2ba61y_data *ts)
   241	{
   242		u8 buffer[FTS2BA61Y_EVENT_BUFF_SIZE];
   243		u8 cmd = FTS2BA61Y_CMD_READ_EVENT;
   244		u8 status_id, stype;
   245		int ret;
   246	
   247		for (int retries = 5; retries > 0; retries--) {
   248			ret = fts2ba61y_read(ts, &cmd, 1, buffer, FTS2BA61Y_EVENT_BUFF_SIZE);
   249	
 > 250			stype = FIELD_GET(FTS2BA61Y_MASK_STYPE, buffer[0]);
   251			status_id = buffer[1];
   252	
   253			if (stype == FTS2BA61Y_EVENT_STATUSTYPE_INFO &&
   254			    status_id == FTS2BA61Y_INFO_READY_STATUS) {
   255				ret = 0;
   256				break;
   257			} else
   258				ret = -ENODEV;
   259	
   260			msleep(20);
   261		}
   262	
   263		return ret;
   264	}
   265	
   266	static int fts2ba61y_reset(struct fts2ba61y_data *ts)
   267	{
   268		u8 cmd = FTS2BA61Y_CMD_REG_W;
   269		/* the following sequence is undocumented */
   270		u8 reset[FTS2BA61Y_RESET_CMD_SIZE] = { 0x20, 0x00,
   271						       0x00, 0x24, 0x81 };
   272		int ret;
   273	
   274		disable_irq(ts->spi->irq);
   275	
   276		ret = fts2ba61y_write(ts, &cmd, 1, &reset[0], FTS2BA61Y_RESET_CMD_SIZE);
   277		if (ret)
   278			return ret;
   279		msleep(30);
   280	
   281		ret = fts2ba61y_wait_for_ready(ts);
   282		if (ret)
   283			return ret;
   284	
   285		enable_irq(ts->spi->irq);
   286	
   287		return 0;
   288	}
   289	
   290	static int fts2ba61y_set_channels(struct fts2ba61y_data *ts)
   291	{
   292		int ret;
   293		u8 cmd = FTS2BA61Y_CMD_READ_PANEL_INFO;
   294		u8 data[FTS2BA61Y_PANEL_INFO_SIZE];
   295	
   296		ret = fts2ba61y_read(ts, &cmd, 1, data, FTS2BA61Y_PANEL_INFO_SIZE);
   297		if (ret)
   298			return ret;
   299	
   300		ts->max_x = get_unaligned_be16(data);
   301		ts->max_y = get_unaligned_be16(data + 2);
   302	
   303		/* if no tx channels defined, at least keep one */
   304		ts->tx_count = max_t(u8, data[8], 1);
   305	
   306		return 0;
   307	}
   308	
   309	static int fts2ba61y_set_touch_func(struct fts2ba61y_data *ts)
   310	{
   311		u8 cmd = FTS2BA61Y_CMD_TOUCHTYPE;
   312		u16 touchtype = cpu_to_le16(FTS2BA61Y_TOUCHTYPE_DEFAULT);
   313	
   314		return fts2ba61y_write(ts, &cmd, 1, (u8 *)&touchtype, 2);
   315	}
   316	
   317	static int fts2ba61y_hw_init(struct fts2ba61y_data *ts)
   318	{
   319		int ret;
   320	
   321		ret = regulator_bulk_enable(ARRAY_SIZE(ts->regulators),
   322									ts->regulators);
   323		if (ret)
   324			return ret;
   325	
   326		msleep(140);
   327	
   328		ret = fts2ba61y_reset(ts);
   329		if (ret)
   330			return ret;
   331	
   332		ret = fts2ba61y_set_channels(ts);
   333		if (ret)
   334			return ret;
   335	
   336		return fts2ba61y_set_touch_func(ts);
   337	}
   338	
   339	static int fts2ba61y_get_event(struct fts2ba61y_data *ts, u8 *data, int *n_events)
   340	{
   341		int ret;
   342		u8 cmd = FTS2BA61Y_CMD_READ_EVENT;
   343	
   344		ret = fts2ba61y_read(ts, &cmd, 1, data, FTS2BA61Y_EVENT_BUFF_SIZE);
   345		if (ret < 0)
   346			return ret;
   347	
   348		if (!data[0]) {
   349			*n_events = 0;
   350			return 0;
   351		}
   352	
   353		*n_events = FIELD_GET(FTS2BA61Y_MASK_LEFT_EVENTS, data[7]);
   354		if (unlikely(*n_events >= FTS2BA61Y_EVENT_COUNT)) {
   355			cmd = FTS2BA61Y_CMD_CLEAR_EVENTS;
   356			fts2ba61y_write(ts, &cmd, 1, NULL, 0);
   357			*n_events = 0;
   358			return -EINVAL;
   359		}
   360	
   361		if (*n_events > 0) {
   362			ret = fts2ba61y_read(ts, &cmd, 1,
   363					     &data[1 * FTS2BA61Y_EVENT_BUFF_SIZE],
   364					     FTS2BA61Y_EVENT_BUFF_SIZE * (*n_events));
   365			if (ret)
   366				return ret;
   367		}
   368	
   369		return 0;
   370	}
   371	
   372	static void fts2ba61y_report_coordinates(struct fts2ba61y_data *ts,
   373						 u8 *event, u8 tid)
   374	{
   375		u8 major = event[4];
   376		u8 minor = event[5];
   377		u8 z = FIELD_GET(FTS2BA61Y_MASK_Z, event[6]);
   378	
   379		u16 x = (event[1] << 4) |
   380			FIELD_GET(FTS2BA61Y_MASK_X_3_0, event[3]);
   381		u16 y = (event[2] << 4) |
   382			FIELD_GET(FTS2BA61Y_MASK_Y_3_0, event[3]);
   383		u16 ttype = (FIELD_GET(FTS2BA61Y_MASK_TTYPE_3_2, event[6]) << 2) |
   384			    (FIELD_GET(FTS2BA61Y_MASK_TTYPE_1_0, event[7]) << 0);
   385	
   386		if (ttype != FTS2BA61Y_TOUCHTYPE_NORMAL &&
   387		    ttype != FTS2BA61Y_TOUCHTYPE_PALM &&
   388		    ttype != FTS2BA61Y_TOUCHTYPE_WET &&
   389		    ttype != FTS2BA61Y_TOUCHTYPE_GLOVE)
   390			return;
   391	
   392		input_mt_slot(ts->input_dev, tid);
   393		input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
   394		input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
   395		input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
   396		input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, major);
   397		input_report_abs(ts->input_dev, ABS_MT_TOUCH_MINOR, minor);
   398		input_report_abs(ts->input_dev, ABS_MT_PRESSURE, z);
   399	
   400		input_mt_sync_frame(ts->input_dev);
   401		input_sync(ts->input_dev);
   402	}
   403	
   404	static void fts2ba61y_report_release(struct fts2ba61y_data *ts, u8 tid)
   405	{
   406		input_mt_slot(ts->input_dev, tid);
   407		input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
   408	
   409		input_mt_sync_frame(ts->input_dev);
   410		input_sync(ts->input_dev);
   411	}
   412	
   413	static void fts2ba61y_handle_coordinates(struct fts2ba61y_data *ts, u8 *event)
   414	{
   415		u8 t_id = FIELD_GET(FTS2BA61Y_MASK_TID, event[0]);
   416		u8 action = FIELD_GET(FTS2BA61Y_MASK_TCHSTA, event[0]);
   417	
   418		if (t_id > ts->tx_count)
   419			return;
   420	
   421		switch (action) {
   422		case FTS2BA61Y_COORDINATE_ACTION_PRESS:
   423		case FTS2BA61Y_COORDINATE_ACTION_MOVE:
   424			fts2ba61y_report_coordinates(ts, event, t_id);
   425			break;
   426	
   427		case FTS2BA61Y_COORDINATE_ACTION_RELEASE:
   428			fts2ba61y_report_release(ts, t_id);
   429			break;
   430		}
   431	}
   432	
   433	static irqreturn_t fts2ba61y_irq_handler(int irq, void *handle)
   434	{
   435		struct fts2ba61y_data *ts = handle;
   436		u8 buffer[FTS2BA61Y_EVENT_COUNT * FTS2BA61Y_EVENT_BUFF_SIZE];
   437		u8 *event;
   438		u8 event_id;
   439		int n_events = 0;
   440		int ret;
   441	
 > 442		usleep(1);
   443	
   444		ret = fts2ba61y_get_event(ts, buffer, &n_events);
   445		if (ret < 0) {
   446			dev_dbg(&ts->spi->dev, "failed to get event: %d", ret);
   447			return IRQ_HANDLED;
   448		}
   449	
   450		for (int i = 0; i <= n_events; i++) {
   451			event = &buffer[i * FTS2BA61Y_EVENT_BUFF_SIZE];
   452			event_id = FIELD_GET(FTS2BA61Y_MASK_EVENT_ID, event[0]);
   453	
   454			if (event_id == FTS2BA61Y_COORDINATE_EVENT)
   455				fts2ba61y_handle_coordinates(ts, event);
   456		}
   457	
   458		return IRQ_HANDLED;
   459	}
   460	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* Re: [syzbot] [kernel?] INFO: task hung in hidp_session_remove
From: syzbot @ 2025-09-20 14:49 UTC (permalink / raw)
  To: anna-maria, bentiss, chenl311, frederic, jikos, jkosina,
	linux-input, linux-kernel, netdev, syzkaller-bugs, tglx
In-Reply-To: <688aa543.a00a0220.26d0e1.0030.GAE@google.com>

syzbot suspects this issue was fixed by commit:

commit 4051ead99888f101be92c7ce90d2de09aac6fd1c
Author: Li Chen <chenl311@chinatelecom.cn>
Date:   Fri Jun 20 12:02:31 2025 +0000

    HID: rate-limit hid_warn to prevent log flooding

bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=1128a712580000
start commit:   afd8c2c9e2e2 Merge branch 'ipv6-f6i-fib6_siblings-and-rt-f..
git tree:       net
kernel config:  https://syzkaller.appspot.com/x/.config?x=a4bcc0a11b3192be
dashboard link: https://syzkaller.appspot.com/bug?extid=234fdcc5f6633833a35c
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=15f458a2580000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=1796c782580000

If the result looks correct, please mark the issue as fixed by replying with:

#syz fix: HID: rate-limit hid_warn to prevent log flooding

For information about bisection process see: https://goo.gl/tpsmEJ#bisection

^ permalink raw reply

* Re: [PATCH v2 00/10] media: Introduce video device state management
From: Andy Shevchenko @ 2025-09-20 10:48 UTC (permalink / raw)
  To: Jai Luthra
  Cc: Hans Verkuil, Mauro Carvalho Chehab, Sakari Ailus,
	Laurent Pinchart, Tomi Valkeinen, Jacopo Mondi, linux-media,
	Ricardo Ribalda, Laurent Pinchart, Al Viro, Ma Ke, linux-kernel,
	Bartosz Golaszewski, Hans de Goede, Dmitry Torokhov, Nick Dyer,
	Tomasz Figa, Marek Szyprowski, Matt Ranostay, Andy Walls,
	Yong Zhi, Bingbu Cao, Dan Scally, Tianshu Qiu, Martin Tuma,
	Bluecherry Maintainers, Andrey Utkin, Ismael Luceno,
	Ezequiel Garcia, Corentin Labbe, Michael Tretter,
	Pengutronix Kernel Team, Keke Li, Neil Armstrong, Kevin Hilman,
	Jerome Brunet, Martin Blumenstingl, Ming Qian, Zhou Peng,
	Eddie James, Joel Stanley, Andrew Jeffery, Eugen Hristev,
	Nicolas Ferre, Alexandre Belloni, Claudiu Beznea,
	Raspberry Pi Kernel Maintenance, Florian Fainelli,
	Broadcom internal kernel review list, Ray Jui, Scott Branden,
	Philipp Zabel, Nas Chung, Jackson Lee, Devarsh Thakkar, Bin Liu,
	Matthias Brugger, AngeloGioacchino Del Regno, Minghsiu Tsai,
	Houlong Wei, Andrew-CT Chen, Tiffany Lin, Yunfei Dong, Joseph Liu,
	Marvin Lin, Dmitry Osipenko, Thierry Reding, Jonathan Hunter,
	Xavier Roumegue, Mirela Rabulea, Shawn Guo, Sascha Hauer,
	Fabio Estevam, Rui Miguel Silva, Martin Kepplinger,
	Purism Kernel Team, Robert Foss, Todor Tomov,
	Bryan O'Donoghue, Vladimir Zapolskiy, Vikash Garodia,
	Dikshita Agarwal, Abhinav Kumar, Niklas Söderlund,
	Geert Uytterhoeven, Magnus Damm, Fabrizio Castro, Kieran Bingham,
	Nikita Yushchenko, Jacob Chen, Heiko Stuebner, Dafna Hirschfeld,
	Detlev Casanova, Krzysztof Kozlowski, Alim Akhtar,
	Sylwester Nawrocki, Łukasz Stelmach, Andrzej Pietrasiewicz,
	Jacek Anaszewski, Andrzej Hajda, Fabien Dessenne, Hugues Fruchet,
	Jean-Christophe Trotin, Maxime Coquelin, Alexandre Torgue,
	Alain Volmat, Maxime Ripard, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland, Yong Deng, Paul Kocialkowski, Shreeya Patel,
	Lad, Prabhakar, Yemike Abhilash Chandra, Jai Luthra,
	Nicolas Dufresne, Benjamin Gaignard, Michal Simek, Alexey Klimov,
	Eduardo Valentin, Shuah Khan, Daniel Almeida, Michael Krufky,
	Mike Isely, Andy Shevchenko, Greg Kroah-Hartman, Steve Longerbeam,
	Jack Zhu, Changhuang Liang, Sowjanya Komatineni, Luca Ceresoli,
	Parthiban Veerasooran, Christian Gromm, Uwe Kleine-König,
	Ingo Molnar, Thomas Gleixner, Plamen Atanasov, Sean Young,
	Ariel Otilibili, Dr. David Alan Gilbert, Jiasheng Jiang,
	Lad Prabhakar, Tommaso Merciai, Biju Das, Daniel Scally,
	Matthew Majewski, Yunseong Kim, Chen Ni, Fabio Luongo, Mark Brown,
	Yang Yingliang, Ludwig Disterhof, Everest K.C., Stefan Wahren,
	Dave Stevenson, Michael Grzeschik, Akash Kumar, linux-input,
	mjpeg-users, linux-amlogic, linux-arm-kernel, openbmc,
	linux-aspeed, linux-rpi-kernel, linux-mediatek, linux-tegra, imx,
	linux-arm-msm, linux-renesas-soc, linux-rockchip,
	linux-samsung-soc, linux-stm32, linux-sunxi, kernel,
	linux-staging, linux-usb
In-Reply-To: <20250919-vdev-state-v2-0-b2c42426965c@ideasonboard.com>

On Fri, Sep 19, 2025 at 12:57 PM Jai Luthra <jai.luthra@ideasonboard.com> wrote:
>
> Hi,
>
> This patch series introduces state management for video devices.
>
> Currently, V4L2 subdevices have a well-established state management
> system [1] that allows the framework to store the subdevice state
> at a central location.
>
> Video devices however lack this, leading to inconsistent state handling
> across drivers and making it difficult to implement features like
> hardware multiplexing in complex media pipelines [2].
>
> The series is composed of three parts:
>
> - Core Infrastructure (PATCH 1-4)
>         Introduces the basic state structure, try state support,
>         initialization callbacks, and driver helpers
> - Framework Integration (PATCH 5-7)
>         Integrates state passing through the ioctl wrappers and driver
>         implementations
> - Driver Examples (PATCH 8-10)
>         Use the state to store formats in TI J721E CSI2RX and Rockchip
>         RKISP1 drivers
>
> This should also provide a foundation for drivers to extend or subclass
> the state structure with device-specific variables in future.
>
> I have tested capture and format negotiation with the converted drivers
> on SK AM62A (j721e-csi2rx) and Debix Model A (rkisp1).
>
> [1]: https://lore.kernel.org/linux-media/20210610145606.3468235-1-tomi.valkeinen@ideasonboard.com/
> [2]: https://lore.kernel.org/linux-media/20250724-multicontext-mainline-2025-v2-0-c9b316773486@ideasonboard.com/

When you add a Cc list., do it after the '---' (three minus signs)
line, otherwise that huge unneeded noise will become part of the
commit message.


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* Re: [PATCH 00/27 5.10.y] Backport minmax.h updates from v6.17-rc6
From: David Laight @ 2025-09-20 10:21 UTC (permalink / raw)
  To: Christian König
  Cc: linux, jdike, anton.ivanov, dave.hansen, peterz, tglx, x86, hpa,
	tony.luck, qiuxu.zhuo, mchehab, james.morse, rric, harry.wentland,
	sunpeng.li, alexander.deucher, airlied, daniel, evan.quan,
	james.qian.wang, liviu.dudau, mihail.atanassov, brian.starkey,
	maarten.lankhorst, mripard, tzimmermann, robdclark, sean,
	dmitry.torokhov, agk, snitzer, dm-devel, rajur, davem, kuba,
	peppe.cavallaro, alexandre.torgue, joabreu, mcoquelin.stm32,
	malattia, hdegoede, mgross, intel-linux-scu, artur.paszkiewicz,
	jejb, martin.petersen, sakari.ailus, gregkh, dushistov,
	luc.vanoostenryck, rostedt, pmladek, sergey.senozhatsky,
	andriy.shevchenko, linux, akpm, kuznet, yoshfuji, pablo, kadlec,
	jmaloy, ying.xue, willy, sashal, ruanjinjie, David.Laight,
	herve.codina, Jason, bvanassche, keescook, linux-arm-kernel,
	linux-kernel, linux-um, linux-edac, amd-gfx, dri-devel,
	linux-arm-msm, freedreno, linux-hwmon, linux-input, 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, stable, jonnyc
In-Reply-To: <184ce83f-0063-43a0-a1c8-da23c5d03cf7@amd.com>

On Fri, 19 Sep 2025 14:11:37 +0200
Christian König <christian.koenig@amd.com> wrote:

> On 19.09.25 12:17, Eliav Farber wrote:
> > This series includes a total of 27 patches, to align minmax.h of
> > v5.15.y with v6.17-rc6.
> > 
> > The set consists of 24 commits that directly update minmax.h:
> > 1) 92d23c6e9415 ("overflow, tracing: Define the is_signed_type() macro
> >    once")
> > 2) 5efcecd9a3b1 ("minmax: sanity check constant bounds when clamping")
> > 3) 2122e2a4efc2 ("minmax: clamp more efficiently by avoiding extra
> >    comparison")
> > 4) f9bff0e31881 ("minmax: add in_range() macro")
> > 5) c952c748c7a9 ("minmax: Introduce {min,max}_array()")
> > 6) 5e57418a2031 ("minmax: deduplicate __unconst_integer_typeof()")
> > 7) f6e9d38f8eb0 ("minmax: fix header inclusions")
> > 8) d03eba99f5bf ("minmax: allow min()/max()/clamp() if the arguments
> >    have the same signedness.")
> > 9) f4b84b2ff851 ("minmax: fix indentation of __cmp_once() and
> >    __clamp_once()")
> > 10) 4ead534fba42 ("minmax: allow comparisons of 'int' against 'unsigned
> >     char/short'")
> > 11) 867046cc7027 ("minmax: relax check to allow comparison between
> >     unsigned arguments and signed constants")
> > 12) 3a7e02c040b1 ("minmax: avoid overly complicated constant
> >     expressions in VM code")
> > 14) 017fa3e89187 ("minmax: simplify and clarify min_t()/max_t()
> >     implementation")
> > 15) 1a251f52cfdc ("minmax: make generic MIN() and MAX() macros
> >     available everywhere")
> > 18) dc1c8034e31b ("minmax: simplify min()/max()/clamp()
> >     implementation")
> > 19) 22f546873149 ("minmax: improve macro expansion and type
> >     checking")
> > 20) 21b136cc63d2 ("minmax: fix up min3() and max3() too")
> > 21) 71ee9b16251e ("minmax.h: add whitespace around operators and after
> >     commas")
> > 22) 10666e992048 ("minmax.h: update some comments")
> > 23) b280bb27a9f7 ("minmax.h: reduce the #define expansion of min(),
> >     max() and clamp()")
> > 24) a5743f32baec ("minmax.h: use BUILD_BUG_ON_MSG() for the lo < hi
> >     test in clamp()")
> > 25) c3939872ee4a ("minmax.h: move all the clamp() definitions after the
> >     min/max() ones")
> > 26) 495bba17cdf9 ("minmax.h: simplify the variants of clamp()")
> > 27) 2b97aaf74ed5 ("minmax.h: remove some #defines that are only
> >     expanded once")
> > 
> > 2 prerequisite commits that adjust users of MIN and MAX macros (to
> > prevent compilation issues):
> > 13) 4477b39c32fd ("minmax: add a few more MIN_T/MAX_T users")
> > 17) cb04e8b1d2f2 ("minmax: don't use max() in situations that want a C
> >     constant expression")
> > 
> > 1 additional commit introduced to resolve a build failures during the
> > backport:
> > 16) lib: zstd: drop local MIN/MAX macros in favor of generic ones
> > 
> > The primary motivation is to bring in commit (8).
> > In mainline, this change allows min()/max()/clamp() to accept mixed
> > argument types when both share the same signedness.
> > Backported patches to v5.10.y that use such forms trigger compiler
> > warnings, which in turn cause build failures when -Werror is enabled.
> > 
> > Originaly I aligned 5.10.y to 5.15.y, but David Laight commented that I
> > need to pick up the later changes (from Linus) as well.
> > 
> > Andy Shevchenko (2):
> >   minmax: deduplicate __unconst_integer_typeof()
> >   minmax: fix header inclusions
> > 
> > Bart Van Assche (1):
> >   overflow, tracing: Define the is_signed_type() macro once
> > 
> > David Laight (11):
> >   minmax: allow min()/max()/clamp() if the arguments have the same
> >     signedness.
> >   minmax: fix indentation of __cmp_once() and __clamp_once()
> >   minmax: allow comparisons of 'int' against 'unsigned char/short'
> >   minmax: relax check to allow comparison between unsigned arguments and
> >     signed constants
> >   minmax.h: add whitespace around operators and after commas
> >   minmax.h: update some comments
> >   minmax.h: reduce the #define expansion of min(), max() and clamp()
> >   minmax.h: use BUILD_BUG_ON_MSG() for the lo < hi test in clamp()
> >   minmax.h: move all the clamp() definitions after the min/max() ones
> >   minmax.h: simplify the variants of clamp()
> >   minmax.h: remove some #defines that are only expanded once
> > 
> > Eliav Farber (1):
> >   lib: zstd: drop local MIN/MAX macros in favor of generic ones
> > 
> > Herve Codina (1):
> >   minmax: Introduce {min,max}_array()
> > 
> > Jason A. Donenfeld (2):
> >   minmax: sanity check constant bounds when clamping
> >   minmax: clamp more efficiently by avoiding extra comparison
> > 
> > Linus Torvalds (8):
> >   minmax: avoid overly complicated constant expressions in VM code
> >   minmax: add a few more MIN_T/MAX_T users
> >   minmax: simplify and clarify min_t()/max_t() implementation
> >   minmax: make generic MIN() and MAX() macros available everywhere
> >   minmax: don't use max() in situations that want a C constant
> >     expression
> >   minmax: simplify min()/max()/clamp() implementation
> >   minmax: improve macro expansion and type checking
> >   minmax: fix up min3() and max3() too
> > 
> > Matthew Wilcox (Oracle) (1):
> >   minmax: add in_range() macro
> > 
> >  arch/arm/mm/pageattr.c                        |   6 +-
> >  arch/um/drivers/mconsole_user.c               |   2 +
> >  arch/x86/mm/pgtable.c                         |   2 +-  
> 
> >  drivers/edac/sb_edac.c                        |   4 +-
> >  drivers/edac/skx_common.h                     |   1 -
> >  .../drm/amd/display/modules/hdcp/hdcp_ddc.c   |   2 +
> >  .../drm/amd/pm/powerplay/hwmgr/ppevvmath.h    |  14 +-
> >  .../drm/arm/display/include/malidp_utils.h    |   2 +-
> >  .../display/komeda/komeda_pipeline_state.c    |  24 +-
> >  drivers/gpu/drm/drm_color_mgmt.c              |   2 +-
> >  drivers/gpu/drm/msm/adreno/a6xx_gmu.c         |   6 -
> >  drivers/gpu/drm/radeon/evergreen_cs.c         |   2 +
> >  drivers/hwmon/adt7475.c                       |  24 +-
> >  drivers/input/touchscreen/cyttsp4_core.c      |   2 +-
> >  drivers/md/dm-integrity.c                     |   2 +-
> >  drivers/media/dvb-frontends/stv0367_priv.h    |   3 +
> >  .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   |  18 +-
> >  .../net/ethernet/stmicro/stmmac/stmmac_main.c |   2 +-
> >  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 +-  
> 
> I do see the value to backport the infrastructure, but why are driver specific changes backported as well?

They will be about removing local definitions of MIN() and MAX() freeing
them up for simple implementations (usable as constant initialisers) and then
using them in places where the compound statements in min() and max() can't
be used.

Linus did all those changes - so he didn't have to wait for the maintainers
to apply the changes (etc).

	David
 
> 
> I mean the changes are most likely correct but also not valuable in anyway as bug fix.
> 
> Regards,
> Christian.
> 
> >  .../pci/hive_isp_css_include/math_support.h   |   5 -
> >  fs/btrfs/misc.h                               |   2 -
> >  fs/btrfs/tree-checker.c                       |   2 +-
> >  fs/ext2/balloc.c                              |   2 -
> >  fs/ext4/ext4.h                                |   2 -
> >  fs/ufs/util.h                                 |   6 -
> >  include/linux/compiler.h                      |  15 +
> >  include/linux/minmax.h                        | 267 ++++++++++++++----
> >  include/linux/overflow.h                      |   1 -
> >  include/linux/trace_events.h                  |   2 -
> >  kernel/trace/preemptirq_delay_test.c          |   2 -
> >  lib/btree.c                                   |   1 -
> >  lib/decompress_unlzma.c                       |   2 +
> >  lib/logic_pio.c                               |   3 -
> >  lib/vsprintf.c                                |   2 +-
> >  lib/zstd/zstd_internal.h                      |   2 -
> >  mm/zsmalloc.c                                 |   1 -
> >  net/ipv4/proc.c                               |   2 +-
> >  net/ipv6/proc.c                               |   2 +-
> >  net/netfilter/nf_nat_core.c                   |   6 +-
> >  net/tipc/core.h                               |   2 +-
> >  net/tipc/link.c                               |  10 +-
> >  44 files changed, 306 insertions(+), 164 deletions(-)
> >   
> 
> 


^ permalink raw reply

* Re: [PATCH v5 3/6] dt-bindings: touchscreen: add touchscreen-glitch-threshold-ns property
From: Dario Binacchi @ 2025-09-20  9:39 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-kernel, Frank Li, linux-amarula, Conor Dooley, Conor Dooley,
	Dmitry Torokhov, Javier Carrasco, Jeff LaBundy,
	Krzysztof Kozlowski, devicetree, linux-input
In-Reply-To: <20250919204436.GA2176045-robh@kernel.org>

On Fri, Sep 19, 2025 at 10:44 PM Rob Herring <robh@kernel.org> wrote:
>
> On Fri, Sep 19, 2025 at 05:12:42PM +0200, Dario Binacchi wrote:
> > On Fri, Sep 19, 2025 at 4:38 PM Rob Herring <robh@kernel.org> wrote:
> > >
> > > On Thu, Sep 18, 2025 at 10:37:37PM +0200, Dario Binacchi wrote:
> > > > On Thu, Sep 18, 2025 at 10:04 PM Rob Herring <robh@kernel.org> wrote:
> > > > >
> > > > > On Thu, Sep 18, 2025 at 05:52:31PM +0200, Dario Binacchi wrote:
> > > > > > Add support for glitch threshold configuration. A detected signal is valid
> > > > > > only if it lasts longer than the set threshold; otherwise, it is regarded
> > > > > > as a glitch.
> > > > > >
> > > > > > Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> > > > > > Acked-by: Conor Dooley <conor.dooley@microchip.com>
> > > > > >
> > > > > > ---
> > > > > >
> > > > > > Changes in v5:
> > > > > > - Add Acked-by tag of Conor Dooley
> > > > > >
> > > > > > Changes in v2:
> > > > > > - Added in v2.
> > > > > >
> > > > > >  .../devicetree/bindings/input/touchscreen/touchscreen.yaml    | 4 ++++
> > > > > >  1 file changed, 4 insertions(+)
> > > > > >
> > > > > > diff --git a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
> > > > > > index 3e3572aa483a..a60b4d08620d 100644
> > > > > > --- a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
> > > > > > +++ b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
> > > > > > @@ -206,6 +206,10 @@ properties:
> > > > > >
> > > > > >          unevaluatedProperties: false
> > > > > >
> > > > > > +  touchscreen-glitch-threshold-ns:
> > > > > > +    description: Minimum duration in nanoseconds a signal must remain stable
> > > > > > +      to be considered valid.
> > > > >
> > > > > What's wrong with debounce-delay-ms?
> > > >
> > > > Do you mean that I should rename touchscreen-glitch-threshold-ns to
> > > > debounce-delay-ms?
> > >
> > > I mean that's the common property we already have, so use it or explain
> > > why you aren't using it. I suppose the definition is technically a bit
> > > different if it's purely a s/w delay vs. h/w monitoring of the signal
> > > state. I don't think it matters if the interpretation by each driver is
> > > a bit different.
> > >
> > > Maybe msec is not enough resolution for you could be another reason?
> >
> > Yes, this is the main reason. As specified in the following patch:
> >   v5 4/6 dt-bindings: touchscreen: fsl,imx6ul-tsc: support glitch threshold
> >
> > Drivers must convert this value to IPG clock cycles and map
> > it to one of the four discrete thresholds exposed by the
> > TSC_DEBUG_MODE2 register:
> >
> >   0: 8191 IPG cycles
> >   1: 4095 IPG cycles
> >   2: 2047 IPG cycles
> >   3: 1023 IPG cycles
> >
> > In my case, the IPG clock runs at 66 MHz, which corresponds to:
> >
> > 124 µs for 0
> > 62 µs for 1
> > 31 us for 2
> > 15 us for 3
> >
> > So using milliseconds would not fit my use case. A possible trade-off
> > could be to use debounce-delay-us. Would that be acceptable?
>
> I agree it wouldn't map to what the h/w provides, but is what the h/w
> provides actually useful? There's plenty of h/w designed that's not
> useful. 15us is quite short for a glitch. Do you have an actual cases
> where the different values above are needed?

Considering an IPG clock at 66 MHz, currently at reset the deglitch
filter is set to 124 µs,
the driver sets it to 31 µs with a hardcoded value, and in my use case
I need to set it to 62 µs,
as you can see in the patch:
https://lore.kernel.org/all/20250918155240.2536852-6-dario.binacchi@amarulasolutions.com/
and its handling in
https://lore.kernel.org/all/20250918155240.2536852-7-dario.binacchi@amarulasolutions.com/

Another option could be to use a specific binding for the
fsl,imx6ul-tsc controller, as I did in the
earlier versions of the series.

Thanks and regards,
Dario

>
> Rob



-- 

Dario Binacchi

Senior Embedded Linux Developer

dario.binacchi@amarulasolutions.com

__________________________________


Amarula Solutions SRL

Via Le Canevare 30, 31100 Treviso, Veneto, IT

T. +39 042 243 5310
info@amarulasolutions.com

www.amarulasolutions.com

^ permalink raw reply

* [PATCH v1 2/2] Input: add support for the STM FTS2BA61Y touchscreen
From: Eric Gonçalves @ 2025-09-20  1:44 UTC (permalink / raw)
  To: Henrik Rydberg, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: Ivaylo Ivanov, devicetree, linux-input, linux-kernel
In-Reply-To: <20250920014450.37787-1-ghatto404@gmail.com>

The ST-Microelectronics FTS2BA61Y touchscreen is a capacitive multi-touch
controller connected through SPI at 0x0, the touchscreen is typically
used in mobile devices (like the Galaxy S22 series)

Signed-off-by: Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
Signed-off-by: Eric Gonçalves <ghatto404@gmail.com>
---
 drivers/input/touchscreen/Kconfig     |  11 +
 drivers/input/touchscreen/Makefile    |   1 +
 drivers/input/touchscreen/fts2ba61y.c | 588 ++++++++++++++++++++++++++
 3 files changed, 600 insertions(+)
 create mode 100644 drivers/input/touchscreen/fts2ba61y.c

diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 196905162945..1e199191f527 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -370,6 +370,17 @@ config TOUCHSCREEN_EXC3000
 	  To compile this driver as a module, choose M here: the
 	  module will be called exc3000.
 
+config TOUCHSCREEN_FTS2BA61Y
+	tristate "ST-Microelectronics FTS2BA61Y touchscreen"
+	depends on SPI
+	help
+	  Say Y here if you have the ST-Microelectronics FTS2BA61Y touchscreen
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called fts2ba61y.
+
 config TOUCHSCREEN_FUJITSU
 	tristate "Fujitsu serial touchscreen"
 	select SERIO
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 97a025c6a377..408a9fd5bd35 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
 obj-$(CONFIG_TOUCHSCREEN_EGALAX)	+= egalax_ts.o
 obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL)	+= egalax_ts_serial.o
 obj-$(CONFIG_TOUCHSCREEN_EXC3000)	+= exc3000.o
+obj-$(CONFIG_TOUCHSCREEN_FTS2BA61Y)	+= fts2ba61y.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_GOODIX)	+= goodix_ts.o
 obj-$(CONFIG_TOUCHSCREEN_GOODIX_BERLIN_CORE)	+= goodix_berlin_core.o
diff --git a/drivers/input/touchscreen/fts2ba61y.c b/drivers/input/touchscreen/fts2ba61y.c
new file mode 100644
index 000000000000..b3b3abca5404
--- /dev/null
+++ b/drivers/input/touchscreen/fts2ba61y.c
@@ -0,0 +1,588 @@
+// SPDX-License-Identifier: GPL-2.0
+// Based loosely on s6sy761.c
+
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/input/mt.h>
+#include <linux/spi/spi.h>
+#include <linux/input/touchscreen.h>
+#include <linux/unaligned.h>
+#include <linux/regulator/consumer.h>
+
+/* commands */
+#define FTS2BA61Y_CMD_SENSE_ON			0x10
+#define FTS2BA61Y_CMD_SENSE_OFF			0x11
+#define FTS2BA61Y_CMD_READ_PANEL_INFO		0x23
+#define FTS2BA61Y_CMD_READ_FW_VER		0x24
+#define FTS2BA61Y_CMD_TOUCHTYPE			0x30 /* R/W for get/set */
+#define FTS2BA61Y_CMD_CLEAR_EVENTS		0x62
+#define FTS2BA61Y_CMD_READ_EVENT		0x87
+#define FTS2BA61Y_CMD_CUSTOM_W			0xC0
+#define FTS2BA61Y_CMD_CUSTOM_R			0xD1
+#define FTS2BA61Y_CMD_REG_W			0xFA
+#define FTS2BA61Y_CMD_REG_R			0xFB
+
+/* touch type masks */
+#define FTS2BA61Y_MASK_TOUCH			BIT(0)
+#define FTS2BA61Y_MASK_HOVER			BIT(1)
+#define FTS2BA61Y_MASK_COVER			BIT(2)
+#define FTS2BA61Y_MASK_GLOVE			BIT(3)
+#define FTS2BA61Y_MASK_STYLUS			BIT(4)
+#define FTS2BA61Y_MASK_PALM			BIT(5)
+#define FTS2BA61Y_MASK_WET			BIT(6)
+#define FTS2BA61Y_TOUCHTYPE_DEFAULT		(FTS2BA61Y_MASK_TOUCH | \
+						 FTS2BA61Y_MASK_PALM | \
+						 FTS2BA61Y_MASK_WET)
+
+/* event status masks */
+#define FTS2BA61Y_MASK_STYPE			GENMASK(5, 2)
+#define FTS2BA61Y_MASK_EVENT_ID			GENMASK(1, 0)
+
+/* event coordinate masks */
+#define FTS2BA61Y_MASK_TCHSTA			GENMASK(7, 6)
+#define FTS2BA61Y_MASK_TID			GENMASK(5, 2)
+#define FTS2BA61Y_MASK_X_3_0			GENMASK(7, 4)
+#define FTS2BA61Y_MASK_Y_3_0			GENMASK(3, 0)
+#define FTS2BA61Y_MASK_Z			GENMASK(5, 0)
+#define FTS2BA61Y_MASK_TTYPE_3_2		GENMASK(7, 6)
+#define FTS2BA61Y_MASK_TTYPE_1_0		GENMASK(1, 0)
+#define FTS2BA61Y_MASK_LEFT_EVENTS		GENMASK(4, 0)
+
+/* event error status */
+#define FTS2BA61Y_EVENT_STATUSTYPE_INFO		0x2
+
+/* information report */
+#define FTS2BA61Y_INFO_READY_STATUS		0x0
+
+/* event status */
+#define FTS2BA61Y_COORDINATE_EVENT		0x0
+
+/* touch types */
+#define FTS2BA61Y_TOUCHTYPE_NORMAL		0x0
+#define FTS2BA61Y_TOUCHTYPE_HOVER		0x1
+#define FTS2BA61Y_TOUCHTYPE_FLIPCOVER		0x2
+#define FTS2BA61Y_TOUCHTYPE_GLOVE		0x3
+#define FTS2BA61Y_TOUCHTYPE_STYLUS		0x4
+#define FTS2BA61Y_TOUCHTYPE_PALM		0x5
+#define FTS2BA61Y_TOUCHTYPE_WET			0x6
+#define FTS2BA61Y_TOUCHTYPE_PROXIMITY		0x7
+#define FTS2BA61Y_TOUCHTYPE_JIG			0x8
+
+#define FTS2BA61Y_COORDINATE_ACTION_NONE	0x0
+#define FTS2BA61Y_COORDINATE_ACTION_PRESS	0x1
+#define FTS2BA61Y_COORDINATE_ACTION_MOVE	0x2
+#define FTS2BA61Y_COORDINATE_ACTION_RELEASE	0x3
+
+#define FTS2BA61Y_DEV_NAME			"fts2ba61y"
+#define FTS2BA61Y_EVENT_BUFF_SIZE		16
+#define FTS2BA61Y_PANEL_INFO_SIZE		11
+#define FTS2BA61Y_RESET_CMD_SIZE		5
+#define FTS2BA61Y_EVENT_COUNT			31
+#define MAX_TRANSFER_SIZE			256
+
+enum fts2ba61y_regulators {
+	FTS2BA61Y_REGULATOR_VDD,
+	FTS2BA61Y_REGULATOR_AVDD,
+};
+
+struct fts2ba61y_data {
+	struct spi_device *spi;
+	struct regulator_bulk_data regulators[2];
+	struct input_dev *input_dev;
+	struct mutex mutex;
+	struct touchscreen_properties prop;
+
+	u8 tx_count;
+
+	unsigned int max_x;
+	unsigned int max_y;
+};
+
+static int fts2ba61y_write(struct fts2ba61y_data *ts,
+			   u8 *reg, int cmd_len, u8 *data, int data_len)
+{
+	struct spi_message msg;
+	struct spi_transfer xfers;
+	char *tx_buf;
+	int len;
+	int ret;
+
+	tx_buf = kzalloc(cmd_len + data_len + 1, GFP_KERNEL);
+	if (!tx_buf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memset(&xfers, 0, sizeof(xfers));
+	spi_message_init(&msg);
+
+	memcpy(&tx_buf[0], reg, cmd_len);
+	if (data_len && data)
+		memcpy(&tx_buf[cmd_len], data, data_len);
+
+	len = cmd_len + data_len;
+
+	/* custom write cmd */
+	if (reg[0] != FTS2BA61Y_CMD_REG_W &&
+	    reg[0] != FTS2BA61Y_CMD_REG_R) {
+		memmove(tx_buf + 1, tx_buf, len);
+		tx_buf[0] = FTS2BA61Y_CMD_CUSTOM_W;
+		len++;
+	}
+
+	xfers.len = len;
+	xfers.tx_buf = tx_buf;
+
+	spi_message_add_tail(&xfers, &msg);
+
+	mutex_lock(&ts->mutex);
+	ret = spi_sync(ts->spi, &msg);
+	if (ret)
+		dev_err(&ts->spi->dev, "spi transfer error, %d", ret);
+	mutex_unlock(&ts->mutex);
+
+out:
+	kfree(tx_buf);
+	return ret;
+}
+
+static int fts2ba61y_spi_raw_read(struct fts2ba61y_data *ts,
+				  u8 *tx_buf, u8 *rx_buf, int len)
+{
+	struct spi_message msg;
+	struct spi_transfer xfer;
+	int ret;
+
+	memset(&xfer, 0, sizeof(xfer));
+	spi_message_init(&msg);
+
+	xfer.len = len;
+	xfer.tx_buf = tx_buf;
+	xfer.rx_buf = rx_buf;
+	spi_message_add_tail(&xfer, &msg);
+
+	mutex_lock(&ts->mutex);
+	ret = spi_sync(ts->spi, &msg);
+	if (ret)
+		dev_err(&ts->spi->dev, "spi transfer error, %d", ret);
+	mutex_unlock(&ts->mutex);
+
+	return ret;
+}
+
+/*
+ * higher-level wrapper that prepares the buffers for a read.
+ */
+static int fts2ba61y_read(struct fts2ba61y_data *ts,
+			  u8 reg[], int tx_len, u8 buf[], int rx_len)
+{
+	char *tx_buf, *rx_buf;
+	int ret, mem_len;
+	u16 reg_val;
+
+	if (tx_len > 3)
+		mem_len = rx_len + 1 + tx_len;
+	else
+		mem_len = rx_len + 4;
+
+	tx_buf = kzalloc(mem_len, GFP_KERNEL);
+	rx_buf = kzalloc(mem_len, GFP_KERNEL);
+	if (!tx_buf || !rx_buf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	switch (reg[0]) {
+	case FTS2BA61Y_CMD_READ_EVENT:
+	case FTS2BA61Y_CMD_REG_W:
+	case FTS2BA61Y_CMD_REG_R:
+		memcpy(tx_buf, reg, tx_len);
+		break;
+
+	default:
+		tx_buf[0] = FTS2BA61Y_CMD_CUSTOM_R;
+
+		if (tx_len == 1)
+			reg_val = 0;
+		else if (tx_len == 2)
+			reg_val = reg[0];
+		else if (tx_len == 3)
+			reg_val = reg[0] | (reg[1] << 8);
+		else {
+			ret = -EINVAL;
+			goto out;
+		}
+
+		tx_len = 3;
+		put_unaligned_be16(reg_val, &tx_buf[1]);
+
+		ret = fts2ba61y_write(ts, reg, 1, NULL, 0);
+		if (ret < 0)
+			goto out;
+		break;
+	}
+
+	ret = fts2ba61y_spi_raw_read(ts, tx_buf, rx_buf, rx_len + 1 + tx_len);
+	if (ret < 0)
+		goto out;
+
+	memcpy(buf, &rx_buf[1 + tx_len], rx_len);
+
+out:
+	kfree(tx_buf);
+	kfree(rx_buf);
+	return ret;
+}
+
+static int fts2ba61y_wait_for_ready(struct fts2ba61y_data *ts)
+{
+	u8 buffer[FTS2BA61Y_EVENT_BUFF_SIZE];
+	u8 cmd = FTS2BA61Y_CMD_READ_EVENT;
+	u8 status_id, stype;
+	int ret;
+
+	for (int retries = 5; retries > 0; retries--) {
+		ret = fts2ba61y_read(ts, &cmd, 1, buffer, FTS2BA61Y_EVENT_BUFF_SIZE);
+
+		stype = FIELD_GET(FTS2BA61Y_MASK_STYPE, buffer[0]);
+		status_id = buffer[1];
+
+		if (stype == FTS2BA61Y_EVENT_STATUSTYPE_INFO &&
+		    status_id == FTS2BA61Y_INFO_READY_STATUS) {
+			ret = 0;
+			break;
+		} else
+			ret = -ENODEV;
+
+		msleep(20);
+	}
+
+	return ret;
+}
+
+static int fts2ba61y_reset(struct fts2ba61y_data *ts)
+{
+	u8 cmd = FTS2BA61Y_CMD_REG_W;
+	/* the following sequence is undocumented */
+	u8 reset[FTS2BA61Y_RESET_CMD_SIZE] = { 0x20, 0x00,
+					       0x00, 0x24, 0x81 };
+	int ret;
+
+	disable_irq(ts->spi->irq);
+
+	ret = fts2ba61y_write(ts, &cmd, 1, &reset[0], FTS2BA61Y_RESET_CMD_SIZE);
+	if (ret)
+		return ret;
+	msleep(30);
+
+	ret = fts2ba61y_wait_for_ready(ts);
+	if (ret)
+		return ret;
+
+	enable_irq(ts->spi->irq);
+
+	return 0;
+}
+
+static int fts2ba61y_set_channels(struct fts2ba61y_data *ts)
+{
+	int ret;
+	u8 cmd = FTS2BA61Y_CMD_READ_PANEL_INFO;
+	u8 data[FTS2BA61Y_PANEL_INFO_SIZE];
+
+	ret = fts2ba61y_read(ts, &cmd, 1, data, FTS2BA61Y_PANEL_INFO_SIZE);
+	if (ret)
+		return ret;
+
+	ts->max_x = get_unaligned_be16(data);
+	ts->max_y = get_unaligned_be16(data + 2);
+
+	/* if no tx channels defined, at least keep one */
+	ts->tx_count = max_t(u8, data[8], 1);
+
+	return 0;
+}
+
+static int fts2ba61y_set_touch_func(struct fts2ba61y_data *ts)
+{
+	u8 cmd = FTS2BA61Y_CMD_TOUCHTYPE;
+	u16 touchtype = cpu_to_le16(FTS2BA61Y_TOUCHTYPE_DEFAULT);
+
+	return fts2ba61y_write(ts, &cmd, 1, (u8 *)&touchtype, 2);
+}
+
+static int fts2ba61y_hw_init(struct fts2ba61y_data *ts)
+{
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(ts->regulators),
+								ts->regulators);
+	if (ret)
+		return ret;
+
+	msleep(140);
+
+	ret = fts2ba61y_reset(ts);
+	if (ret)
+		return ret;
+
+	ret = fts2ba61y_set_channels(ts);
+	if (ret)
+		return ret;
+
+	return fts2ba61y_set_touch_func(ts);
+}
+
+static int fts2ba61y_get_event(struct fts2ba61y_data *ts, u8 *data, int *n_events)
+{
+	int ret;
+	u8 cmd = FTS2BA61Y_CMD_READ_EVENT;
+
+	ret = fts2ba61y_read(ts, &cmd, 1, data, FTS2BA61Y_EVENT_BUFF_SIZE);
+	if (ret < 0)
+		return ret;
+
+	if (!data[0]) {
+		*n_events = 0;
+		return 0;
+	}
+
+	*n_events = FIELD_GET(FTS2BA61Y_MASK_LEFT_EVENTS, data[7]);
+	if (unlikely(*n_events >= FTS2BA61Y_EVENT_COUNT)) {
+		cmd = FTS2BA61Y_CMD_CLEAR_EVENTS;
+		fts2ba61y_write(ts, &cmd, 1, NULL, 0);
+		*n_events = 0;
+		return -EINVAL;
+	}
+
+	if (*n_events > 0) {
+		ret = fts2ba61y_read(ts, &cmd, 1,
+				     &data[1 * FTS2BA61Y_EVENT_BUFF_SIZE],
+				     FTS2BA61Y_EVENT_BUFF_SIZE * (*n_events));
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void fts2ba61y_report_coordinates(struct fts2ba61y_data *ts,
+					 u8 *event, u8 tid)
+{
+	u8 major = event[4];
+	u8 minor = event[5];
+	u8 z = FIELD_GET(FTS2BA61Y_MASK_Z, event[6]);
+
+	u16 x = (event[1] << 4) |
+		FIELD_GET(FTS2BA61Y_MASK_X_3_0, event[3]);
+	u16 y = (event[2] << 4) |
+		FIELD_GET(FTS2BA61Y_MASK_Y_3_0, event[3]);
+	u16 ttype = (FIELD_GET(FTS2BA61Y_MASK_TTYPE_3_2, event[6]) << 2) |
+		    (FIELD_GET(FTS2BA61Y_MASK_TTYPE_1_0, event[7]) << 0);
+
+	if (ttype != FTS2BA61Y_TOUCHTYPE_NORMAL &&
+	    ttype != FTS2BA61Y_TOUCHTYPE_PALM &&
+	    ttype != FTS2BA61Y_TOUCHTYPE_WET &&
+	    ttype != FTS2BA61Y_TOUCHTYPE_GLOVE)
+		return;
+
+	input_mt_slot(ts->input_dev, tid);
+	input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
+	input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
+	input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
+	input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, major);
+	input_report_abs(ts->input_dev, ABS_MT_TOUCH_MINOR, minor);
+	input_report_abs(ts->input_dev, ABS_MT_PRESSURE, z);
+
+	input_mt_sync_frame(ts->input_dev);
+	input_sync(ts->input_dev);
+}
+
+static void fts2ba61y_report_release(struct fts2ba61y_data *ts, u8 tid)
+{
+	input_mt_slot(ts->input_dev, tid);
+	input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
+
+	input_mt_sync_frame(ts->input_dev);
+	input_sync(ts->input_dev);
+}
+
+static void fts2ba61y_handle_coordinates(struct fts2ba61y_data *ts, u8 *event)
+{
+	u8 t_id = FIELD_GET(FTS2BA61Y_MASK_TID, event[0]);
+	u8 action = FIELD_GET(FTS2BA61Y_MASK_TCHSTA, event[0]);
+
+	if (t_id > ts->tx_count)
+		return;
+
+	switch (action) {
+	case FTS2BA61Y_COORDINATE_ACTION_PRESS:
+	case FTS2BA61Y_COORDINATE_ACTION_MOVE:
+		fts2ba61y_report_coordinates(ts, event, t_id);
+		break;
+
+	case FTS2BA61Y_COORDINATE_ACTION_RELEASE:
+		fts2ba61y_report_release(ts, t_id);
+		break;
+	}
+}
+
+static irqreturn_t fts2ba61y_irq_handler(int irq, void *handle)
+{
+	struct fts2ba61y_data *ts = handle;
+	u8 buffer[FTS2BA61Y_EVENT_COUNT * FTS2BA61Y_EVENT_BUFF_SIZE];
+	u8 *event;
+	u8 event_id;
+	int n_events = 0;
+	int ret;
+
+	usleep(1);
+
+	ret = fts2ba61y_get_event(ts, buffer, &n_events);
+	if (ret < 0) {
+		dev_dbg(&ts->spi->dev, "failed to get event: %d", ret);
+		return IRQ_HANDLED;
+	}
+
+	for (int i = 0; i <= n_events; i++) {
+		event = &buffer[i * FTS2BA61Y_EVENT_BUFF_SIZE];
+		event_id = FIELD_GET(FTS2BA61Y_MASK_EVENT_ID, event[0]);
+
+		if (event_id == FTS2BA61Y_COORDINATE_EVENT)
+			fts2ba61y_handle_coordinates(ts, event);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int fts2ba61y_input_open(struct input_dev *dev)
+{
+	struct fts2ba61y_data *ts = input_get_drvdata(dev);
+	u8 cmd = FTS2BA61Y_CMD_SENSE_ON;
+
+	return fts2ba61y_write(ts, &cmd, 1, NULL, 0);
+}
+
+static void fts2ba61y_input_close(struct input_dev *dev)
+{
+	struct fts2ba61y_data *ts = input_get_drvdata(dev);
+	int ret;
+	u8 cmd = FTS2BA61Y_CMD_SENSE_OFF;
+
+	ret = fts2ba61y_write(ts, &cmd, 1, NULL, 0);
+	if (ret)
+		dev_err(&ts->spi->dev, "failed to turn off sensing\n");
+}
+
+static void fts2ba61y_power_off(void *data)
+{
+	struct fts2ba61y_data *ts = data;
+
+	disable_irq(ts->spi->irq);
+	regulator_bulk_disable(ARRAY_SIZE(ts->regulators),
+						   ts->regulators);
+}
+
+static int fts2ba61y_probe(struct spi_device *spi) {
+	struct fts2ba61y_data *ts;
+	struct input_dev *input_dev;
+	int error;
+
+	ts = devm_kzalloc(&spi->dev, sizeof(*ts), GFP_KERNEL);
+	if (!ts)
+		return -ENOMEM;
+
+	ts->spi = spi;
+	mutex_init(&ts->mutex);
+
+	spi->mode = SPI_MODE_0;
+	spi->bits_per_word = 8;
+
+	error = spi_setup(spi);
+	if (error)
+		return error;
+
+	ts->regulators[FTS2BA61Y_REGULATOR_VDD].supply = "vdd";
+	ts->regulators[FTS2BA61Y_REGULATOR_AVDD].supply = "avdd";
+	error = devm_regulator_bulk_get(&spi->dev,
+									ARRAY_SIZE(ts->regulators),
+									ts->regulators);
+	if (error)
+		return error;
+
+	error = fts2ba61y_hw_init(ts);
+	if (error)
+		return error;
+
+	error = devm_add_action_or_reset(&ts->spi->dev, fts2ba61y_power_off, ts);
+	if (error)
+		return error;
+
+	input_dev = devm_input_allocate_device(&spi->dev);
+	if (!input_dev)
+		return -ENOMEM;
+
+	ts->input_dev = input_dev;
+
+	input_dev->name = FTS2BA61Y_DEV_NAME;
+	input_dev->id.bustype = BUS_SPI;
+	input_dev->open = fts2ba61y_input_open;
+	input_dev->close = fts2ba61y_input_close;
+
+	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ts->max_x, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ts->max_y, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 255, 0, 0);
+
+	touchscreen_parse_properties(input_dev, true, &ts->prop);
+
+	spi_set_drvdata(spi, ts);
+	input_set_drvdata(input_dev, ts);
+
+	error = input_mt_init_slots(input_dev, ts->tx_count, INPUT_MT_DIRECT);
+	if (error)
+		return error;
+
+	error = input_register_device(input_dev);
+	if (error)
+		return error;
+
+	error = devm_request_threaded_irq(&spi->dev, spi->irq, NULL,
+					  fts2ba61y_irq_handler,
+					  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+					  "fts2ba61y_irq", ts);
+	return error;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id spi_touchscreen_dt_ids[] = {
+	{ .compatible = "st,fts2ba61y" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, spi_touchscreen_dt_ids);
+#endif
+
+static const struct spi_device_id fts2ba61y_spi_ids[] = {
+	{ "fts2ba61y" },
+	{ },
+};
+MODULE_DEVICE_TABLE(spi, fts2ba61y_spi_ids);
+
+static struct spi_driver spi_touchscreen_driver = {
+	.driver = {
+		.name = FTS2BA61Y_DEV_NAME,
+		.of_match_table = of_match_ptr(spi_touchscreen_dt_ids),
+	},
+	.probe = fts2ba61y_probe,
+	.id_table = fts2ba61y_spi_ids,
+};
+
+module_spi_driver(spi_touchscreen_driver);
+
+MODULE_AUTHOR("Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>");
+MODULE_DESCRIPTION("ST-Microelectronics FTS2BA61Y Touch Screen");
+MODULE_LICENSE("GPL");
-- 
2.51.0


^ permalink raw reply related

* [PATCH v1 1/2] dt-bindings: input: Add ST-Microelectronics FTS2BA61Y touchscreen
From: Eric Gonçalves @ 2025-09-20  1:44 UTC (permalink / raw)
  To: Henrik Rydberg, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: Ivaylo Ivanov, devicetree, linux-input, linux-kernel
In-Reply-To: <20250920014450.37787-1-ghatto404@gmail.com>

Add the bindings for ST-Microelectronics FTS2BA61Y capacitive touchscreen.

Signed-off-by: Eric Gonçalves <ghatto404@gmail.com>
---
 .../input/touchscreen/st,fts2ba61y.yaml       | 52 +++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100755 Documentation/devicetree/bindings/input/touchscreen/st,fts2ba61y.yaml

diff --git a/Documentation/devicetree/bindings/input/touchscreen/st,fts2ba61y.yaml b/Documentation/devicetree/bindings/input/touchscreen/st,fts2ba61y.yaml
new file mode 100644
index 000000000000..d5565b5360fc
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/st,fts2ba61y.yaml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/st,fts2ba61y.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ST-Microelectronics FTS2BA61Y touchscreen controller
+
+maintainers:
+  - Ivaylo Ivanov <ivo.ivanov.ivanov1@gmail.com>
+
+allOf:
+  - $ref: touchscreen.yaml#
+
+properties:
+  compatible:
+    const: st,fts2ba61y
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  avdd-supply: true
+  vdd-supply: true
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - avdd-supply
+  - vdd-supply
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    spi {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        touchscreen@0 {
+            compatible = "st,fts2ba61y";
+            reg = <0x0>;
+            interrupt-parent = <&gpa2>;
+            interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+            avdd-supply = <&ldo17_reg>;
+            vdd-supply = <&ldo28_reg>;
+        };
+    };
-- 
2.51.0


^ permalink raw reply related

* [PATCH v1 0/2] Input: add fts2ba61y touchscreen driver
From: Eric Gonçalves @ 2025-09-20  1:44 UTC (permalink / raw)
  To: Henrik Rydberg, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley
  Cc: Ivaylo Ivanov, devicetree, linux-input, linux-kernel

This patchset adds support for the ST-Microelectronics FTS2BA61Y,
a capacitive multi-touch touchscreen controller. this touchscreen
is used in many mobile devices, like ones from the Galaxy S22 series
and the Z Fold 5. Ivaylo Ivanov wrote the driver originally,
and I'm upstreaming it on his behalf.

Shortly after this patchset, I'll be sending another one that
enables touchscreen on the Galaxy S22 (r0q) board.

Thanks!

Changes from RFC->v1:
- move unevaluatedProperties to after the required: field
- set Ivaylo as the author of driver commit

Eric Gonçalves (1):
  dt-bindings: input: Add ST-Microelectronics FTS2BA61Y touchscreen

Ivaylo Ivanov (1):
  Input: add support for the STM FTS2BA61Y touchscreen

 .../input/touchscreen/st,fts2ba61y.yaml       |  52 ++
 drivers/input/touchscreen/Kconfig             |  11 +
 drivers/input/touchscreen/Makefile            |   1 +
 drivers/input/touchscreen/fts2ba61y.c         | 588 ++++++++++++++++++
 4 files changed, 652 insertions(+)
 create mode 100755 Documentation/devicetree/bindings/input/touchscreen/st,fts2ba61y.yaml
 create mode 100644 drivers/input/touchscreen/fts2ba61y.c

-- 
2.51.0


^ permalink raw reply

* Re: [PATCH v6] HID: lg-g15 - Add support for Logitech G13.
From: Hans de Goede @ 2025-09-19 21:09 UTC (permalink / raw)
  To: Leo L. Schwab
  Cc: Kate Hsuan, Jiri Kosina, Benjamin Tissoires, linux-input,
	linux-kernel
In-Reply-To: <20250917230550.1160621-1-ewhac@ewhac.org>

Hi,

On 18-Sep-25 1:05 AM, Leo L. Schwab wrote:
> The Logitech G13 is a gaming keypad with general-purpose macro keys,
> four LED-backlit macro preset keys, five "menu" keys, backlight toggle
> key, an analog thumbstick, RGB LED backlight, and a monochrome LCD
> display.
> 
> Support input event generation for all keys and the thumbstick, and
> expose all LEDs.
> 
> Signed-off-by: Leo L. Schwab <ewhac@ewhac.org>
> Reviewed-by: Hans de Goede <hansg@kernel.org>
> Tested-by: Kate Hsuan <hpa@redhat.com>
> ---
> Changes in v6:
>   - Alter interaction between `brightness` and `brightness_hw_changed`
>     for the backlight as advised by Hans de Goede <hansg@kernel.org>.
>   - On probe, query device for current state of HW backlight toggle;
>     track in `backlight_disabled` and update sysfs.
>   - Ensure non-backlight LED brightnesses report either 0 or 1.

Thanks, this latest version looks good to me:

Reviewed-by: Hans de Goede <hansg@kernel.org>

note this is already there, just making clear that all me
remarks are resolved now and this is ready to merge.

Regards,

Hans


> Changes in v5:
>   - None; resend v4 due to bounced email submission.
> Changes in v4:
>   - Minor changes recommended by Hans de Goede <hansg@kernel.org>.
> Changes in v3:
>   - Re-revise commit message.
>   - Conditionally compile the section depending on
>     CONFIG_LEDS_BRIGHTNESS_HW_CHANGED correctly this time.
>   - Use led-class-multicolor facilities for the RGB backlight.
>   - Changes recommended by Kate Hsuan <hpa@redhat.com>:
>     - Use guard(mutex) construct.
>     - Fix numerous style nits.
> Changes in v2:
>   - Add `#ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED` bracket around new
>     code segment dependent on that feature (fixes test robot build
>     error).
>   - Use `guard(mutex)` construct in new code (existing code left
>     unmodified).
>   - Commit message revised.
> 
>  drivers/hid/hid-ids.h    |   1 +
>  drivers/hid/hid-lg-g15.c | 448 +++++++++++++++++++++++++++++++++++++--
>  2 files changed, 433 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 33cc5820f2be..7ed1e402b80a 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -870,6 +870,7 @@
>  #define USB_DEVICE_ID_LOGITECH_DUAL_ACTION	0xc216
>  #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2	0xc218
>  #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2	0xc219
> +#define USB_DEVICE_ID_LOGITECH_G13		0xc21c
>  #define USB_DEVICE_ID_LOGITECH_G15_LCD		0xc222
>  #define USB_DEVICE_ID_LOGITECH_G11		0xc225
>  #define USB_DEVICE_ID_LOGITECH_G15_V2_LCD	0xc227
> diff --git a/drivers/hid/hid-lg-g15.c b/drivers/hid/hid-lg-g15.c
> index f8605656257b..7b8df2d5b57f 100644
> --- a/drivers/hid/hid-lg-g15.c
> +++ b/drivers/hid/hid-lg-g15.c
> @@ -26,7 +26,21 @@
>  #define LG_G510_FEATURE_BACKLIGHT_RGB	0x05
>  #define LG_G510_FEATURE_POWER_ON_RGB	0x06
>  
> +#define LG_G13_INPUT_REPORT		0x01
> +#define LG_G13_FEATURE_M_KEYS_LEDS	0x05
> +#define LG_G13_FEATURE_BACKLIGHT_RGB	0x07
> +#define LG_G13_BACKLIGHT_HW_ON_BIT	23
> +
> +/**
> + * g13_input_report.keybits[] is not 32-bit aligned, so we can't use the bitops macros.
> + *
> + * @ary: Pointer to array of u8s
> + * @b: Bit index into ary, LSB first.  Not range checked.
> + */
> +#define TEST_BIT(ary, b)	((1 << ((b) & 7)) & (ary)[(b) >> 3])
> +
>  enum lg_g15_model {
> +	LG_G13,
>  	LG_G15,
>  	LG_G15_V2,
>  	LG_G510,
> @@ -45,6 +59,12 @@ enum lg_g15_led_type {
>  	LG_G15_LED_MAX
>  };
>  
> +struct g13_input_report {
> +	u8 report_id;	/* Report ID is always set to 1. */
> +	u8 joy_x, joy_y;
> +	u8 keybits[5];
> +};
> +
>  struct lg_g15_led {
>  	union {
>  		struct led_classdev cdev;
> @@ -63,12 +83,188 @@ struct lg_g15_data {
>  	struct mutex mutex;
>  	struct work_struct work;
>  	struct input_dev *input;
> +	struct input_dev *input_js; /* Separate joystick device for G13. */
>  	struct hid_device *hdev;
>  	enum lg_g15_model model;
>  	struct lg_g15_led leds[LG_G15_LED_MAX];
>  	bool game_mode_enabled;
> +	bool backlight_disabled;	/* true == HW backlight toggled *OFF* */
>  };
>  
> +/********* G13 LED functions ***********/
> +/*
> + * G13 retains no state across power cycles, and always powers up with the backlight on,
> + * color #5AFF6E, all macro key LEDs off.
> + */
> +static int lg_g13_get_leds_state(struct lg_g15_data *g15)
> +{
> +	u8 * const tbuf = g15->transfer_buf;
> +	int ret, high;
> +
> +	/* RGB backlight. */
> +	ret = hid_hw_raw_request(g15->hdev, LG_G13_FEATURE_BACKLIGHT_RGB,
> +				 tbuf, 5,
> +				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
> +	if (ret != 5) {
> +		hid_err(g15->hdev, "Error getting backlight brightness: %d\n", ret);
> +		return (ret < 0) ? ret : -EIO;
> +	}
> +
> +	/* Normalize RGB intensities against the highest component. */
> +	high = max3(tbuf[1], tbuf[2], tbuf[3]);
> +	if (high) {
> +		g15->leds[LG_G15_KBD_BRIGHTNESS].red =
> +			DIV_ROUND_CLOSEST(tbuf[1] * 255, high);
> +		g15->leds[LG_G15_KBD_BRIGHTNESS].green =
> +			DIV_ROUND_CLOSEST(tbuf[2] * 255, high);
> +		g15->leds[LG_G15_KBD_BRIGHTNESS].blue =
> +			DIV_ROUND_CLOSEST(tbuf[3] * 255, high);
> +		g15->leds[LG_G15_KBD_BRIGHTNESS].brightness = high;
> +	} else {
> +		g15->leds[LG_G15_KBD_BRIGHTNESS].red        = 255;
> +		g15->leds[LG_G15_KBD_BRIGHTNESS].green      = 255;
> +		g15->leds[LG_G15_KBD_BRIGHTNESS].blue       = 255;
> +		g15->leds[LG_G15_KBD_BRIGHTNESS].brightness = 0;
> +	}
> +
> +	/* Macro LEDs. */
> +	ret = hid_hw_raw_request(g15->hdev, LG_G13_FEATURE_M_KEYS_LEDS,
> +				 tbuf, 5,
> +				 HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
> +	if (ret != 5) {
> +		hid_err(g15->hdev, "Error getting macro LED brightness: %d\n", ret);
> +		return (ret < 0) ? ret : -EIO;
> +	}
> +
> +	for (int i = LG_G15_MACRO_PRESET1; i < LG_G15_LED_MAX; ++i)
> +		g15->leds[i].brightness = !!(tbuf[1] & (1 << (i - LG_G15_MACRO_PRESET1)));
> +
> +	/*
> +	 * Bit 23 of g13_input_report.keybits[] contains the backlight's
> +	 * current HW toggle state.  Retrieve it from the device.
> +	 */
> +	ret = hid_hw_raw_request(g15->hdev, LG_G13_INPUT_REPORT,
> +				 tbuf, sizeof(struct g13_input_report),
> +				 HID_INPUT_REPORT, HID_REQ_GET_REPORT);
> +	if (ret != sizeof(struct g13_input_report)) {
> +		hid_err(g15->hdev, "Error getting backlight on/off state: %d\n", ret);
> +		return (ret < 0) ? ret : -EIO;
> +	}
> +	g15->backlight_disabled =
> +		!TEST_BIT(((struct g13_input_report *) tbuf)->keybits,
> +			  LG_G13_BACKLIGHT_HW_ON_BIT);
> +
> +	return 0;
> +}
> +
> +static int lg_g13_kbd_led_write(struct lg_g15_data *g15,
> +				struct lg_g15_led *g15_led,
> +				enum led_brightness brightness)
> +{
> +	struct mc_subled const * const subleds = g15_led->mcdev.subled_info;
> +	u8 * const tbuf = g15->transfer_buf;
> +	int ret;
> +
> +	guard(mutex)(&g15->mutex);
> +
> +	led_mc_calc_color_components(&g15_led->mcdev, brightness);
> +
> +	tbuf[0] = 5;
> +	tbuf[1] = subleds[0].brightness;
> +	tbuf[2] = subleds[1].brightness;
> +	tbuf[3] = subleds[2].brightness;
> +	tbuf[4] = 0;
> +
> +	ret = hid_hw_raw_request(g15->hdev, LG_G13_FEATURE_BACKLIGHT_RGB,
> +				 tbuf, 5,
> +				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
> +	if (ret != 5) {
> +		hid_err(g15->hdev, "Error setting backlight brightness: %d\n", ret);
> +		return (ret < 0) ? ret : -EIO;
> +	}
> +
> +	g15_led->brightness = brightness;
> +	return 0;
> +}
> +
> +static int lg_g13_kbd_led_set(struct led_classdev *led_cdev, enum led_brightness brightness)
> +{
> +	struct led_classdev_mc *mc = lcdev_to_mccdev(led_cdev);
> +	struct lg_g15_led *g15_led =
> +		container_of(mc, struct lg_g15_led, mcdev);
> +	struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
> +
> +	/* Ignore LED off on unregister / keyboard unplug */
> +	if (led_cdev->flags & LED_UNREGISTERING)
> +		return 0;
> +
> +	return lg_g13_kbd_led_write(g15, g15_led, brightness);
> +}
> +
> +static enum led_brightness lg_g13_kbd_led_get(struct led_classdev *led_cdev)
> +{
> +	struct led_classdev_mc const * const mc = lcdev_to_mccdev(led_cdev);
> +	struct lg_g15_led const *g15_led =
> +		container_of(mc, struct lg_g15_led, mcdev);
> +
> +	return g15_led->brightness;
> +}
> +
> +static int lg_g13_mkey_led_set(struct led_classdev *led_cdev, enum led_brightness brightness)
> +{
> +	struct lg_g15_led *g15_led =
> +		container_of(led_cdev, struct lg_g15_led, cdev);
> +	struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
> +	int i, ret;
> +	u8 * const tbuf = g15->transfer_buf;
> +	u8 val, mask = 0;
> +
> +	/* Ignore LED off on unregister / keyboard unplug */
> +	if (led_cdev->flags & LED_UNREGISTERING)
> +		return 0;
> +
> +	guard(mutex)(&g15->mutex);
> +
> +	for (i = LG_G15_MACRO_PRESET1; i < LG_G15_LED_MAX; ++i) {
> +		if (i == g15_led->led)
> +			val = brightness;
> +		else
> +			val = g15->leds[i].brightness;
> +
> +		if (val)
> +			mask |= 1 << (i - LG_G15_MACRO_PRESET1);
> +	}
> +
> +	tbuf[0] = 5;
> +	tbuf[1] = mask;
> +	tbuf[2] = 0;
> +	tbuf[3] = 0;
> +	tbuf[4] = 0;
> +
> +	ret = hid_hw_raw_request(g15->hdev, LG_G13_FEATURE_M_KEYS_LEDS,
> +				 tbuf, 5,
> +				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
> +	if (ret != 5) {
> +		hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret);
> +		return (ret < 0) ? ret : -EIO;
> +	}
> +
> +	g15_led->brightness = brightness;
> +	return 0;
> +}
> +
> +static enum led_brightness lg_g13_mkey_led_get(struct led_classdev *led_cdev)
> +{
> +	/*
> +	 * G13 doesn't change macro key LEDs behind our back, so they're
> +	 * whatever we last set them to.
> +	 */
> +	struct lg_g15_led *g15_led =
> +		container_of(led_cdev, struct lg_g15_led, cdev);
> +
> +	return g15_led->brightness;
> +}
> +
>  /******** G15 and G15 v2 LED functions ********/
>  
>  static int lg_g15_update_led_brightness(struct lg_g15_data *g15)
> @@ -390,6 +586,8 @@ static int lg_g15_get_initial_led_brightness(struct lg_g15_data *g15)
>  	int ret;
>  
>  	switch (g15->model) {
> +	case LG_G13:
> +		return lg_g13_get_leds_state(g15);
>  	case LG_G15:
>  	case LG_G15_V2:
>  		return lg_g15_update_led_brightness(g15);
> @@ -417,6 +615,108 @@ static int lg_g15_get_initial_led_brightness(struct lg_g15_data *g15)
>  
>  /******** Input functions ********/
>  
> +/* Table mapping keybits[] bit positions to event codes. */
> +/* Note: Indices are discontinuous to aid readability. */
> +static const u16 g13_keys_for_bits[] = {
> +	/* Main keypad - keys G1 - G22 */
> +	[0] = KEY_MACRO1,
> +	[1] = KEY_MACRO2,
> +	[2] = KEY_MACRO3,
> +	[3] = KEY_MACRO4,
> +	[4] = KEY_MACRO5,
> +	[5] = KEY_MACRO6,
> +	[6] = KEY_MACRO7,
> +	[7] = KEY_MACRO8,
> +	[8] = KEY_MACRO9,
> +	[9] = KEY_MACRO10,
> +	[10] = KEY_MACRO11,
> +	[11] = KEY_MACRO12,
> +	[12] = KEY_MACRO13,
> +	[13] = KEY_MACRO14,
> +	[14] = KEY_MACRO15,
> +	[15] = KEY_MACRO16,
> +	[16] = KEY_MACRO17,
> +	[17] = KEY_MACRO18,
> +	[18] = KEY_MACRO19,
> +	[19] = KEY_MACRO20,
> +	[20] = KEY_MACRO21,
> +	[21] = KEY_MACRO22,
> +
> +	/* LCD menu buttons. */
> +	[24] = KEY_KBD_LCD_MENU5,	/* "Next page" button */
> +	[25] = KEY_KBD_LCD_MENU1,	/* Left-most */
> +	[26] = KEY_KBD_LCD_MENU2,
> +	[27] = KEY_KBD_LCD_MENU3,
> +	[28] = KEY_KBD_LCD_MENU4,	/* Right-most */
> +
> +	/* Macro preset and record buttons; have red LEDs under them. */
> +	[29] = KEY_MACRO_PRESET1,
> +	[30] = KEY_MACRO_PRESET2,
> +	[31] = KEY_MACRO_PRESET3,
> +	[32] = KEY_MACRO_RECORD_START,
> +
> +	/* 33-35 handled by joystick device. */
> +
> +	/* Backlight toggle. */
> +	[37] = KEY_LIGHTS_TOGGLE,
> +};
> +
> +#define G13_JS_KEYBITS_OFFSET	33
> +
> +static const u16 g13_keys_for_bits_js[] = {
> +	/* Joystick buttons */
> +	/* These keybits are at bit indices 33, 34, and 35. */
> +	BTN_BASE,	/* Left side */
> +	BTN_BASE2,	/* Bottom side */
> +	BTN_THUMB,	/* Stick depress */
> +};
> +
> +static int lg_g13_event(struct lg_g15_data *g15, u8 const *data)
> +{
> +	struct g13_input_report const * const rep = (struct g13_input_report *) data;
> +	int i, val;
> +	bool backlight_disabled;
> +
> +	/*
> +	 * Main macropad and menu keys.
> +	 * Emit key events defined for each bit position.
> +	 */
> +	for (i = 0; i < ARRAY_SIZE(g13_keys_for_bits); ++i) {
> +		if (g13_keys_for_bits[i]) {
> +			val = TEST_BIT(rep->keybits, i);
> +			input_report_key(g15->input, g13_keys_for_bits[i], val);
> +		}
> +	}
> +	input_sync(g15->input);
> +
> +	/*
> +	 * Joystick.
> +	 * Emit button and deflection events.
> +	 */
> +	for (i = 0; i < ARRAY_SIZE(g13_keys_for_bits_js); ++i) {
> +		val = TEST_BIT(rep->keybits, i + G13_JS_KEYBITS_OFFSET);
> +		input_report_key(g15->input_js, g13_keys_for_bits_js[i], val);
> +	}
> +	input_report_abs(g15->input_js, ABS_X, rep->joy_x);
> +	input_report_abs(g15->input_js, ABS_Y, rep->joy_y);
> +	input_sync(g15->input_js);
> +
> +	/*
> +	 * Bit 23 of keybits[] reports the current backlight on/off state.  If
> +	 * it has changed from the last cached value, apply an update.
> +	 */
> +	backlight_disabled = !TEST_BIT(rep->keybits, LG_G13_BACKLIGHT_HW_ON_BIT);
> +	if (backlight_disabled ^ g15->backlight_disabled) {
> +		led_classdev_notify_brightness_hw_changed(
> +			&g15->leds[LG_G15_KBD_BRIGHTNESS].mcdev.led_cdev,
> +			backlight_disabled
> +			? 0 : g15->leds[LG_G15_KBD_BRIGHTNESS].brightness);
> +		g15->backlight_disabled = backlight_disabled;
> +	}
> +
> +	return 0;
> +}
> +
>  /* On the G15 Mark I Logitech has been quite creative with which bit is what */
>  static void lg_g15_handle_lcd_menu_keys(struct lg_g15_data *g15, u8 *data)
>  {
> @@ -572,6 +872,10 @@ static int lg_g15_raw_event(struct hid_device *hdev, struct hid_report *report,
>  		return 0;
>  
>  	switch (g15->model) {
> +	case LG_G13:
> +		if (data[0] == 0x01 && size == sizeof(struct g13_input_report))
> +			return lg_g13_event(g15, data);
> +		break;
>  	case LG_G15:
>  		if (data[0] == 0x02 && size == 9)
>  			return lg_g15_event(g15, data);
> @@ -616,13 +920,22 @@ static void lg_g15_setup_led_rgb(struct lg_g15_data *g15, int index)
>  {
>  	int i;
>  	struct mc_subled *subled_info;
> -
> -	g15->leds[index].mcdev.led_cdev.brightness_set_blocking =
> -		lg_g510_kbd_led_set;
> -	g15->leds[index].mcdev.led_cdev.brightness_get =
> -		lg_g510_kbd_led_get;
> -	g15->leds[index].mcdev.led_cdev.max_brightness = 255;
> -	g15->leds[index].mcdev.num_colors = 3;
> +	struct lg_g15_led * const gled = &g15->leds[index];
> +
> +	if (g15->model == LG_G13) {
> +		gled->mcdev.led_cdev.brightness_set_blocking =
> +			lg_g13_kbd_led_set;
> +		gled->mcdev.led_cdev.brightness_get =
> +			lg_g13_kbd_led_get;
> +		gled->mcdev.led_cdev.flags = LED_BRIGHT_HW_CHANGED;
> +	} else {
> +		gled->mcdev.led_cdev.brightness_set_blocking =
> +			lg_g510_kbd_led_set;
> +		gled->mcdev.led_cdev.brightness_get =
> +			lg_g510_kbd_led_get;
> +	}
> +	gled->mcdev.led_cdev.max_brightness = 255;
> +	gled->mcdev.num_colors = 3;
>  
>  	subled_info = devm_kcalloc(&g15->hdev->dev, 3, sizeof(*subled_info), GFP_KERNEL);
>  	if (!subled_info)
> @@ -632,20 +945,20 @@ static void lg_g15_setup_led_rgb(struct lg_g15_data *g15, int index)
>  		switch (i + 1) {
>  		case LED_COLOR_ID_RED:
>  			subled_info[i].color_index = LED_COLOR_ID_RED;
> -			subled_info[i].intensity = g15->leds[index].red;
> +			subled_info[i].intensity = gled->red;
>  			break;
>  		case LED_COLOR_ID_GREEN:
>  			subled_info[i].color_index = LED_COLOR_ID_GREEN;
> -			subled_info[i].intensity = g15->leds[index].green;
> +			subled_info[i].intensity = gled->green;
>  			break;
>  		case LED_COLOR_ID_BLUE:
>  			subled_info[i].color_index = LED_COLOR_ID_BLUE;
> -			subled_info[i].intensity = g15->leds[index].blue;
> +			subled_info[i].intensity = gled->blue;
>  			break;
>  		}
>  		subled_info[i].channel = i;
>  	}
> -	g15->leds[index].mcdev.subled_info = subled_info;
> +	gled->mcdev.subled_info = subled_info;
>  }
>  
>  static int lg_g15_register_led(struct lg_g15_data *g15, int i, const char *name)
> @@ -656,6 +969,23 @@ static int lg_g15_register_led(struct lg_g15_data *g15, int i, const char *name)
>  	g15->leds[i].cdev.name = name;
>  
>  	switch (g15->model) {
> +	case LG_G13:
> +		if (i < LG_G15_BRIGHTNESS_MAX) {
> +			/* RGB backlight. */
> +			lg_g15_setup_led_rgb(g15, i);
> +			ret = devm_led_classdev_multicolor_register_ext(&g15->hdev->dev,
> +									&g15->leds[i].mcdev,
> +									NULL);
> +		} else {
> +			/* Macro keys */
> +			g15->leds[i].cdev.brightness_set_blocking = lg_g13_mkey_led_set;
> +			g15->leds[i].cdev.brightness_get = lg_g13_mkey_led_get;
> +			g15->leds[i].cdev.max_brightness = 1;
> +
> +			ret = devm_led_classdev_register(&g15->hdev->dev,
> +							 &g15->leds[i].cdev);
> +		}
> +		break;
>  	case LG_G15:
>  	case LG_G15_V2:
>  		g15->leds[i].cdev.brightness_get = lg_g15_led_get;
> @@ -702,11 +1032,9 @@ static int lg_g15_register_led(struct lg_g15_data *g15, int i, const char *name)
>  }
>  
>  /* Common input device init code shared between keyboards and Z-10 speaker handling */
> -static void lg_g15_init_input_dev(struct hid_device *hdev, struct input_dev *input,
> -				  const char *name)
> +static void lg_g15_init_input_dev_core(struct hid_device *hdev, struct input_dev *input,
> +				       char const *name)
>  {
> -	int i;
> -
>  	input->name = name;
>  	input->phys = hdev->phys;
>  	input->uniq = hdev->uniq;
> @@ -717,12 +1045,42 @@ static void lg_g15_init_input_dev(struct hid_device *hdev, struct input_dev *inp
>  	input->dev.parent = &hdev->dev;
>  	input->open = lg_g15_input_open;
>  	input->close = lg_g15_input_close;
> +}
> +
> +static void lg_g15_init_input_dev(struct hid_device *hdev, struct input_dev *input,
> +				  const char *name)
> +{
> +	int i;
> +
> +	lg_g15_init_input_dev_core(hdev, input, name);
>  
>  	/* Keys below the LCD, intended for controlling a menu on the LCD */
>  	for (i = 0; i < 5; i++)
>  		input_set_capability(input, EV_KEY, KEY_KBD_LCD_MENU1 + i);
>  }
>  
> +static void lg_g13_init_input_dev(struct hid_device *hdev,
> +				  struct input_dev *input, const char *name,
> +				  struct input_dev *input_js, const char *name_js)
> +{
> +	/* Macropad. */
> +	lg_g15_init_input_dev_core(hdev, input, name);
> +	for (int i = 0; i < ARRAY_SIZE(g13_keys_for_bits); ++i) {
> +		if (g13_keys_for_bits[i])
> +			input_set_capability(input, EV_KEY, g13_keys_for_bits[i]);
> +	}
> +
> +	/* OBTW, we're a joystick, too... */
> +	lg_g15_init_input_dev_core(hdev, input_js, name_js);
> +	for (int i = 0; i < ARRAY_SIZE(g13_keys_for_bits_js); ++i)
> +		input_set_capability(input_js, EV_KEY, g13_keys_for_bits_js[i]);
> +
> +	input_set_capability(input_js, EV_ABS, ABS_X);
> +	input_set_abs_params(input_js, ABS_X, 0, 255, 0, 0);
> +	input_set_capability(input_js, EV_ABS, ABS_Y);
> +	input_set_abs_params(input_js, ABS_Y, 0, 255, 0, 0);
> +}
> +
>  static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
>  {
>  	static const char * const led_names[] = {
> @@ -739,7 +1097,7 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
>  	unsigned int connect_mask = 0;
>  	bool has_ff000000 = false;
>  	struct lg_g15_data *g15;
> -	struct input_dev *input;
> +	struct input_dev *input, *input_js;
>  	struct hid_report *rep;
>  	int ret, i, gkeys = 0;
>  
> @@ -778,6 +1136,25 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
>  	hid_set_drvdata(hdev, (void *)g15);
>  
>  	switch (g15->model) {
> +	case LG_G13:
> +		/*
> +		 * The G13 has an analog thumbstick with nearby buttons.  Some
> +		 * libraries and applications are known to ignore devices that
> +		 * don't "look like" a joystick, and a device with two ABS axes
> +		 * and 25+ macro keys would confuse them.
> +		 *
> +		 * Create an additional input device dedicated to appear as a
> +		 * simplified joystick (two ABS axes, three BTN buttons).
> +		 */
> +		input_js = devm_input_allocate_device(&hdev->dev);
> +		if (!input_js)
> +			return -ENOMEM;
> +		g15->input_js = input_js;
> +		input_set_drvdata(input_js, hdev);
> +
> +		connect_mask = HID_CONNECT_HIDRAW;
> +		gkeys = 25;
> +		break;
>  	case LG_G15:
>  		INIT_WORK(&g15->work, lg_g15_leds_changed_work);
>  		/*
> @@ -859,6 +1236,38 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
>  			goto error_hw_stop;
>  
>  		return 0; /* All done */
> +	} else if (g15->model == LG_G13) {
> +		static char const * const g13_led_names[] = {
> +			/* Backlight is shared between LCD and keys. */
> +			"g13:rgb:kbd_backlight",
> +			NULL,	/* Keep in sync with led_type enum */
> +			"g13:red:macro_preset_1",
> +			"g13:red:macro_preset_2",
> +			"g13:red:macro_preset_3",
> +			"g13:red:macro_record",
> +		};
> +		lg_g13_init_input_dev(hdev,
> +				      input, "Logitech G13 Gaming Keypad",
> +				      input_js, "Logitech G13 Thumbstick");
> +		ret = input_register_device(input);
> +		if (ret)
> +			goto error_hw_stop;
> +		ret = input_register_device(input_js);
> +		if (ret)
> +			goto error_hw_stop;
> +
> +		for (i = 0; i < ARRAY_SIZE(g13_led_names); ++i) {
> +			if (g13_led_names[i]) {
> +				ret = lg_g15_register_led(g15, i, g13_led_names[i]);
> +				if (ret)
> +					goto error_hw_stop;
> +			}
> +		}
> +		led_classdev_notify_brightness_hw_changed(
> +			&g15->leds[LG_G15_KBD_BRIGHTNESS].mcdev.led_cdev,
> +			g15->backlight_disabled
> +			? 0 : g15->leds[LG_G15_KBD_BRIGHTNESS].brightness);
> +		return 0;
>  	}
>  
>  	/* Setup and register input device */
> @@ -903,6 +1312,13 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
>  }
>  
>  static const struct hid_device_id lg_g15_devices[] = {
> +	/*
> +	 * The G13 is a macropad-only device with an LCD, LED backlighing,
> +	 * and joystick.
> +	 */
> +	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
> +			 USB_DEVICE_ID_LOGITECH_G13),
> +		.driver_data = LG_G13 },
>  	/* The G11 is a G15 without the LCD, treat it as a G15 */
>  	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
>  		USB_DEVICE_ID_LOGITECH_G11),


^ permalink raw reply

* Re: [PATCH v5 3/6] dt-bindings: touchscreen: add touchscreen-glitch-threshold-ns property
From: Rob Herring @ 2025-09-19 20:44 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: linux-kernel, Frank Li, linux-amarula, Conor Dooley, Conor Dooley,
	Dmitry Torokhov, Javier Carrasco, Jeff LaBundy,
	Krzysztof Kozlowski, devicetree, linux-input
In-Reply-To: <CABGWkvrxOTzAcqWHLvuqk_7WFxybheSZFnMkqnksfkPi6wXcpQ@mail.gmail.com>

On Fri, Sep 19, 2025 at 05:12:42PM +0200, Dario Binacchi wrote:
> On Fri, Sep 19, 2025 at 4:38 PM Rob Herring <robh@kernel.org> wrote:
> >
> > On Thu, Sep 18, 2025 at 10:37:37PM +0200, Dario Binacchi wrote:
> > > On Thu, Sep 18, 2025 at 10:04 PM Rob Herring <robh@kernel.org> wrote:
> > > >
> > > > On Thu, Sep 18, 2025 at 05:52:31PM +0200, Dario Binacchi wrote:
> > > > > Add support for glitch threshold configuration. A detected signal is valid
> > > > > only if it lasts longer than the set threshold; otherwise, it is regarded
> > > > > as a glitch.
> > > > >
> > > > > Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> > > > > Acked-by: Conor Dooley <conor.dooley@microchip.com>
> > > > >
> > > > > ---
> > > > >
> > > > > Changes in v5:
> > > > > - Add Acked-by tag of Conor Dooley
> > > > >
> > > > > Changes in v2:
> > > > > - Added in v2.
> > > > >
> > > > >  .../devicetree/bindings/input/touchscreen/touchscreen.yaml    | 4 ++++
> > > > >  1 file changed, 4 insertions(+)
> > > > >
> > > > > diff --git a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
> > > > > index 3e3572aa483a..a60b4d08620d 100644
> > > > > --- a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
> > > > > +++ b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
> > > > > @@ -206,6 +206,10 @@ properties:
> > > > >
> > > > >          unevaluatedProperties: false
> > > > >
> > > > > +  touchscreen-glitch-threshold-ns:
> > > > > +    description: Minimum duration in nanoseconds a signal must remain stable
> > > > > +      to be considered valid.
> > > >
> > > > What's wrong with debounce-delay-ms?
> > >
> > > Do you mean that I should rename touchscreen-glitch-threshold-ns to
> > > debounce-delay-ms?
> >
> > I mean that's the common property we already have, so use it or explain
> > why you aren't using it. I suppose the definition is technically a bit
> > different if it's purely a s/w delay vs. h/w monitoring of the signal
> > state. I don't think it matters if the interpretation by each driver is
> > a bit different.
> >
> > Maybe msec is not enough resolution for you could be another reason?
> 
> Yes, this is the main reason. As specified in the following patch:
>   v5 4/6 dt-bindings: touchscreen: fsl,imx6ul-tsc: support glitch threshold
> 
> Drivers must convert this value to IPG clock cycles and map
> it to one of the four discrete thresholds exposed by the
> TSC_DEBUG_MODE2 register:
> 
>   0: 8191 IPG cycles
>   1: 4095 IPG cycles
>   2: 2047 IPG cycles
>   3: 1023 IPG cycles
> 
> In my case, the IPG clock runs at 66 MHz, which corresponds to:
> 
> 124 µs for 0
> 62 µs for 1
> 31 us for 2
> 15 us for 3
> 
> So using milliseconds would not fit my use case. A possible trade-off
> could be to use debounce-delay-us. Would that be acceptable?

I agree it wouldn't map to what the h/w provides, but is what the h/w 
provides actually useful? There's plenty of h/w designed that's not 
useful. 15us is quite short for a glitch. Do you have an actual cases 
where the different values above are needed?

Rob

^ permalink raw reply

* Re: [PATCH] HID: amd_sfh: Add sync across amd sfh work functions
From: Jiri Kosina @ 2025-09-19 15:30 UTC (permalink / raw)
  To: Basavaraj Natikar
  Cc: bentiss, linux-input, Matthew Schwartz, Prakruthi SP,
	Akshata MukundShetty
In-Reply-To: <20250918123202.1076393-1-Basavaraj.Natikar@amd.com>

On Thu, 18 Sep 2025, Basavaraj Natikar wrote:

> The process of the report is delegated across different work functions.
> Hence, add a sync mechanism to protect SFH work data across functions.
> 
> Fixes: 4b2c53d93a4b ("SFH:Transport Driver to add support of AMD Sensor Fusion Hub (SFH)")
> Reported-by: Matthew Schwartz <matthew.schwartz@linux.dev>
> Closes: https://lore.kernel.org/all/a21abca5-4268-449d-95f1-bdd7a25894a5@linux.dev/
> Tested-by: Prakruthi SP <Prakruthi.SP@amd.com>
> Co-developed-by: Akshata MukundShetty <akshata.mukundshetty@amd.com>
> Signed-off-by: Akshata MukundShetty <akshata.mukundshetty@amd.com>
> Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>

Applied, thanks.

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply

* Re: [PATCH v3 RESEND] hid: intel-thc-hid: intel-quicki2c: support ACPI config for advanced features
From: Jiri Kosina @ 2025-09-19 15:13 UTC (permalink / raw)
  To: Xinpeng Sun
  Cc: bentiss, srinivas.pandruvada, linux-input, linux-kernel, even.xu,
	Rui Zhang
In-Reply-To: <20250917015344.1169412-1-xinpeng.sun@intel.com>

On Wed, 17 Sep 2025, Xinpeng Sun wrote:

> There is a new BIOS enhancement that adds the capability to configure the
> following two features of I2C subsystem introduced in commit 1ed0b48
> ("Intel-thc: Introduce max input size control") and commit 3f2a921
> ("Intel-thc: Introduce interrupt delay control"):
> - Max input size control
> - Interrupt delay control
> 
> As BIOS is used for the configuration of these two features, change driver
> data usage to indicate hardware capability, and add corresponding ACPI
> configuration support in QuickI2C driver.

Applied to hid.git#for-6.18/intel-thc-hid, thanks.

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply

* Re: [PATCH v5 3/6] dt-bindings: touchscreen: add touchscreen-glitch-threshold-ns property
From: Dario Binacchi @ 2025-09-19 15:12 UTC (permalink / raw)
  To: Rob Herring
  Cc: linux-kernel, Frank Li, linux-amarula, Conor Dooley, Conor Dooley,
	Dmitry Torokhov, Javier Carrasco, Jeff LaBundy,
	Krzysztof Kozlowski, devicetree, linux-input
In-Reply-To: <20250919143831.GA862818-robh@kernel.org>

On Fri, Sep 19, 2025 at 4:38 PM Rob Herring <robh@kernel.org> wrote:
>
> On Thu, Sep 18, 2025 at 10:37:37PM +0200, Dario Binacchi wrote:
> > On Thu, Sep 18, 2025 at 10:04 PM Rob Herring <robh@kernel.org> wrote:
> > >
> > > On Thu, Sep 18, 2025 at 05:52:31PM +0200, Dario Binacchi wrote:
> > > > Add support for glitch threshold configuration. A detected signal is valid
> > > > only if it lasts longer than the set threshold; otherwise, it is regarded
> > > > as a glitch.
> > > >
> > > > Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> > > > Acked-by: Conor Dooley <conor.dooley@microchip.com>
> > > >
> > > > ---
> > > >
> > > > Changes in v5:
> > > > - Add Acked-by tag of Conor Dooley
> > > >
> > > > Changes in v2:
> > > > - Added in v2.
> > > >
> > > >  .../devicetree/bindings/input/touchscreen/touchscreen.yaml    | 4 ++++
> > > >  1 file changed, 4 insertions(+)
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
> > > > index 3e3572aa483a..a60b4d08620d 100644
> > > > --- a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
> > > > +++ b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
> > > > @@ -206,6 +206,10 @@ properties:
> > > >
> > > >          unevaluatedProperties: false
> > > >
> > > > +  touchscreen-glitch-threshold-ns:
> > > > +    description: Minimum duration in nanoseconds a signal must remain stable
> > > > +      to be considered valid.
> > >
> > > What's wrong with debounce-delay-ms?
> >
> > Do you mean that I should rename touchscreen-glitch-threshold-ns to
> > debounce-delay-ms?
>
> I mean that's the common property we already have, so use it or explain
> why you aren't using it. I suppose the definition is technically a bit
> different if it's purely a s/w delay vs. h/w monitoring of the signal
> state. I don't think it matters if the interpretation by each driver is
> a bit different.
>
> Maybe msec is not enough resolution for you could be another reason?

Yes, this is the main reason. As specified in the following patch:
  v5 4/6 dt-bindings: touchscreen: fsl,imx6ul-tsc: support glitch threshold

Drivers must convert this value to IPG clock cycles and map
it to one of the four discrete thresholds exposed by the
TSC_DEBUG_MODE2 register:

  0: 8191 IPG cycles
  1: 4095 IPG cycles
  2: 2047 IPG cycles
  3: 1023 IPG cycles

In my case, the IPG clock runs at 66 MHz, which corresponds to:

124 µs for 0
62 µs for 1
31 us for 2
15 us for 3

So using milliseconds would not fit my use case. A possible trade-off
could be to use debounce-delay-us. Would that be acceptable?

Thanks and regards
Dario

> Looks like your h/w supports that assuming the clock frequency is 10s
> of MHz. But are touchscreen glitches really in sub msec times? Not in my
> experience, but that's 20 years ago on resistive touchscreens...
>
> Rob



-- 

Dario Binacchi

Senior Embedded Linux Developer

dario.binacchi@amarulasolutions.com

__________________________________


Amarula Solutions SRL

Via Le Canevare 30, 31100 Treviso, Veneto, IT

T. +39 042 243 5310
info@amarulasolutions.com

www.amarulasolutions.com

^ permalink raw reply

* Re: The zero power level of the HID device in kernel 6.12 is not reported from the kernel to the upper layer.
From: Dmitry Torokhov @ 2025-09-19 15:04 UTC (permalink / raw)
  To: José Expósito
  Cc: 卢国宏, linux-input, linux-kernel, jikos,
	bentiss, 李鹏, Fei1 Jiang 蒋飞,
	宋密密
In-Reply-To: <aM0XBudxlXuzALbg@fedora>

Hi,

On Fri, Sep 19, 2025 at 10:40:38AM +0200, José Expósito wrote:
> Hi 卢国宏,
> 
> Thanks for reporting this issue.
> 
> In the furure, when reporting bugs, it is prefered to send them to the
> mailing list (linux-input@vger.kernel.org and linux-kernel@vger.kernel.org)
> to discuss them in public.
> 
> Let me forward your email to the mailing list and also CC Dmitry, the
> author of that code, who might help us understand the problem.
> 
> On Tue, Sep 16, 2025 at 12:29:32PM +0000, 卢国宏 wrote:
> > Hi, jose!
> >
> > We encountered a problem where the zero battery level of the HID device
> > in kernel 6.12 was not reported from the kernel to the upper layer.
> > I checked the HID protocol and it doesn't say that there is no need to
> > report the zero power of the HID device. For details, see page 381 of
> > the HID protocol, 31.4 Battery Measures. "Absolute State Of Charge DV
> > The predicted remaining battery capacity expressed as a percentage of
> > design capacity. (Units are %. The value may be greater than 100%.)".
> > However, in the file hid-input.c in kernel 6.12, the following code:
> > 
> > static void hidinput_update_battery(struct hid_device *dev, unsigned int usage,
> >                                     int value)
> > {
> >         int capacity;
> > 
> >         if (!dev->battery)
> >                 return;
> > 
> >         if (hidinput_update_battery_charge_status(dev, usage, value)) {
> >                 power_supply_changed(dev->battery);
> >                 return;
> >         }
> > 
> >         if (value == 0 || value < dev->battery_min || value > dev->battery_max)
> >                 return;
> > 
> >         capacity = hidinput_scale_battery_capacity(dev, value);
> > 
> >          ......
> > 
> > }
> > 
> > The parameter value is the power level. When the value is 0, the above code
> > returns without reporting.
> > Is this a problem?
> > We're currently experiencing this issue on Android 16. The upper layer of
> > Android needs to receive a zero battery level before it can take appropriate
> > action.

What kind of action are we talking about? Section 31 of the HID
specification defines events for "Smart Battery" ("To comply with the
Smart Battery Specification, the Battery System must support the
functions defined in the Battery and Charger usage tables. For details,
see Section 4.2, “Battery System Page (x85).”) and is typically used for
"battery pack for cellular phones (principal source), the battery
pack(s) for notebook computers (auxiliary source), and the sealed
batteries in uninterruptible power supplies (auxiliary source)."

Is your use case main battery or battery in a stylus or some other
peripheral?

> > Could you please help me evaluate whether we should remove the behavior of
> > returning to zero battery?
> >
> > Thanks!
> > #/******本邮件及其附件含有小米公司的保密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制、或散发)本邮件中的信息。如果您错收了本邮件,请您立即电话或邮件通知发件人并删除本邮件! This e-mail and its attachments contain confidential information from XIAOMI, which is intended only for the person or entity whose address is listed above. Any use of the information contained herein in any way (including, but not limited to, total or partial disclosure, reproduction, or dissemination) by persons other than the intended recipient(s) is prohibited. If you receive this e-mail in error, please notify the sender by phone or email immediately and delete it!******/#
> 
> It indeed looks like it could be problematic.
> 
> Values are allowed ot be grater than 100, however, I didn't find
> any references to negative values. Since it is a percentage, it
> make sense to limit it to 0%, i.e., not allowing negative values.
> 
> I think that removing the "value == 0" check, or replacing it with
> "value < 0" should fix the issue.

If we are dealing with peripherals (stylus for example) - for which this
piece of code was written - how a battery powered peripheral that is
fully discharged can communicate it's battery state of 0?

I think we have observed bogus reports with 0 values (IIRC trying to
query battery strength when stylus is not in proximity would yield
responses with 0 strength).

Thanks.

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH v5 3/6] dt-bindings: touchscreen: add touchscreen-glitch-threshold-ns property
From: Rob Herring @ 2025-09-19 14:38 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: linux-kernel, Frank Li, linux-amarula, Conor Dooley, Conor Dooley,
	Dmitry Torokhov, Javier Carrasco, Jeff LaBundy,
	Krzysztof Kozlowski, devicetree, linux-input
In-Reply-To: <CABGWkvqX9aCxam6UMYsUBkwnMJrMNKjVKrqi5Ca7O5Jk8xRTAA@mail.gmail.com>

On Thu, Sep 18, 2025 at 10:37:37PM +0200, Dario Binacchi wrote:
> On Thu, Sep 18, 2025 at 10:04 PM Rob Herring <robh@kernel.org> wrote:
> >
> > On Thu, Sep 18, 2025 at 05:52:31PM +0200, Dario Binacchi wrote:
> > > Add support for glitch threshold configuration. A detected signal is valid
> > > only if it lasts longer than the set threshold; otherwise, it is regarded
> > > as a glitch.
> > >
> > > Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> > > Acked-by: Conor Dooley <conor.dooley@microchip.com>
> > >
> > > ---
> > >
> > > Changes in v5:
> > > - Add Acked-by tag of Conor Dooley
> > >
> > > Changes in v2:
> > > - Added in v2.
> > >
> > >  .../devicetree/bindings/input/touchscreen/touchscreen.yaml    | 4 ++++
> > >  1 file changed, 4 insertions(+)
> > >
> > > diff --git a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
> > > index 3e3572aa483a..a60b4d08620d 100644
> > > --- a/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
> > > +++ b/Documentation/devicetree/bindings/input/touchscreen/touchscreen.yaml
> > > @@ -206,6 +206,10 @@ properties:
> > >
> > >          unevaluatedProperties: false
> > >
> > > +  touchscreen-glitch-threshold-ns:
> > > +    description: Minimum duration in nanoseconds a signal must remain stable
> > > +      to be considered valid.
> >
> > What's wrong with debounce-delay-ms?
> 
> Do you mean that I should rename touchscreen-glitch-threshold-ns to
> debounce-delay-ms?

I mean that's the common property we already have, so use it or explain 
why you aren't using it. I suppose the definition is technically a bit 
different if it's purely a s/w delay vs. h/w monitoring of the signal 
state. I don't think it matters if the interpretation by each driver is 
a bit different.

Maybe msec is not enough resolution for you could be another reason? 
Looks like your h/w supports that assuming the clock frequency is 10s 
of MHz. But are touchscreen glitches really in sub msec times? Not in my 
experience, but that's 20 years ago on resistive touchscreens...

Rob

^ permalink raw reply

* Re: [PATCH v3 RESEND] hid: intel-thc-hid: intel-quicki2c: support ACPI config for advanced features
From: Pandruvada, Srinivas @ 2025-09-19 14:20 UTC (permalink / raw)
  To: Sun, Xinpeng, jikos@kernel.org, Xu, Even, bentiss@kernel.org
  Cc: linux-input@vger.kernel.org, Zhang, Rui1,
	linux-kernel@vger.kernel.org
In-Reply-To: <IA1PR11MB6098555DA1279BFFCC9CDD89F411A@IA1PR11MB6098.namprd11.prod.outlook.com>

On Fri, 2025-09-19 at 07:56 +0000, Xu, Even wrote:
> 
> 
> > -----Original Message-----
> > From: Sun, Xinpeng <xinpeng.sun@intel.com>
> > Sent: Wednesday, September 17, 2025 9:54 AM
> > To: jikos@kernel.org; bentiss@kernel.org
> > Cc: srinivas.pandruvada@linux.intel.com;
> > linux-input@vger.kernel.org; linux-
> > kernel@vger.kernel.org; Xu, Even <even.xu@intel.com>; Sun, Xinpeng
> > <xinpeng.sun@intel.com>; Zhang, Rui1 <rui1.zhang@intel.com>
> > Subject: [PATCH v3 RESEND] hid: intel-thc-hid: intel-quicki2c:
> > support ACPI config
> > for advanced features
> > 
> > There is a new BIOS enhancement that adds the capability to
> > configure the
> > following two features of I2C subsystem introduced in commit
> > 1ed0b48
> > ("Intel-thc: Introduce max input size control") and commit 3f2a921
> > ("Intel-thc: Introduce interrupt delay control"):
> > - Max input size control
> > - Interrupt delay control
> > 
> > As BIOS is used for the configuration of these two features, change
> > driver data
> > usage to indicate hardware capability, and add corresponding ACPI
> > configuration
> > support in QuickI2C driver.
> > 
> > Signed-off-by: Xinpeng Sun <xinpeng.sun@intel.com>
> > Tested-by: Rui Zhang <rui1.zhang@intel.com>

Add your reviewed-by here..

> > 
> > ---
> > Changes in v3:
> >  - remove unnecessary initialization of local variables Changes in
> > v2:
> >  - refine the commit message
> > ---
> >  .../intel-quicki2c/pci-quicki2c.c             | 39
> > +++++++++++++++----
> >  .../intel-quicki2c/quicki2c-dev.h             | 24 +++++++++++-
> >  2 files changed, 53 insertions(+), 10 deletions(-)
> > 
> > diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-
> > quicki2c.c
> > b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
> > index 854926b3cfd4..3ce5a692b92b 100644
> > --- a/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
> > +++ b/drivers/hid/intel-thc-hid/intel-quicki2c/pci-quicki2c.c
> > @@ -23,6 +23,7 @@
> > 
> >  static struct quicki2c_ddata ptl_ddata = {
> >  	.max_detect_size = MAX_RX_DETECT_SIZE_PTL,
> > +	.max_interrupt_delay = MAX_RX_INTERRUPT_DELAY,
> >  };
> > 
> >  /* THC QuickI2C ACPI method to get device properties */ @@ -200,6
> > +201,21
> > @@ static int quicki2c_get_acpi_resources(struct quicki2c_device
> > *qcdev)
> >  		return -EOPNOTSUPP;
> >  	}
> > 
> > +	if (qcdev->ddata) {
> > +		qcdev->i2c_max_frame_size_enable =
> > i2c_config.FSEN;
> > +		qcdev->i2c_int_delay_enable = i2c_config.INDE;
> > +
> > +		if (i2c_config.FSVL <= qcdev->ddata-
> > >max_detect_size)
> > +			qcdev->i2c_max_frame_size =
> > i2c_config.FSVL;
> > +		else
> > +			qcdev->i2c_max_frame_size = qcdev->ddata-
> > > max_detect_size;
> > +
> > +		if (i2c_config.INDV <= qcdev->ddata-
> > >max_interrupt_delay)
> > +			qcdev->i2c_int_delay = i2c_config.INDV;
> > +		else
> > +			qcdev->i2c_int_delay = qcdev->ddata-
> > > max_interrupt_delay;
> > +	}
> > +
> >  	return 0;
> >  }
> > 
> > @@ -441,17 +457,24 @@ static void quicki2c_dma_adv_enable(struct
> > quicki2c_device *qcdev)
> >  	 * max input length <= THC detect capability, enable the
> > feature with
> > device
> >  	 * max input length.
> >  	 */
> > -	if (qcdev->ddata->max_detect_size >=
> > -	    le16_to_cpu(qcdev->dev_desc.max_input_len)) {
> > -		thc_i2c_set_rx_max_size(qcdev->thc_hw,
> > -					le16_to_cpu(qcdev-
> > > dev_desc.max_input_len));
> > +	if (qcdev->i2c_max_frame_size_enable) {
> > +		if (qcdev->i2c_max_frame_size >=
> > +		    le16_to_cpu(qcdev->dev_desc.max_input_len)) {
> > +			thc_i2c_set_rx_max_size(qcdev->thc_hw,
> > +						le16_to_cpu(qcdev-
> > > dev_desc.max_input_len));
> > +		} else {
> > +			dev_warn(qcdev->dev,
> > +				 "Max frame size is smaller than
> > hid max input
> > length!");
> > +			thc_i2c_set_rx_max_size(qcdev->thc_hw,
> > +						le16_to_cpu(qcdev-
> > > i2c_max_frame_size));
> > +		}
> >  		thc_i2c_rx_max_size_enable(qcdev->thc_hw, true);
> >  	}
> > 
> >  	/* If platform supports interrupt delay feature, enable it
> > with given delay
> > */
> > -	if (qcdev->ddata->interrupt_delay) {
> > +	if (qcdev->i2c_int_delay_enable) {
> >  		thc_i2c_set_rx_int_delay(qcdev->thc_hw,
> > -					 qcdev->ddata-
> > >interrupt_delay);
> > +					 qcdev->i2c_int_delay *
> > 10);
> >  		thc_i2c_rx_int_delay_enable(qcdev->thc_hw, true);
> >  	}
> >  }
> > @@ -464,10 +487,10 @@ static void quicki2c_dma_adv_enable(struct
> > quicki2c_device *qcdev)
> >   */
> >  static void quicki2c_dma_adv_disable(struct quicki2c_device
> > *qcdev)  {
> > -	if (qcdev->ddata->max_detect_size)
> > +	if (qcdev->i2c_max_frame_size_enable)
> >  		thc_i2c_rx_max_size_enable(qcdev->thc_hw, false);
> > 
> > -	if (qcdev->ddata->interrupt_delay)
> > +	if (qcdev->i2c_int_delay_enable)
> >  		thc_i2c_rx_int_delay_enable(qcdev->thc_hw,
> > false);  }
> > 
> > diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-
> > dev.h
> > b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h
> > index d412eafcf9ea..0d423d5dd7a7 100644
> > --- a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h
> > +++ b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-dev.h
> > @@ -38,6 +38,8 @@
> > 
> >  /* PTL Max packet size detection capability is 255 Bytes */
> >  #define MAX_RX_DETECT_SIZE_PTL			255
> > +/* Max interrupt delay capability is 2.56ms */
> > +#define MAX_RX_INTERRUPT_DELAY			256
> > 
> >  /* Default interrupt delay is 1ms, suitable for most devices */
> >  #define DEFAULT_INTERRUPT_DELAY_US		(1 *
> > USEC_PER_MSEC)
> > @@ -101,6 +103,10 @@ struct quicki2c_subip_acpi_parameter {
> >   * @HMTD: High Speed Mode Plus (3.4Mbits/sec) Serial Data Line
> > Transmit
> > HOLD Period
> >   * @HMRD: High Speed Mode Plus (3.4Mbits/sec) Serial Data Line
> > Receive HOLD
> > Period
> >   * @HMSL: Maximum length (in ic_clk_cycles) of suppressed spikes
> > in High Speed
> > Mode
> > + * @FSEN: Maximum Frame Size Feature Enable Control
> > + * @FSVL: Maximum Frame Size Value (unit in Bytes)
> > + * @INDE: Interrupt Delay Feature Enable Control
> > + * @INDV: Interrupt Delay Value (unit in 10 us)
> >   *
> >   * Those properties get from QUICKI2C_ACPI_METHOD_NAME_ISUB
> > method,
> > used for
> >   * I2C timing configure.
> > @@ -127,17 +133,22 @@ struct quicki2c_subip_acpi_config {
> >  	u64 HMTD;
> >  	u64 HMRD;
> >  	u64 HMSL;
> > +
> > +	u64 FSEN;
> > +	u64 FSVL;
> > +	u64 INDE;
> > +	u64 INDV;
> >  	u8 reserved;
> >  };
> > 
> >  /**
> >   * struct quicki2c_ddata - Driver specific data for quicki2c
> > device
> >   * @max_detect_size: Identify max packet size detect for rx
> > - * @interrupt_delay: Identify interrupt detect delay for rx
> > + * @interrupt_delay: Identify max interrupt detect delay for rx
> >   */
> >  struct quicki2c_ddata {
> >  	u32 max_detect_size;
> > -	u32 interrupt_delay;
> > +	u32 max_interrupt_delay;
> >  };
> > 
> >  struct device;
> > @@ -170,6 +181,10 @@ struct acpi_device;
> >   * @report_len: The length of input/output report packet
> >   * @reset_ack_wq: Workqueue for waiting reset response from device
> >   * @reset_ack: Indicate reset response received or not
> > + * @i2c_max_frame_size_enable: Indicate max frame size feature
> > enabled
> > + or not
> > + * @i2c_max_frame_size: Max RX frame size (unit in Bytes)
> > + * @i2c_int_delay_enable: Indicate interrupt delay feature enabled
> > or
> > + not
> > + * @i2c_int_delay: Interrupt detection delay value (unit in 10 us)
> >   */
> >  struct quicki2c_device {
> >  	struct device *dev;
> > @@ -200,6 +215,11 @@ struct quicki2c_device {
> > 
> >  	wait_queue_head_t reset_ack_wq;
> >  	bool reset_ack;
> > +
> > +	u32 i2c_max_frame_size_enable;
> > +	u32 i2c_max_frame_size;
> > +	u32 i2c_int_delay_enable;
> > +	u32 i2c_int_delay;
> >  };
> > 
> 
> Thanks for the patch!
> 
> Reviewed-by: Even Xu <even.xu@intel.com>
> 
> >  #endif /* _QUICKI2C_DEV_H_ */
> > --
> > 2.40.1
> 


^ permalink raw reply

* Re: [PATCH 00/27 5.10.y] Backport minmax.h updates from v6.17-rc6
From: Christian König @ 2025-09-19 12:11 UTC (permalink / raw)
  To: Eliav Farber, linux, jdike, richard, anton.ivanov, dave.hansen,
	luto, peterz, tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo,
	mchehab, james.morse, rric, harry.wentland, sunpeng.li,
	alexander.deucher, airlied, daniel, evan.quan, james.qian.wang,
	liviu.dudau, mihail.atanassov, brian.starkey, maarten.lankhorst,
	mripard, tzimmermann, robdclark, sean, jdelvare, linux, fery,
	dmitry.torokhov, agk, snitzer, dm-devel, rajur, davem, kuba,
	peppe.cavallaro, alexandre.torgue, joabreu, mcoquelin.stm32,
	malattia, hdegoede, mgross, intel-linux-scu, artur.paszkiewicz,
	jejb, martin.petersen, sakari.ailus, gregkh, clm, josef, dsterba,
	jack, tytso, adilger.kernel, dushistov, luc.vanoostenryck,
	rostedt, pmladek, sergey.senozhatsky, andriy.shevchenko, linux,
	minchan, ngupta, akpm, kuznet, yoshfuji, pablo, kadlec, fw,
	jmaloy, ying.xue, willy, sashal, ruanjinjie, David.Laight,
	herve.codina, Jason, bvanassche, keescook, linux-arm-kernel,
	linux-kernel, linux-um, linux-edac, amd-gfx, dri-devel,
	linux-arm-msm, freedreno, linux-hwmon, linux-input, 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, stable
  Cc: jonnyc
In-Reply-To: <20250919101727.16152-1-farbere@amazon.com>

On 19.09.25 12:17, Eliav Farber wrote:
> This series includes a total of 27 patches, to align minmax.h of
> v5.15.y with v6.17-rc6.
> 
> The set consists of 24 commits that directly update minmax.h:
> 1) 92d23c6e9415 ("overflow, tracing: Define the is_signed_type() macro
>    once")
> 2) 5efcecd9a3b1 ("minmax: sanity check constant bounds when clamping")
> 3) 2122e2a4efc2 ("minmax: clamp more efficiently by avoiding extra
>    comparison")
> 4) f9bff0e31881 ("minmax: add in_range() macro")
> 5) c952c748c7a9 ("minmax: Introduce {min,max}_array()")
> 6) 5e57418a2031 ("minmax: deduplicate __unconst_integer_typeof()")
> 7) f6e9d38f8eb0 ("minmax: fix header inclusions")
> 8) d03eba99f5bf ("minmax: allow min()/max()/clamp() if the arguments
>    have the same signedness.")
> 9) f4b84b2ff851 ("minmax: fix indentation of __cmp_once() and
>    __clamp_once()")
> 10) 4ead534fba42 ("minmax: allow comparisons of 'int' against 'unsigned
>     char/short'")
> 11) 867046cc7027 ("minmax: relax check to allow comparison between
>     unsigned arguments and signed constants")
> 12) 3a7e02c040b1 ("minmax: avoid overly complicated constant
>     expressions in VM code")
> 14) 017fa3e89187 ("minmax: simplify and clarify min_t()/max_t()
>     implementation")
> 15) 1a251f52cfdc ("minmax: make generic MIN() and MAX() macros
>     available everywhere")
> 18) dc1c8034e31b ("minmax: simplify min()/max()/clamp()
>     implementation")
> 19) 22f546873149 ("minmax: improve macro expansion and type
>     checking")
> 20) 21b136cc63d2 ("minmax: fix up min3() and max3() too")
> 21) 71ee9b16251e ("minmax.h: add whitespace around operators and after
>     commas")
> 22) 10666e992048 ("minmax.h: update some comments")
> 23) b280bb27a9f7 ("minmax.h: reduce the #define expansion of min(),
>     max() and clamp()")
> 24) a5743f32baec ("minmax.h: use BUILD_BUG_ON_MSG() for the lo < hi
>     test in clamp()")
> 25) c3939872ee4a ("minmax.h: move all the clamp() definitions after the
>     min/max() ones")
> 26) 495bba17cdf9 ("minmax.h: simplify the variants of clamp()")
> 27) 2b97aaf74ed5 ("minmax.h: remove some #defines that are only
>     expanded once")
> 
> 2 prerequisite commits that adjust users of MIN and MAX macros (to
> prevent compilation issues):
> 13) 4477b39c32fd ("minmax: add a few more MIN_T/MAX_T users")
> 17) cb04e8b1d2f2 ("minmax: don't use max() in situations that want a C
>     constant expression")
> 
> 1 additional commit introduced to resolve a build failures during the
> backport:
> 16) lib: zstd: drop local MIN/MAX macros in favor of generic ones
> 
> The primary motivation is to bring in commit (8).
> In mainline, this change allows min()/max()/clamp() to accept mixed
> argument types when both share the same signedness.
> Backported patches to v5.10.y that use such forms trigger compiler
> warnings, which in turn cause build failures when -Werror is enabled.
> 
> Originaly I aligned 5.10.y to 5.15.y, but David Laight commented that I
> need to pick up the later changes (from Linus) as well.
> 
> Andy Shevchenko (2):
>   minmax: deduplicate __unconst_integer_typeof()
>   minmax: fix header inclusions
> 
> Bart Van Assche (1):
>   overflow, tracing: Define the is_signed_type() macro once
> 
> David Laight (11):
>   minmax: allow min()/max()/clamp() if the arguments have the same
>     signedness.
>   minmax: fix indentation of __cmp_once() and __clamp_once()
>   minmax: allow comparisons of 'int' against 'unsigned char/short'
>   minmax: relax check to allow comparison between unsigned arguments and
>     signed constants
>   minmax.h: add whitespace around operators and after commas
>   minmax.h: update some comments
>   minmax.h: reduce the #define expansion of min(), max() and clamp()
>   minmax.h: use BUILD_BUG_ON_MSG() for the lo < hi test in clamp()
>   minmax.h: move all the clamp() definitions after the min/max() ones
>   minmax.h: simplify the variants of clamp()
>   minmax.h: remove some #defines that are only expanded once
> 
> Eliav Farber (1):
>   lib: zstd: drop local MIN/MAX macros in favor of generic ones
> 
> Herve Codina (1):
>   minmax: Introduce {min,max}_array()
> 
> Jason A. Donenfeld (2):
>   minmax: sanity check constant bounds when clamping
>   minmax: clamp more efficiently by avoiding extra comparison
> 
> Linus Torvalds (8):
>   minmax: avoid overly complicated constant expressions in VM code
>   minmax: add a few more MIN_T/MAX_T users
>   minmax: simplify and clarify min_t()/max_t() implementation
>   minmax: make generic MIN() and MAX() macros available everywhere
>   minmax: don't use max() in situations that want a C constant
>     expression
>   minmax: simplify min()/max()/clamp() implementation
>   minmax: improve macro expansion and type checking
>   minmax: fix up min3() and max3() too
> 
> Matthew Wilcox (Oracle) (1):
>   minmax: add in_range() macro
> 
>  arch/arm/mm/pageattr.c                        |   6 +-
>  arch/um/drivers/mconsole_user.c               |   2 +
>  arch/x86/mm/pgtable.c                         |   2 +-

>  drivers/edac/sb_edac.c                        |   4 +-
>  drivers/edac/skx_common.h                     |   1 -
>  .../drm/amd/display/modules/hdcp/hdcp_ddc.c   |   2 +
>  .../drm/amd/pm/powerplay/hwmgr/ppevvmath.h    |  14 +-
>  .../drm/arm/display/include/malidp_utils.h    |   2 +-
>  .../display/komeda/komeda_pipeline_state.c    |  24 +-
>  drivers/gpu/drm/drm_color_mgmt.c              |   2 +-
>  drivers/gpu/drm/msm/adreno/a6xx_gmu.c         |   6 -
>  drivers/gpu/drm/radeon/evergreen_cs.c         |   2 +
>  drivers/hwmon/adt7475.c                       |  24 +-
>  drivers/input/touchscreen/cyttsp4_core.c      |   2 +-
>  drivers/md/dm-integrity.c                     |   2 +-
>  drivers/media/dvb-frontends/stv0367_priv.h    |   3 +
>  .../net/ethernet/chelsio/cxgb3/cxgb3_main.c   |  18 +-
>  .../net/ethernet/stmicro/stmmac/stmmac_main.c |   2 +-
>  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 +-

I do see the value to backport the infrastructure, but why are driver specific changes backported as well?

I mean the changes are most likely correct but also not valuable in anyway as bug fix.

Regards,
Christian.

>  .../pci/hive_isp_css_include/math_support.h   |   5 -
>  fs/btrfs/misc.h                               |   2 -
>  fs/btrfs/tree-checker.c                       |   2 +-
>  fs/ext2/balloc.c                              |   2 -
>  fs/ext4/ext4.h                                |   2 -
>  fs/ufs/util.h                                 |   6 -
>  include/linux/compiler.h                      |  15 +
>  include/linux/minmax.h                        | 267 ++++++++++++++----
>  include/linux/overflow.h                      |   1 -
>  include/linux/trace_events.h                  |   2 -
>  kernel/trace/preemptirq_delay_test.c          |   2 -
>  lib/btree.c                                   |   1 -
>  lib/decompress_unlzma.c                       |   2 +
>  lib/logic_pio.c                               |   3 -
>  lib/vsprintf.c                                |   2 +-
>  lib/zstd/zstd_internal.h                      |   2 -
>  mm/zsmalloc.c                                 |   1 -
>  net/ipv4/proc.c                               |   2 +-
>  net/ipv6/proc.c                               |   2 +-
>  net/netfilter/nf_nat_core.c                   |   6 +-
>  net/tipc/core.h                               |   2 +-
>  net/tipc/link.c                               |  10 +-
>  44 files changed, 306 insertions(+), 164 deletions(-)
> 


^ permalink raw reply

* [PATCH 27/27 5.10.y] minmax.h: remove some #defines that are only expanded once
From: Eliav Farber @ 2025-09-19 10:17 UTC (permalink / raw)
  To: linux, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
	tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, mchehab,
	james.morse, rric, harry.wentland, sunpeng.li, alexander.deucher,
	christian.koenig, airlied, daniel, evan.quan, james.qian.wang,
	liviu.dudau, mihail.atanassov, brian.starkey, maarten.lankhorst,
	mripard, tzimmermann, robdclark, sean, jdelvare, linux, fery,
	dmitry.torokhov, agk, snitzer, dm-devel, rajur, davem, kuba,
	peppe.cavallaro, alexandre.torgue, joabreu, mcoquelin.stm32,
	malattia, hdegoede, mgross, intel-linux-scu, artur.paszkiewicz,
	jejb, martin.petersen, sakari.ailus, gregkh, clm, josef, dsterba,
	jack, tytso, adilger.kernel, dushistov, luc.vanoostenryck,
	rostedt, pmladek, sergey.senozhatsky, andriy.shevchenko, linux,
	minchan, ngupta, akpm, kuznet, yoshfuji, pablo, kadlec, fw,
	jmaloy, ying.xue, willy, farbere, sashal, ruanjinjie,
	David.Laight, herve.codina, Jason, bvanassche, keescook,
	linux-arm-kernel, linux-kernel, linux-um, linux-edac, amd-gfx,
	dri-devel, linux-arm-msm, freedreno, linux-hwmon, linux-input,
	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, stable
  Cc: jonnyc, Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
	Jens Axboe, Lorenzo Stoakes, Mateusz Guzik, Pedro Falcato
In-Reply-To: <20250919101727.16152-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 26/27 5.10.y] minmax.h: simplify the variants of clamp()
From: Eliav Farber @ 2025-09-19 10:17 UTC (permalink / raw)
  To: linux, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
	tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, mchehab,
	james.morse, rric, harry.wentland, sunpeng.li, alexander.deucher,
	christian.koenig, airlied, daniel, evan.quan, james.qian.wang,
	liviu.dudau, mihail.atanassov, brian.starkey, maarten.lankhorst,
	mripard, tzimmermann, robdclark, sean, jdelvare, linux, fery,
	dmitry.torokhov, agk, snitzer, dm-devel, rajur, davem, kuba,
	peppe.cavallaro, alexandre.torgue, joabreu, mcoquelin.stm32,
	malattia, hdegoede, mgross, intel-linux-scu, artur.paszkiewicz,
	jejb, martin.petersen, sakari.ailus, gregkh, clm, josef, dsterba,
	jack, tytso, adilger.kernel, dushistov, luc.vanoostenryck,
	rostedt, pmladek, sergey.senozhatsky, andriy.shevchenko, linux,
	minchan, ngupta, akpm, kuznet, yoshfuji, pablo, kadlec, fw,
	jmaloy, ying.xue, willy, farbere, sashal, ruanjinjie,
	David.Laight, herve.codina, Jason, bvanassche, keescook,
	linux-arm-kernel, linux-kernel, linux-um, linux-edac, amd-gfx,
	dri-devel, linux-arm-msm, freedreno, linux-hwmon, linux-input,
	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, stable
  Cc: jonnyc, Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
	Jens Axboe, Lorenzo Stoakes, Mateusz Guzik, Pedro Falcato
In-Reply-To: <20250919101727.16152-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 25/27 5.10.y] minmax.h: move all the clamp() definitions after the min/max() ones
From: Eliav Farber @ 2025-09-19 10:17 UTC (permalink / raw)
  To: linux, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
	tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, mchehab,
	james.morse, rric, harry.wentland, sunpeng.li, alexander.deucher,
	christian.koenig, airlied, daniel, evan.quan, james.qian.wang,
	liviu.dudau, mihail.atanassov, brian.starkey, maarten.lankhorst,
	mripard, tzimmermann, robdclark, sean, jdelvare, linux, fery,
	dmitry.torokhov, agk, snitzer, dm-devel, rajur, davem, kuba,
	peppe.cavallaro, alexandre.torgue, joabreu, mcoquelin.stm32,
	malattia, hdegoede, mgross, intel-linux-scu, artur.paszkiewicz,
	jejb, martin.petersen, sakari.ailus, gregkh, clm, josef, dsterba,
	jack, tytso, adilger.kernel, dushistov, luc.vanoostenryck,
	rostedt, pmladek, sergey.senozhatsky, andriy.shevchenko, linux,
	minchan, ngupta, akpm, kuznet, yoshfuji, pablo, kadlec, fw,
	jmaloy, ying.xue, willy, farbere, sashal, ruanjinjie,
	David.Laight, herve.codina, Jason, bvanassche, keescook,
	linux-arm-kernel, linux-kernel, linux-um, linux-edac, amd-gfx,
	dri-devel, linux-arm-msm, freedreno, linux-hwmon, linux-input,
	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, stable
  Cc: jonnyc, Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
	Jens Axboe, Lorenzo Stoakes, Mateusz Guzik, Pedro Falcato
In-Reply-To: <20250919101727.16152-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 24/27 5.10.y] minmax.h: use BUILD_BUG_ON_MSG() for the lo < hi test in clamp()
From: Eliav Farber @ 2025-09-19 10:17 UTC (permalink / raw)
  To: linux, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
	tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, mchehab,
	james.morse, rric, harry.wentland, sunpeng.li, alexander.deucher,
	christian.koenig, airlied, daniel, evan.quan, james.qian.wang,
	liviu.dudau, mihail.atanassov, brian.starkey, maarten.lankhorst,
	mripard, tzimmermann, robdclark, sean, jdelvare, linux, fery,
	dmitry.torokhov, agk, snitzer, dm-devel, rajur, davem, kuba,
	peppe.cavallaro, alexandre.torgue, joabreu, mcoquelin.stm32,
	malattia, hdegoede, mgross, intel-linux-scu, artur.paszkiewicz,
	jejb, martin.petersen, sakari.ailus, gregkh, clm, josef, dsterba,
	jack, tytso, adilger.kernel, dushistov, luc.vanoostenryck,
	rostedt, pmladek, sergey.senozhatsky, andriy.shevchenko, linux,
	minchan, ngupta, akpm, kuznet, yoshfuji, pablo, kadlec, fw,
	jmaloy, ying.xue, willy, farbere, sashal, ruanjinjie,
	David.Laight, herve.codina, Jason, bvanassche, keescook,
	linux-arm-kernel, linux-kernel, linux-um, linux-edac, amd-gfx,
	dri-devel, linux-arm-msm, freedreno, linux-hwmon, linux-input,
	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, stable
  Cc: jonnyc, Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
	Jens Axboe, Lorenzo Stoakes, Mateusz Guzik, Pedro Falcato
In-Reply-To: <20250919101727.16152-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 23/27 5.10.y] minmax.h: reduce the #define expansion of min(), max() and clamp()
From: Eliav Farber @ 2025-09-19 10:17 UTC (permalink / raw)
  To: linux, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
	tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, mchehab,
	james.morse, rric, harry.wentland, sunpeng.li, alexander.deucher,
	christian.koenig, airlied, daniel, evan.quan, james.qian.wang,
	liviu.dudau, mihail.atanassov, brian.starkey, maarten.lankhorst,
	mripard, tzimmermann, robdclark, sean, jdelvare, linux, fery,
	dmitry.torokhov, agk, snitzer, dm-devel, rajur, davem, kuba,
	peppe.cavallaro, alexandre.torgue, joabreu, mcoquelin.stm32,
	malattia, hdegoede, mgross, intel-linux-scu, artur.paszkiewicz,
	jejb, martin.petersen, sakari.ailus, gregkh, clm, josef, dsterba,
	jack, tytso, adilger.kernel, dushistov, luc.vanoostenryck,
	rostedt, pmladek, sergey.senozhatsky, andriy.shevchenko, linux,
	minchan, ngupta, akpm, kuznet, yoshfuji, pablo, kadlec, fw,
	jmaloy, ying.xue, willy, farbere, sashal, ruanjinjie,
	David.Laight, herve.codina, Jason, bvanassche, keescook,
	linux-arm-kernel, linux-kernel, linux-um, linux-edac, amd-gfx,
	dri-devel, linux-arm-msm, freedreno, linux-hwmon, linux-input,
	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, stable
  Cc: jonnyc, Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
	Jens Axboe, Lorenzo Stoakes, Mateusz Guzik, Pedro Falcato
In-Reply-To: <20250919101727.16152-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 22/27 5.10.y] minmax.h: update some comments
From: Eliav Farber @ 2025-09-19 10:17 UTC (permalink / raw)
  To: linux, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
	tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, mchehab,
	james.morse, rric, harry.wentland, sunpeng.li, alexander.deucher,
	christian.koenig, airlied, daniel, evan.quan, james.qian.wang,
	liviu.dudau, mihail.atanassov, brian.starkey, maarten.lankhorst,
	mripard, tzimmermann, robdclark, sean, jdelvare, linux, fery,
	dmitry.torokhov, agk, snitzer, dm-devel, rajur, davem, kuba,
	peppe.cavallaro, alexandre.torgue, joabreu, mcoquelin.stm32,
	malattia, hdegoede, mgross, intel-linux-scu, artur.paszkiewicz,
	jejb, martin.petersen, sakari.ailus, gregkh, clm, josef, dsterba,
	jack, tytso, adilger.kernel, dushistov, luc.vanoostenryck,
	rostedt, pmladek, sergey.senozhatsky, andriy.shevchenko, linux,
	minchan, ngupta, akpm, kuznet, yoshfuji, pablo, kadlec, fw,
	jmaloy, ying.xue, willy, farbere, sashal, ruanjinjie,
	David.Laight, herve.codina, Jason, bvanassche, keescook,
	linux-arm-kernel, linux-kernel, linux-um, linux-edac, amd-gfx,
	dri-devel, linux-arm-msm, freedreno, linux-hwmon, linux-input,
	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, stable
  Cc: jonnyc, Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
	Jens Axboe, Lorenzo Stoakes, Mateusz Guzik, Pedro Falcato
In-Reply-To: <20250919101727.16152-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 21/27 5.10.y] minmax.h: add whitespace around operators and after commas
From: Eliav Farber @ 2025-09-19 10:17 UTC (permalink / raw)
  To: linux, jdike, richard, anton.ivanov, dave.hansen, luto, peterz,
	tglx, mingo, bp, x86, hpa, tony.luck, qiuxu.zhuo, mchehab,
	james.morse, rric, harry.wentland, sunpeng.li, alexander.deucher,
	christian.koenig, airlied, daniel, evan.quan, james.qian.wang,
	liviu.dudau, mihail.atanassov, brian.starkey, maarten.lankhorst,
	mripard, tzimmermann, robdclark, sean, jdelvare, linux, fery,
	dmitry.torokhov, agk, snitzer, dm-devel, rajur, davem, kuba,
	peppe.cavallaro, alexandre.torgue, joabreu, mcoquelin.stm32,
	malattia, hdegoede, mgross, intel-linux-scu, artur.paszkiewicz,
	jejb, martin.petersen, sakari.ailus, gregkh, clm, josef, dsterba,
	jack, tytso, adilger.kernel, dushistov, luc.vanoostenryck,
	rostedt, pmladek, sergey.senozhatsky, andriy.shevchenko, linux,
	minchan, ngupta, akpm, kuznet, yoshfuji, pablo, kadlec, fw,
	jmaloy, ying.xue, willy, farbere, sashal, ruanjinjie,
	David.Laight, herve.codina, Jason, bvanassche, keescook,
	linux-arm-kernel, linux-kernel, linux-um, linux-edac, amd-gfx,
	dri-devel, linux-arm-msm, freedreno, linux-hwmon, linux-input,
	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, stable
  Cc: jonnyc, Arnd Bergmann, Christoph Hellwig, Dan Carpenter,
	Jens Axboe, Lorenzo Stoakes, Mateusz Guzik, Pedro Falcato
In-Reply-To: <20250919101727.16152-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


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox