* [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation
@ 2026-05-05 4:59 Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 02/20] Input: rmi4 - refactor register descriptor parsing Dmitry Torokhov
` (18 more replies)
0 siblings, 19 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel, stable
When reading the register descriptor, the base address is incremented by
1 to read the presence register block. However, after reading the
presence register block, the address is incorrectly incremented by only
1 byte (++addr) instead of the actual size of the presence block
(size_presence_reg). This causes the subsequent structure block read to
read from the wrong memory location if the presence block is larger than
1 byte.
Fix this by advancing the address by size_presence_reg.
Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI4 devices")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
v2 of the series: added a bunch of new patches.
drivers/input/rmi4/rmi_driver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index ccd9338a44db..06f5e3000cf0 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -594,7 +594,7 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
ret = rmi_read_block(d, addr, buf, size_presence_reg);
if (ret)
return ret;
- ++addr;
+ addr += size_presence_reg;
if (buf[0] == 0) {
presense_offset = 3;
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 02/20] Input: rmi4 - refactor register descriptor parsing
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 03/20] Input: rmi4 - fix type overflow in register counts Dmitry Torokhov
` (17 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel, stable
Factor out parsing a register descriptor item from
rmi_read_register_desc() and ensure there are no out-of-bounds accesses.
Use get_unaligned_le16() and get_unaligned_le32() for reading multi-byte
values.
Reported-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI4 devices")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_driver.c | 124 +++++++++++++++++++-------------
1 file changed, 76 insertions(+), 48 deletions(-)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index 06f5e3000cf0..75949fb1a922 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -22,6 +22,7 @@
#include <uapi/linux/input.h>
#include <linux/rmi.h>
#include <linux/export.h>
+#include <linux/unaligned.h>
#include "rmi_bus.h"
#include "rmi_driver.h"
@@ -558,30 +559,74 @@ int rmi_scan_pdt(struct rmi_device *rmi_dev, void *ctx,
return retval < 0 ? retval : 0;
}
+static int rmi_parse_register_desc_item(struct rmi_register_desc_item *item,
+ const u8 *buf, size_t size)
+{
+ unsigned int offset = 0;
+ unsigned int map_offset = 0;
+ int b;
+
+ if (offset >= size)
+ return -EIO;
+
+ item->reg_size = buf[offset++];
+ if (item->reg_size == 0) {
+ if (size - offset < 2)
+ return -EIO;
+ item->reg_size = get_unaligned_le16(&buf[offset]);
+ offset += 2;
+ }
+
+ if (item->reg_size == 0) {
+ if (size - offset < 4)
+ return -EIO;
+ item->reg_size = get_unaligned_le32(&buf[offset]);
+ offset += 4;
+ }
+
+ do {
+ if (offset >= size)
+ return -EIO;
+
+ for (b = 0; b < 7; b++) {
+ if (buf[offset] & BIT(b)) {
+ if (map_offset >= RMI_REG_DESC_SUBPACKET_BITS)
+ return -EIO;
+ __set_bit(map_offset, item->subpacket_map);
+ }
+ ++map_offset;
+ }
+ } while (buf[offset++] & BIT(7));
+
+ item->num_subpackets = bitmap_weight(item->subpacket_map,
+ RMI_REG_DESC_SUBPACKET_BITS);
+
+ return offset;
+}
+
int rmi_read_register_desc(struct rmi_device *d, u16 addr,
- struct rmi_register_descriptor *rdesc)
+ struct rmi_register_descriptor *rdesc)
{
int ret;
u8 size_presence_reg;
u8 buf[35];
- int presense_offset = 1;
- u8 *struct_buf;
- int reg;
- int offset = 0;
- int map_offset = 0;
+ unsigned int presence_offset;
+ unsigned int map_offset;
+ unsigned int offset;
+ unsigned int reg;
int i;
int b;
/*
* The first register of the register descriptor is the size of
- * the register descriptor's presense register.
+ * the register descriptor's presence register.
*/
ret = rmi_read(d, addr, &size_presence_reg);
if (ret)
return ret;
++addr;
- if (size_presence_reg < 0 || size_presence_reg > 35)
+ if (size_presence_reg < 1 || size_presence_reg > 35)
return -EIO;
memset(buf, 0, sizeof(buf));
@@ -597,16 +642,23 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
addr += size_presence_reg;
if (buf[0] == 0) {
- presense_offset = 3;
- rdesc->struct_size = buf[1] | (buf[2] << 8);
+ if (size_presence_reg < 3)
+ return -EIO;
+ presence_offset = 3;
+ rdesc->struct_size = get_unaligned_le16(&buf[1]);
} else {
+ presence_offset = 1;
rdesc->struct_size = buf[0];
}
- for (i = presense_offset; i < size_presence_reg; i++) {
+ map_offset = 0;
+ for (i = presence_offset; i < size_presence_reg; i++) {
for (b = 0; b < 8; b++) {
- if (buf[i] & (0x1 << b))
+ if (buf[i] & BIT(b)) {
+ if (map_offset >= RMI_REG_DESC_PRESENSE_BITS)
+ return -EIO;
bitmap_set(rdesc->presense_map, map_offset, 1);
+ }
++map_offset;
}
}
@@ -626,7 +678,7 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
* I'm not using devm_kzalloc here since it will not be retained
* after exiting this function
*/
- struct_buf = kzalloc(rdesc->struct_size, GFP_KERNEL);
+ u8 *struct_buf __free(kfree) = kzalloc(rdesc->struct_size, GFP_KERNEL);
if (!struct_buf)
return -ENOMEM;
@@ -638,56 +690,32 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
*/
ret = rmi_read_block(d, addr, struct_buf, rdesc->struct_size);
if (ret)
- goto free_struct_buff;
+ return ret;
reg = find_first_bit(rdesc->presense_map, RMI_REG_DESC_PRESENSE_BITS);
+ offset = 0;
for (i = 0; i < rdesc->num_registers; i++) {
struct rmi_register_desc_item *item = &rdesc->registers[i];
- int reg_size = struct_buf[offset];
-
- ++offset;
- if (reg_size == 0) {
- reg_size = struct_buf[offset] |
- (struct_buf[offset + 1] << 8);
- offset += 2;
- }
+ int item_size;
- if (reg_size == 0) {
- reg_size = struct_buf[offset] |
- (struct_buf[offset + 1] << 8) |
- (struct_buf[offset + 2] << 16) |
- (struct_buf[offset + 3] << 24);
- offset += 4;
- }
+ item_size = rmi_parse_register_desc_item(item,
+ &struct_buf[offset],
+ rdesc->struct_size - offset);
+ if (item_size < 0)
+ return item_size;
item->reg = reg;
- item->reg_size = reg_size;
-
- map_offset = 0;
-
- do {
- for (b = 0; b < 7; b++) {
- if (struct_buf[offset] & (0x1 << b))
- bitmap_set(item->subpacket_map,
- map_offset, 1);
- ++map_offset;
- }
- } while (struct_buf[offset++] & 0x80);
-
- item->num_subpackets = bitmap_weight(item->subpacket_map,
- RMI_REG_DESC_SUBPACKET_BITS);
+ offset += item_size;
rmi_dbg(RMI_DEBUG_CORE, &d->dev,
"%s: reg: %d reg size: %ld subpackets: %d\n", __func__,
item->reg, item->reg_size, item->num_subpackets);
reg = find_next_bit(rdesc->presense_map,
- RMI_REG_DESC_PRESENSE_BITS, reg + 1);
+ RMI_REG_DESC_PRESENSE_BITS, reg + 1);
}
-free_struct_buff:
- kfree(struct_buf);
- return ret;
+ return 0;
}
const struct rmi_register_desc_item *rmi_get_register_desc_item(
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 03/20] Input: rmi4 - fix type overflow in register counts
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 02/20] Input: rmi4 - refactor register descriptor parsing Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 04/20] Input: rmi4 - fix num_subpackets overflow in register descriptor Dmitry Torokhov
` (16 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel, stable
The number of registers in the RMI4 register descriptor is populated
by counting the bits in the presence map using bitmap_weight(). Since
the presence map can contain up to 256 bits (RMI_REG_DESC_PRESENSE_BITS),
storing this count in a u8 can overflow to 0 if all 256 bits are set.
Change the num_registers field in struct rmi_register_descriptor
from u8 to u16 to prevent potential integer overflow and ensure safe
processing of devices reporting large descriptors.
Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI4 devices")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_driver.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index e84495caab15..5f769fcc758d 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -65,7 +65,7 @@ struct rmi_register_desc_item {
struct rmi_register_descriptor {
unsigned long struct_size;
unsigned long presense_map[BITS_TO_LONGS(RMI_REG_DESC_PRESENSE_BITS)];
- u8 num_registers;
+ u16 num_registers;
struct rmi_register_desc_item *registers;
};
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 04/20] Input: rmi4 - fix num_subpackets overflow in register descriptor
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 02/20] Input: rmi4 - refactor register descriptor parsing Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 03/20] Input: rmi4 - fix type overflow in register counts Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 05/20] Input: rmi4 - fix memory leak in rmi_set_attn_data() Dmitry Torokhov
` (15 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel, stable
RMI_REG_DESC_SUBPACKET_BITS is defined as 296 (37 * BITS_PER_BYTE). This
may overflow num_subpackets in struct rmi_register_desc_item which is
defined as a u8.
Fix this by changing the type of num_subpackets to u16.
Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI4 devices")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_driver.h | 2 +-
drivers/input/rmi4/rmi_f12.c | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index 5f769fcc758d..6952059bf4f5 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -53,7 +53,7 @@ struct pdt_entry {
struct rmi_register_desc_item {
u16 reg;
unsigned long reg_size;
- u8 num_subpackets;
+ u16 num_subpackets;
unsigned long subpacket_map[BITS_TO_LONGS(
RMI_REG_DESC_SUBPACKET_BITS)];
};
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 8246fe77114b..c2b07c6905d7 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -467,6 +467,13 @@ static int rmi_f12_probe(struct rmi_function *fn)
f12->data1 = item;
f12->data1_offset = data_offset;
data_offset += item->reg_size;
+
+ if (item->num_subpackets > 255) {
+ dev_err(&fn->dev, "Too many fingers declared: %d\n",
+ item->num_subpackets);
+ return -EINVAL;
+ }
+
sensor->nbr_fingers = item->num_subpackets;
sensor->report_abs = 1;
sensor->attn_size += item->reg_size;
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 05/20] Input: rmi4 - fix memory leak in rmi_set_attn_data()
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (2 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 04/20] Input: rmi4 - fix num_subpackets overflow in register descriptor Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 06/20] Input: rmi4 - iterative IRQ handler Dmitry Torokhov
` (14 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel, stable
kfifo_put() returns 0 if the FIFO is full. In this case, we must
free the memory allocated for the attention data to avoid a leak.
Fixes: b908d3cd812a ("Input: synaptics-rmi4 - allow to add attention data")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_driver.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index 75949fb1a922..d873c7f08e42 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -183,7 +183,11 @@ void rmi_set_attn_data(struct rmi_device *rmi_dev, unsigned long irq_status,
attn_data.size = size;
attn_data.data = fifo_data;
- kfifo_put(&drvdata->attn_fifo, attn_data);
+ if (!kfifo_put(&drvdata->attn_fifo, attn_data)) {
+ dev_warn_ratelimited(&rmi_dev->dev,
+ "Failed to enqueue attention data, FIFO full\n");
+ kfree(fifo_data);
+ }
}
EXPORT_SYMBOL_GPL(rmi_set_attn_data);
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 06/20] Input: rmi4 - iterative IRQ handler
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (3 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 05/20] Input: rmi4 - fix memory leak in rmi_set_attn_data() Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 07/20] Input: rmi4 - fix bit count in bitmap_copy() Dmitry Torokhov
` (13 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel, stable
The current IRQ handler uses recursion to drain the attention FIFO,
which can lead to stack overflow on deep queues. Convert it to a
loop.
Fixes: b908d3cd812a ("Input: synaptics-rmi4 - allow to add attention data")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_driver.c | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index d873c7f08e42..c2843c21f0b9 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -198,24 +198,24 @@ static irqreturn_t rmi_irq_fn(int irq, void *dev_id)
struct rmi4_attn_data attn_data = {0};
int ret, count;
- count = kfifo_get(&drvdata->attn_fifo, &attn_data);
- if (count) {
- *(drvdata->irq_status) = attn_data.irq_status;
- drvdata->attn_data = attn_data;
- }
-
- ret = rmi_process_interrupt_requests(rmi_dev);
- if (ret)
- rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
- "Failed to process interrupt request: %d\n", ret);
+ do {
+ count = kfifo_get(&drvdata->attn_fifo, &attn_data);
+ if (count) {
+ *drvdata->irq_status = attn_data.irq_status;
+ drvdata->attn_data = attn_data;
+ }
- if (count) {
- kfree(attn_data.data);
- drvdata->attn_data.data = NULL;
- }
+ ret = rmi_process_interrupt_requests(rmi_dev);
+ if (ret)
+ rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev,
+ "Failed to process interrupt request: %d\n",
+ ret);
- if (!kfifo_is_empty(&drvdata->attn_fifo))
- return rmi_irq_fn(irq, dev_id);
+ if (count) {
+ kfree(attn_data.data);
+ drvdata->attn_data.data = NULL;
+ }
+ } while (!kfifo_is_empty(&drvdata->attn_fifo));
return IRQ_HANDLED;
}
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 07/20] Input: rmi4 - fix bit count in bitmap_copy()
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (4 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 06/20] Input: rmi4 - iterative IRQ handler Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 08/20] Input: rmi4 - fix limit in rmi_register_desc_has_subpacket() Dmitry Torokhov
` (12 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel, stable
bitmap_copy() takes number of bits, not bytes (or longs). Correct
the bit count in rmi_driver_set_irq_bits() and
rmi_driver_clear_irq_bits().
Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI4 devices")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_driver.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index c2843c21f0b9..ebff1ce07e58 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -388,9 +388,8 @@ static int rmi_driver_set_irq_bits(struct rmi_device *rmi_dev,
__func__);
goto error_unlock;
}
- bitmap_copy(data->current_irq_mask, data->new_irq_mask,
- data->num_of_irq_regs);
+ bitmap_copy(data->current_irq_mask, data->new_irq_mask, data->irq_count);
bitmap_or(data->fn_irq_bits, data->fn_irq_bits, mask, data->irq_count);
error_unlock:
@@ -419,8 +418,8 @@ static int rmi_driver_clear_irq_bits(struct rmi_device *rmi_dev,
__func__);
goto error_unlock;
}
- bitmap_copy(data->current_irq_mask, data->new_irq_mask,
- data->num_of_irq_regs);
+
+ bitmap_copy(data->current_irq_mask, data->new_irq_mask, data->irq_count);
error_unlock:
mutex_unlock(&data->irq_mutex);
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 08/20] Input: rmi4 - fix limit in rmi_register_desc_has_subpacket()
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (5 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 07/20] Input: rmi4 - fix bit count in bitmap_copy() Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 09/20] Input: rmi4 - use local presence map in rmi_read_register_desc() Dmitry Torokhov
` (11 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel
rmi_register_desc_has_subpacket() should use RMI_REG_DESC_SUBPACKET_BITS,
not RMI_REG_DESC_PRESENCE_BITS, as the limit for subpacket_map.
Fixes: 2b6a321da9a2 ("Input: synaptics-rmi4 - add support for Synaptics RMI4 devices")
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_driver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index ebff1ce07e58..84cf7df705f9 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -769,7 +769,7 @@ int rmi_register_desc_calc_reg_offset(
bool rmi_register_desc_has_subpacket(const struct rmi_register_desc_item *item,
u8 subpacket)
{
- return find_next_bit(item->subpacket_map, RMI_REG_DESC_PRESENSE_BITS,
+ return find_next_bit(item->subpacket_map, RMI_REG_DESC_SUBPACKET_BITS,
subpacket) == subpacket;
}
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 09/20] Input: rmi4 - use local presence map in rmi_read_register_desc()
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (6 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 08/20] Input: rmi4 - fix limit in rmi_register_desc_has_subpacket() Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 10/20] Input: rmi4 - refactor function allocation and registration Dmitry Torokhov
` (10 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel
The presence map is only used during the parsing of the register
descriptor, so we can make it a local variable instead of storing it
in struct rmi_register_descriptor.
Also fix the spelling of the constant and the variable name (presence
instead of presense).
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_driver.c | 22 ++++++++++++----------
drivers/input/rmi4/rmi_driver.h | 4 ++--
2 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index 84cf7df705f9..6755dd66d62f 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -610,15 +610,16 @@ static int rmi_parse_register_desc_item(struct rmi_register_desc_item *item,
int rmi_read_register_desc(struct rmi_device *d, u16 addr,
struct rmi_register_descriptor *rdesc)
{
- int ret;
+ DECLARE_BITMAP(presence_map, RMI_REG_DESC_PRESENCE_BITS);
+ u8 buf[RMI_REG_DESC_PRESENCE_REGS_MAX];
u8 size_presence_reg;
- u8 buf[35];
unsigned int presence_offset;
unsigned int map_offset;
unsigned int offset;
unsigned int reg;
int i;
int b;
+ int ret;
/*
* The first register of the register descriptor is the size of
@@ -629,7 +630,7 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
return ret;
++addr;
- if (size_presence_reg < 1 || size_presence_reg > 35)
+ if (size_presence_reg < 1 || size_presence_reg > RMI_REG_DESC_PRESENCE_REGS_MAX)
return -EIO;
memset(buf, 0, sizeof(buf));
@@ -654,20 +655,21 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
rdesc->struct_size = buf[0];
}
+ memset(presence_map, 0, sizeof(presence_map));
map_offset = 0;
for (i = presence_offset; i < size_presence_reg; i++) {
for (b = 0; b < 8; b++) {
if (buf[i] & BIT(b)) {
- if (map_offset >= RMI_REG_DESC_PRESENSE_BITS)
+ if (map_offset >= RMI_REG_DESC_PRESENCE_BITS)
return -EIO;
- bitmap_set(rdesc->presense_map, map_offset, 1);
+ bitmap_set(presence_map, map_offset, 1);
}
++map_offset;
}
}
- rdesc->num_registers = bitmap_weight(rdesc->presense_map,
- RMI_REG_DESC_PRESENSE_BITS);
+ rdesc->num_registers = bitmap_weight(presence_map,
+ RMI_REG_DESC_PRESENCE_BITS);
rdesc->registers = devm_kcalloc(&d->dev,
rdesc->num_registers,
@@ -695,7 +697,7 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
if (ret)
return ret;
- reg = find_first_bit(rdesc->presense_map, RMI_REG_DESC_PRESENSE_BITS);
+ reg = find_first_bit(presence_map, RMI_REG_DESC_PRESENCE_BITS);
offset = 0;
for (i = 0; i < rdesc->num_registers; i++) {
struct rmi_register_desc_item *item = &rdesc->registers[i];
@@ -714,8 +716,8 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
"%s: reg: %d reg size: %ld subpackets: %d\n", __func__,
item->reg, item->reg_size, item->num_subpackets);
- reg = find_next_bit(rdesc->presense_map,
- RMI_REG_DESC_PRESENSE_BITS, reg + 1);
+ reg = find_next_bit(presence_map,
+ RMI_REG_DESC_PRESENCE_BITS, reg + 1);
}
return 0;
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index 6952059bf4f5..b93905a6a43a 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -46,7 +46,8 @@ struct pdt_entry {
u8 function_number;
};
-#define RMI_REG_DESC_PRESENSE_BITS (32 * BITS_PER_BYTE)
+#define RMI_REG_DESC_PRESENCE_BITS (32 * BITS_PER_BYTE)
+#define RMI_REG_DESC_PRESENCE_REGS_MAX (3 + RMI_REG_DESC_PRESENCE_BITS / 8)
#define RMI_REG_DESC_SUBPACKET_BITS (37 * BITS_PER_BYTE)
/* describes a single packet register */
@@ -64,7 +65,6 @@ struct rmi_register_desc_item {
*/
struct rmi_register_descriptor {
unsigned long struct_size;
- unsigned long presense_map[BITS_TO_LONGS(RMI_REG_DESC_PRESENSE_BITS)];
u16 num_registers;
struct rmi_register_desc_item *registers;
};
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 10/20] Input: rmi4 - refactor function allocation and registration
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (7 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 09/20] Input: rmi4 - use local presence map in rmi_read_register_desc() Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 11/20] Input: rmi4 - use kzalloc_flex() for struct rmi_function Dmitry Torokhov
` (9 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel
Currently, rmi_create_function() allocates memory for the rmi_function
structure, but rmi_register_function() initializes the device via
device_initialize(). This split of ownership makes error handling in
rmi_create_function() confusing because the caller must be aware that
if rmi_register_function() fails, it has already called put_device() to
clean up the memory.
To make the memory lifecycle explicit and fix potential leaks cleanly
introduce rmi_alloc_function() to handle memory allocation and device
initialization, and make the caller of rmi_register_function()
responsible for cleanup.
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_bus.c | 32 +++++++++++++++++++++-----------
drivers/input/rmi4/rmi_bus.h | 1 +
drivers/input/rmi4/rmi_driver.c | 10 ++++------
3 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index 687cb987bc13..71a25df73984 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -237,36 +237,46 @@ static int rmi_function_remove(struct device *dev)
return 0;
}
-int rmi_register_function(struct rmi_function *fn)
+struct rmi_function *rmi_alloc_function(struct rmi_device *rmi_dev, u8 id)
{
- struct rmi_device *rmi_dev = fn->rmi_dev;
- int error;
+ struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
+ struct rmi_function *fn;
+
+ fn = kzalloc(sizeof(*fn) +
+ BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!fn)
+ return NULL;
device_initialize(&fn->dev);
- dev_set_name(&fn->dev, "%s.fn%02x",
- dev_name(&rmi_dev->dev), fn->fd.function_number);
+ dev_set_name(&fn->dev, "%s.fn%02x", dev_name(&rmi_dev->dev), id);
fn->dev.parent = &rmi_dev->dev;
fn->dev.type = &rmi_function_type;
fn->dev.bus = &rmi_bus_type;
+ fn->rmi_dev = rmi_dev;
+
+ return fn;
+}
+
+int rmi_register_function(struct rmi_function *fn)
+{
+ struct rmi_device *rmi_dev = fn->rmi_dev;
+ int error;
error = device_add(&fn->dev);
if (error) {
dev_err(&rmi_dev->dev,
- "Failed device_register function device %s\n",
+ "Failed to register function device %s\n",
dev_name(&fn->dev));
- goto err_put_device;
+ return error;
}
rmi_dbg(RMI_DEBUG_CORE, &rmi_dev->dev, "Registered F%02X.\n",
fn->fd.function_number);
return 0;
-
-err_put_device:
- put_device(&fn->dev);
- return error;
}
void rmi_unregister_function(struct rmi_function *fn)
diff --git a/drivers/input/rmi4/rmi_bus.h b/drivers/input/rmi4/rmi_bus.h
index d4d0d82c69aa..90122df21f74 100644
--- a/drivers/input/rmi4/rmi_bus.h
+++ b/drivers/input/rmi4/rmi_bus.h
@@ -49,6 +49,7 @@ struct rmi_function {
bool rmi_is_function_device(struct device *dev);
+struct rmi_function *rmi_alloc_function(struct rmi_device *rmi_dev, u8 id);
int __must_check rmi_register_function(struct rmi_function *);
void rmi_unregister_function(struct rmi_function *);
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index 6755dd66d62f..aae4a9bb76fb 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -872,9 +872,7 @@ static int rmi_create_function(struct rmi_device *rmi_dev,
rmi_dbg(RMI_DEBUG_CORE, dev, "Initializing F%02X.\n",
pdt->function_number);
- fn = kzalloc(sizeof(struct rmi_function) +
- BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long),
- GFP_KERNEL);
+ fn = rmi_alloc_function(rmi_dev, pdt->function_number);
if (!fn) {
dev_err(dev, "Failed to allocate memory for F%02X\n",
pdt->function_number);
@@ -884,8 +882,6 @@ static int rmi_create_function(struct rmi_device *rmi_dev,
INIT_LIST_HEAD(&fn->node);
rmi_driver_copy_pdt_to_fd(pdt, &fn->fd);
- fn->rmi_dev = rmi_dev;
-
fn->num_of_irqs = pdt->interrupt_source_count;
fn->irq_pos = *current_irq_count;
*current_irq_count += fn->num_of_irqs;
@@ -894,8 +890,10 @@ static int rmi_create_function(struct rmi_device *rmi_dev,
set_bit(fn->irq_pos + i, fn->irq_mask);
error = rmi_register_function(fn);
- if (error)
+ if (error) {
+ put_device(&fn->dev);
return error;
+ }
if (pdt->function_number == 0x01)
data->f01_container = fn;
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 11/20] Input: rmi4 - use kzalloc_flex() for struct rmi_function
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (8 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 10/20] Input: rmi4 - refactor function allocation and registration Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 12/20] Input: rmi4 - refactor F12 probe function Dmitry Torokhov
` (8 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel
struct rmi_function contains a flexible array member irq_mask.
Convert the manual kzalloc size calculation to use the kzalloc_flex()
macro.
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_bus.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/input/rmi4/rmi_bus.c b/drivers/input/rmi4/rmi_bus.c
index 71a25df73984..64d5cb72e113 100644
--- a/drivers/input/rmi4/rmi_bus.c
+++ b/drivers/input/rmi4/rmi_bus.c
@@ -242,9 +242,7 @@ struct rmi_function *rmi_alloc_function(struct rmi_device *rmi_dev, u8 id)
struct rmi_driver_data *data = dev_get_drvdata(&rmi_dev->dev);
struct rmi_function *fn;
- fn = kzalloc(sizeof(*fn) +
- BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long),
- GFP_KERNEL);
+ fn = kzalloc_flex(*fn, irq_mask, BITS_TO_LONGS(data->irq_count));
if (!fn)
return NULL;
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 12/20] Input: rmi4 - refactor F12 probe function
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (9 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 11/20] Input: rmi4 - use kzalloc_flex() for struct rmi_function Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 13/20] Input: rmi4 - change reg_size type to u32 Dmitry Torokhov
` (7 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel
The F12 probe function contains highly repetitive logic for parsing
register descriptors and their individual data items. Refactor the
function to use loops to eliminate redundancy, and clarify the code.
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_f12.c | 197 ++++++++++++++---------------------
1 file changed, 81 insertions(+), 116 deletions(-)
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index c2b07c6905d7..973288103b6a 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -61,6 +61,36 @@ struct f12_data {
unsigned long *rel_mask;
};
+static int rmi_f12_read_register_descs(struct rmi_function *fn,
+ struct f12_data *f12, u16 query_addr)
+{
+ struct {
+ struct rmi_register_descriptor *desc;
+ const char *name;
+ } descriptors[] = {
+ { &f12->query_reg_desc, "Query" },
+ { &f12->control_reg_desc, "Control" },
+ { &f12->data_reg_desc, "Data" },
+ };
+ struct rmi_device *rmi_dev = fn->rmi_dev;
+ int error;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(descriptors); i++) {
+ error = rmi_read_register_desc(rmi_dev, query_addr,
+ descriptors[i].desc);
+ if (error) {
+ dev_err(&fn->dev,
+ "Failed to read the %s Register Descriptor: %d\n",
+ descriptors[i].name, error);
+ return error;
+ }
+ query_addr += 3;
+ }
+
+ return 0;
+}
+
static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
{
const struct rmi_register_desc_item *item;
@@ -351,6 +381,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
u16 data_offset = 0;
int mask_size;
+ int i;
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s\n", __func__);
@@ -393,35 +424,9 @@ static int rmi_f12_probe(struct rmi_function *fn)
f12->sensor_pdata = pdata->sensor_pdata;
}
- ret = rmi_read_register_desc(rmi_dev, query_addr,
- &f12->query_reg_desc);
- if (ret) {
- dev_err(&fn->dev,
- "Failed to read the Query Register Descriptor: %d\n",
- ret);
- return ret;
- }
- query_addr += 3;
-
- ret = rmi_read_register_desc(rmi_dev, query_addr,
- &f12->control_reg_desc);
- if (ret) {
- dev_err(&fn->dev,
- "Failed to read the Control Register Descriptor: %d\n",
- ret);
- return ret;
- }
- query_addr += 3;
-
- ret = rmi_read_register_desc(rmi_dev, query_addr,
- &f12->data_reg_desc);
- if (ret) {
- dev_err(&fn->dev,
- "Failed to read the Data Register Descriptor: %d\n",
- ret);
+ ret = rmi_f12_read_register_descs(fn, f12, query_addr);
+ if (ret)
return ret;
- }
- query_addr += 3;
sensor = &f12->sensor;
sensor->fn = fn;
@@ -452,101 +457,61 @@ static int rmi_f12_probe(struct rmi_function *fn)
return ret;
/*
- * Figure out what data is contained in the data registers. HID devices
- * may have registers defined, but their data is not reported in the
- * HID attention report. Registers which are not reported in the HID
- * attention report check to see if the device is receiving data from
- * HID attention reports.
+ * Identify available data registers and calculate their offsets within
+ * the attention report. For HID devices, only Data1 and Data5 are
+ * included in the report; other registers may be described but are
+ * not transmitted in the attention packet and thus skipped here.
*/
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 0);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 1);
- if (item) {
- f12->data1 = item;
- f12->data1_offset = data_offset;
- data_offset += item->reg_size;
-
- if (item->num_subpackets > 255) {
- dev_err(&fn->dev, "Too many fingers declared: %d\n",
- item->num_subpackets);
- return -EINVAL;
- }
-
- sensor->nbr_fingers = item->num_subpackets;
- sensor->report_abs = 1;
- sensor->attn_size += item->reg_size;
- }
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 2);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 3);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 4);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 5);
- if (item) {
- f12->data5 = item;
- f12->data5_offset = data_offset;
- data_offset += item->reg_size;
- sensor->attn_size += item->reg_size;
- }
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 6);
- if (item && !drvdata->attn_data.data) {
- f12->data6 = item;
- f12->data6_offset = data_offset;
- data_offset += item->reg_size;
- }
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 7);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 8);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
-
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 9);
- if (item && !drvdata->attn_data.data) {
- f12->data9 = item;
- f12->data9_offset = data_offset;
- data_offset += item->reg_size;
- if (!sensor->report_abs)
- sensor->report_rel = 1;
- }
+ for (i = 0; i < 16; i++) {
+ item = rmi_get_register_desc_item(&f12->data_reg_desc, i);
+ if (!item)
+ continue;
+
+ /* HID attention reports only contain Data1 and Data5 */
+ if (drvdata->attn_data.data && i != 1 && i != 5)
+ continue;
+
+ switch (i) {
+ case 1:
+ f12->data1 = item;
+ f12->data1_offset = data_offset;
+
+ if (item->num_subpackets > 255) {
+ dev_err(&fn->dev,
+ "Too many fingers declared: %d\n",
+ item->num_subpackets);
+ return -EINVAL;
+ }
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 10);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
+ sensor->nbr_fingers = item->num_subpackets;
+ sensor->report_abs = 1;
+ sensor->attn_size += item->reg_size;
+ break;
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 11);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
+ case 5:
+ f12->data5 = item;
+ f12->data5_offset = data_offset;
+ sensor->attn_size += item->reg_size;
+ break;
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 12);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
+ case 6:
+ f12->data6 = item;
+ f12->data6_offset = data_offset;
+ break;
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 13);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
+ case 9:
+ f12->data9 = item;
+ f12->data9_offset = data_offset;
+ if (!sensor->report_abs)
+ sensor->report_rel = 1;
+ break;
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 14);
- if (item && !drvdata->attn_data.data)
- data_offset += item->reg_size;
+ case 15:
+ f12->data15 = item;
+ f12->data15_offset = data_offset;
+ break;
+ }
- item = rmi_get_register_desc_item(&f12->data_reg_desc, 15);
- if (item && !drvdata->attn_data.data) {
- f12->data15 = item;
- f12->data15_offset = data_offset;
data_offset += item->reg_size;
}
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 13/20] Input: rmi4 - change reg_size type to u32
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (10 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 12/20] Input: rmi4 - refactor F12 probe function Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 14/20] Input: rmi4 - use unaligned access helpers in F12 Dmitry Torokhov
` (6 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel
Change reg_size from unsigned long to u32 to save space and ensure
consistent size across 32-bit and 64-bit architectures, and use
DECLARE_BITMAP() for subpacket_map.
Also pack the structure by rearranging the members to avoid holes,
and use size_add() to prevent potential integer overflows when
calculating the total size of registers.
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_2d_sensor.h | 4 ++--
drivers/input/rmi4/rmi_driver.c | 4 ++--
drivers/input/rmi4/rmi_driver.h | 5 ++---
drivers/input/rmi4/rmi_f11.c | 2 +-
drivers/input/rmi4/rmi_f12.c | 25 +++++++++++++++++++------
5 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/drivers/input/rmi4/rmi_2d_sensor.h b/drivers/input/rmi4/rmi_2d_sensor.h
index 61a99c8a7a26..f9d9c1dd5eb0 100644
--- a/drivers/input/rmi4/rmi_2d_sensor.h
+++ b/drivers/input/rmi4/rmi_2d_sensor.h
@@ -56,8 +56,8 @@ struct rmi_2d_sensor {
u16 max_y;
u8 nbr_fingers;
u8 *data_pkt;
- int pkt_size;
- int attn_size;
+ u32 pkt_size;
+ u32 attn_size;
bool topbuttonpad;
enum rmi_sensor_type sensor_type;
struct input_dev *input;
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index aae4a9bb76fb..6416c1d97a6d 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -713,7 +713,7 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
offset += item_size;
rmi_dbg(RMI_DEBUG_CORE, &d->dev,
- "%s: reg: %d reg size: %ld subpackets: %d\n", __func__,
+ "%s: reg: %d reg size: %u subpackets: %d\n", __func__,
item->reg, item->reg_size, item->num_subpackets);
reg = find_next_bit(presence_map,
@@ -746,7 +746,7 @@ size_t rmi_register_desc_calc_size(struct rmi_register_descriptor *rdesc)
for (i = 0; i < rdesc->num_registers; i++) {
item = &rdesc->registers[i];
- size += item->reg_size;
+ size = size_add(size, item->reg_size);
}
return size;
}
diff --git a/drivers/input/rmi4/rmi_driver.h b/drivers/input/rmi4/rmi_driver.h
index b93905a6a43a..abeafb77a483 100644
--- a/drivers/input/rmi4/rmi_driver.h
+++ b/drivers/input/rmi4/rmi_driver.h
@@ -52,11 +52,10 @@ struct pdt_entry {
/* describes a single packet register */
struct rmi_register_desc_item {
+ u32 reg_size;
u16 reg;
- unsigned long reg_size;
u16 num_subpackets;
- unsigned long subpacket_map[BITS_TO_LONGS(
- RMI_REG_DESC_SUBPACKET_BITS)];
+ DECLARE_BITMAP(subpacket_map, RMI_REG_DESC_SUBPACKET_BITS);
};
/*
diff --git a/drivers/input/rmi4/rmi_f11.c b/drivers/input/rmi4/rmi_f11.c
index 49ca9168685a..9ade74b36edb 100644
--- a/drivers/input/rmi4/rmi_f11.c
+++ b/drivers/input/rmi4/rmi_f11.c
@@ -1304,7 +1304,7 @@ static irqreturn_t rmi_f11_attention(int irq, void *ctx)
struct f11_data *f11 = dev_get_drvdata(&fn->dev);
u16 data_base_addr = fn->fd.data_base_addr;
int error;
- int valid_bytes = f11->sensor.pkt_size;
+ u32 valid_bytes = f11->sensor.pkt_size;
if (drvdata->attn_data.data) {
/*
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 973288103b6a..b179980003f1 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -5,6 +5,7 @@
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/rmi.h>
+#include <linux/sizes.h>
#include "rmi_driver.h"
#include "rmi_2d_sensor.h"
@@ -118,7 +119,7 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
if (item->reg_size > sizeof(buf)) {
dev_err(&fn->dev,
- "F12 control8 should be no bigger than %zd bytes, not: %ld\n",
+ "F12 control8 should be no bigger than %zd bytes, not: %u\n",
sizeof(buf), item->reg_size);
return -ENODEV;
}
@@ -256,7 +257,7 @@ static irqreturn_t rmi_f12_attention(int irq, void *ctx)
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
struct f12_data *f12 = dev_get_drvdata(&fn->dev);
struct rmi_2d_sensor *sensor = &f12->sensor;
- int valid_bytes = sensor->pkt_size;
+ u32 valid_bytes = sensor->pkt_size;
if (drvdata->attn_data.data) {
if (sensor->attn_size > drvdata->attn_data.size)
@@ -310,7 +311,7 @@ static int rmi_f12_write_control_regs(struct rmi_function *fn)
* on the existence of subpacket 0. If control 20 is
* larger then 3 bytes, just read the first 3.
*/
- control_size = min(item->reg_size, 3UL);
+ control_size = min(item->reg_size, 3U);
ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr
+ control_offset, buf, control_size);
@@ -379,7 +380,8 @@ static int rmi_f12_probe(struct rmi_function *fn)
struct rmi_2d_sensor *sensor;
struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev);
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
- u16 data_offset = 0;
+ size_t data_offset = 0;
+ size_t pkt_size;
int mask_size;
int i;
@@ -431,7 +433,12 @@ static int rmi_f12_probe(struct rmi_function *fn)
sensor = &f12->sensor;
sensor->fn = fn;
f12->data_addr = fn->fd.data_base_addr;
- sensor->pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
+ pkt_size = rmi_register_desc_calc_size(&f12->data_reg_desc);
+ if (pkt_size > SZ_1M) {
+ dev_err(&fn->dev, "Invalid data packet size: %zu\n", pkt_size);
+ return -EINVAL;
+ }
+ sensor->pkt_size = pkt_size;
sensor->axis_align =
f12->sensor_pdata.axis_align;
@@ -444,7 +451,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
sensor->sensor_type =
f12->sensor_pdata.sensor_type;
- rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %d\n", __func__,
+ rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %u\n", __func__,
sensor->pkt_size);
sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
if (!sensor->data_pkt)
@@ -471,6 +478,12 @@ static int rmi_f12_probe(struct rmi_function *fn)
if (drvdata->attn_data.data && i != 1 && i != 5)
continue;
+ if (data_offset > U16_MAX) {
+ dev_err(&fn->dev, "Invalid offset for data%d: %zu\n",
+ i, data_offset);
+ return -EINVAL;
+ }
+
switch (i) {
case 1:
f12->data1 = item;
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 14/20] Input: rmi4 - use unaligned access helpers in F12
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (11 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 13/20] Input: rmi4 - change reg_size type to u32 Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 15/20] Input: rmi4 - use flexible array member for IRQ masks " Dmitry Torokhov
` (5 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel
Use get_unaligned_le16() instead of manual bit shifts to construct
16-bit values for max_x, max_y, pitch_x, pitch_y, and object
coordinates in the F12 parsing logic. This simplifies the code and
makes the endianness explicit.
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_f12.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index b179980003f1..752c1d137da0 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -6,6 +6,7 @@
#include <linux/input/mt.h>
#include <linux/rmi.h>
#include <linux/sizes.h>
+#include <linux/unaligned.h>
#include "rmi_driver.h"
#include "rmi_2d_sensor.h"
@@ -131,8 +132,8 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
offset = 0;
if (rmi_register_desc_has_subpacket(item, 0)) {
- sensor->max_x = (buf[offset + 1] << 8) | buf[offset];
- sensor->max_y = (buf[offset + 3] << 8) | buf[offset + 2];
+ sensor->max_x = get_unaligned_le16(&buf[offset]);
+ sensor->max_y = get_unaligned_le16(&buf[offset + 2]);
offset += 4;
}
@@ -140,8 +141,8 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
sensor->max_x, sensor->max_y);
if (rmi_register_desc_has_subpacket(item, 1)) {
- pitch_x = (buf[offset + 1] << 8) | buf[offset];
- pitch_y = (buf[offset + 3] << 8) | buf[offset + 2];
+ pitch_x = get_unaligned_le16(&buf[offset]);
+ pitch_y = get_unaligned_le16(&buf[offset + 2]);
offset += 4;
}
@@ -227,8 +228,8 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
break;
}
- obj->x = (data1[2] << 8) | data1[1];
- obj->y = (data1[4] << 8) | data1[3];
+ obj->x = get_unaligned_le16(&data1[1]);
+ obj->y = get_unaligned_le16(&data1[3]);
obj->z = data1[5];
obj->wx = data1[6];
obj->wy = data1[7];
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 15/20] Input: rmi4 - use flexible array member for IRQ masks in F12
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (12 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 14/20] Input: rmi4 - use unaligned access helpers in F12 Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 16/20] Input: rmi4 - use devm_kmalloc for F12 data packet buffer Dmitry Torokhov
` (4 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel
Use a flexible array member to allocate the IRQ masks at the end of
the f12_data structure, and use the struct_size() helper to
calculate the allocation size safely. This replaces manual pointer
arithmetic.
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_f12.c | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 752c1d137da0..b9cd70422b68 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -59,8 +59,7 @@ struct f12_data {
const struct rmi_register_desc_item *data15;
u16 data15_offset;
- unsigned long *abs_mask;
- unsigned long *rel_mask;
+ unsigned long irq_mask[];
};
static int rmi_f12_read_register_descs(struct rmi_function *fn,
@@ -350,17 +349,21 @@ static int rmi_f12_config(struct rmi_function *fn)
{
struct rmi_driver *drv = fn->rmi_dev->driver;
struct f12_data *f12 = dev_get_drvdata(&fn->dev);
+ struct rmi_driver_data *drvdata = dev_get_drvdata(&fn->rmi_dev->dev);
+ int irq_mask_size = BITS_TO_LONGS(drvdata->irq_count);
+ unsigned long *abs_mask = f12->irq_mask;
+ unsigned long *rel_mask = f12->irq_mask + irq_mask_size;
struct rmi_2d_sensor *sensor;
int ret;
sensor = &f12->sensor;
if (!sensor->report_abs)
- drv->clear_irq_bits(fn->rmi_dev, f12->abs_mask);
+ drv->clear_irq_bits(fn->rmi_dev, abs_mask);
else
- drv->set_irq_bits(fn->rmi_dev, f12->abs_mask);
+ drv->set_irq_bits(fn->rmi_dev, abs_mask);
- drv->clear_irq_bits(fn->rmi_dev, f12->rel_mask);
+ drv->clear_irq_bits(fn->rmi_dev, rel_mask);
ret = rmi_f12_write_control_regs(fn);
if (ret)
@@ -383,12 +386,12 @@ static int rmi_f12_probe(struct rmi_function *fn)
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
size_t data_offset = 0;
size_t pkt_size;
- int mask_size;
+ int irq_mask_size;
int i;
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s\n", __func__);
- mask_size = BITS_TO_LONGS(drvdata->irq_count) * sizeof(unsigned long);
+ irq_mask_size = BITS_TO_LONGS(drvdata->irq_count);
ret = rmi_read(fn->rmi_dev, query_addr, &buf);
if (ret < 0) {
@@ -404,18 +407,13 @@ static int rmi_f12_probe(struct rmi_function *fn)
return -ENODEV;
}
- f12 = devm_kzalloc(&fn->dev, sizeof(struct f12_data) + mask_size * 2,
- GFP_KERNEL);
+ f12 = devm_kzalloc(&fn->dev, struct_size(f12, irq_mask, irq_mask_size * 2),
+ GFP_KERNEL);
if (!f12)
return -ENOMEM;
- f12->abs_mask = (unsigned long *)((char *)f12
- + sizeof(struct f12_data));
- f12->rel_mask = (unsigned long *)((char *)f12
- + sizeof(struct f12_data) + mask_size);
-
- set_bit(fn->irq_pos, f12->abs_mask);
- set_bit(fn->irq_pos + 1, f12->rel_mask);
+ set_bit(fn->irq_pos, f12->irq_mask);
+ set_bit(fn->irq_pos + 1, f12->irq_mask + irq_mask_size);
f12->has_dribble = !!(buf & BIT(3));
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 16/20] Input: rmi4 - use devm_kmalloc for F12 data packet buffer
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (13 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 15/20] Input: rmi4 - use flexible array member for IRQ masks " Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 17/20] Input: rmi4 - use sizeof(*ptr) and idiomatic checks in f12 allocators Dmitry Torokhov
` (3 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel
The sensor->data_pkt buffer is used exclusively to store incoming
hardware data during the attention handler, where it is entirely
overwritten by either memcpy() or rmi_read_block(). Therefore,
there is no need to zero-initialize it during probe.
Switch to devm_kmalloc() to avoid the unnecessary memset overhead.
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_f12.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index b9cd70422b68..01838907c64b 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -452,7 +452,7 @@ static int rmi_f12_probe(struct rmi_function *fn)
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %u\n", __func__,
sensor->pkt_size);
- sensor->data_pkt = devm_kzalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
+ sensor->data_pkt = devm_kmalloc(&fn->dev, sensor->pkt_size, GFP_KERNEL);
if (!sensor->data_pkt)
return -ENOMEM;
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 17/20] Input: rmi4 - use sizeof(*ptr) and idiomatic checks in f12 allocators
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (14 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 16/20] Input: rmi4 - use devm_kmalloc for F12 data packet buffer Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 18/20] Input: rmi4 - simplify size calculations in F12 Dmitry Torokhov
` (2 subsequent siblings)
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel
Using sizeof(*ptr) is preferred over sizeof(struct) because it is
more robust against type changes. Also switch to checking for
allocation failure immediately after each call, and update
formatting.
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_f12.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 01838907c64b..34ed02b7f30f 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -528,16 +528,21 @@ static int rmi_f12_probe(struct rmi_function *fn)
}
/* allocate the in-kernel tracking buffers */
- sensor->tracking_pos = devm_kcalloc(&fn->dev,
- sensor->nbr_fingers, sizeof(struct input_mt_pos),
- GFP_KERNEL);
- sensor->tracking_slots = devm_kcalloc(&fn->dev,
- sensor->nbr_fingers, sizeof(int), GFP_KERNEL);
- sensor->objs = devm_kcalloc(&fn->dev,
- sensor->nbr_fingers,
- sizeof(struct rmi_2d_sensor_abs_object),
- GFP_KERNEL);
- if (!sensor->tracking_pos || !sensor->tracking_slots || !sensor->objs)
+ sensor->tracking_pos = devm_kcalloc(&fn->dev, sensor->nbr_fingers,
+ sizeof(*sensor->tracking_pos),
+ GFP_KERNEL);
+ if (!sensor->tracking_pos)
+ return -ENOMEM;
+
+ sensor->tracking_slots = devm_kcalloc(&fn->dev, sensor->nbr_fingers,
+ sizeof(*sensor->tracking_slots),
+ GFP_KERNEL);
+ if (!sensor->tracking_slots)
+ return -ENOMEM;
+
+ sensor->objs = devm_kcalloc(&fn->dev, sensor->nbr_fingers,
+ sizeof(*sensor->objs), GFP_KERNEL);
+ if (!sensor->objs)
return -ENOMEM;
ret = rmi_2d_sensor_configure_input(fn, sensor);
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 18/20] Input: rmi4 - simplify size calculations in F12
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (15 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 17/20] Input: rmi4 - use sizeof(*ptr) and idiomatic checks in f12 allocators Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 19/20] Input: rmi4 - propagate proper error code in F12 sensor tuning Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 20/20] Input: rmi4 - update formatting in F12 Dmitry Torokhov
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel
Use min_t() to simplify the clamping logic when calculating the
number of objects to process and the number of valid bytes in the
attention handler.
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_f12.c | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 34ed02b7f30f..ea72d5ce8050 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -195,14 +195,11 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
return 0;
}
-static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, int size)
+static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, u32 size)
{
- int i;
struct rmi_2d_sensor *sensor = &f12->sensor;
- int objects = f12->data1->num_subpackets;
-
- if ((f12->data1->num_subpackets * F12_DATA1_BYTES_PER_OBJ) > size)
- objects = size / F12_DATA1_BYTES_PER_OBJ;
+ u32 objects = min(f12->data1->num_subpackets, size / F12_DATA1_BYTES_PER_OBJ);
+ int i;
for (i = 0; i < objects; i++) {
struct rmi_2d_sensor_abs_object *obj = &sensor->objs[i];
@@ -260,10 +257,7 @@ static irqreturn_t rmi_f12_attention(int irq, void *ctx)
u32 valid_bytes = sensor->pkt_size;
if (drvdata->attn_data.data) {
- if (sensor->attn_size > drvdata->attn_data.size)
- valid_bytes = drvdata->attn_data.size;
- else
- valid_bytes = sensor->attn_size;
+ valid_bytes = min_t(u32, sensor->attn_size, drvdata->attn_data.size);
memcpy(sensor->data_pkt, drvdata->attn_data.data,
valid_bytes);
drvdata->attn_data.data += valid_bytes;
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 19/20] Input: rmi4 - propagate proper error code in F12 sensor tuning
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (16 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 18/20] Input: rmi4 - simplify size calculations in F12 Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 20/20] Input: rmi4 - update formatting in F12 Dmitry Torokhov
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel
Propagate the actual error code returned by rmi_read() in
rmi_f12_read_sensor_tuning() instead of hardcoding -ENODEV.
Also, since rmi_read() returns 0 on success, use 'if (ret)'
instead of 'if (ret < 0)'.
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_f12.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index ea72d5ce8050..bf8c4a0e10de 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -166,9 +166,9 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
RMI_F12_QUERY_RESOLUTION);
query_dpm_addr = fn->fd.query_base_addr + offset;
ret = rmi_read(fn->rmi_dev, query_dpm_addr, buf);
- if (ret < 0) {
+ if (ret) {
dev_err(&fn->dev, "Failed to read DPM value: %d\n", ret);
- return -ENODEV;
+ return ret;
}
dpm_resolution = buf[0];
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 20/20] Input: rmi4 - update formatting in F12
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
` (17 preceding siblings ...)
2026-05-05 4:59 ` [PATCH v2 19/20] Input: rmi4 - propagate proper error code in F12 sensor tuning Dmitry Torokhov
@ 2026-05-05 4:59 ` Dmitry Torokhov
18 siblings, 0 replies; 20+ messages in thread
From: Dmitry Torokhov @ 2026-05-05 4:59 UTC (permalink / raw)
To: linux-input; +Cc: Marge Yang, Greg Kroah-Hartman, linux-kernel
Clean up various style and formatting issues in the F12 code.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/input/rmi4/rmi_f12.c | 120 +++++++++++++++++------------------
1 file changed, 60 insertions(+), 60 deletions(-)
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index bf8c4a0e10de..88c28089de99 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -51,7 +51,6 @@ struct f12_data {
const struct rmi_register_desc_item *data6;
u16 data6_offset;
-
/* F12 Data9 reports relative data */
const struct rmi_register_desc_item *data9;
u16 data9_offset;
@@ -124,8 +123,8 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
return -ENODEV;
}
- ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr + offset, buf,
- item->reg_size);
+ ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr + offset,
+ buf, item->reg_size);
if (ret)
return ret;
@@ -163,7 +162,7 @@ static int rmi_f12_read_sensor_tuning(struct f12_data *f12)
if (rmi_get_register_desc_item(&f12->query_reg_desc,
RMI_F12_QUERY_RESOLUTION)) {
offset = rmi_register_desc_calc_reg_offset(&f12->query_reg_desc,
- RMI_F12_QUERY_RESOLUTION);
+ RMI_F12_QUERY_RESOLUTION);
query_dpm_addr = fn->fd.query_base_addr + offset;
ret = rmi_read(fn->rmi_dev, query_dpm_addr, buf);
if (ret) {
@@ -248,18 +247,17 @@ static void rmi_f12_process_objects(struct f12_data *f12, u8 *data1, u32 size)
static irqreturn_t rmi_f12_attention(int irq, void *ctx)
{
- int retval;
struct rmi_function *fn = ctx;
struct rmi_device *rmi_dev = fn->rmi_dev;
struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
struct f12_data *f12 = dev_get_drvdata(&fn->dev);
struct rmi_2d_sensor *sensor = &f12->sensor;
u32 valid_bytes = sensor->pkt_size;
+ int retval;
if (drvdata->attn_data.data) {
valid_bytes = min_t(u32, sensor->attn_size, drvdata->attn_data.size);
- memcpy(sensor->data_pkt, drvdata->attn_data.data,
- valid_bytes);
+ memcpy(sensor->data_pkt, drvdata->attn_data.data, valid_bytes);
drvdata->attn_data.data += valid_bytes;
drvdata->attn_data.size -= valid_bytes;
} else {
@@ -273,70 +271,74 @@ static irqreturn_t rmi_f12_attention(int irq, void *ctx)
}
if (f12->data1)
- rmi_f12_process_objects(f12,
- &sensor->data_pkt[f12->data1_offset], valid_bytes);
+ rmi_f12_process_objects(f12, &sensor->data_pkt[f12->data1_offset],
+ valid_bytes);
input_mt_sync_frame(sensor->input);
return IRQ_HANDLED;
}
-static int rmi_f12_write_control_regs(struct rmi_function *fn)
+static int rmi_f12_update_dribble(struct rmi_function *fn, struct f12_data *f12)
{
- int ret;
const struct rmi_register_desc_item *item;
struct rmi_device *rmi_dev = fn->rmi_dev;
- struct f12_data *f12 = dev_get_drvdata(&fn->dev);
- int control_size;
- char buf[3];
- u16 control_offset = 0;
u8 subpacket_offset = 0;
+ u16 control_offset;
+ u32 control_size;
+ int error;
+ u8 buf[3];
- if (f12->has_dribble
- && (f12->sensor.dribble != RMI_REG_STATE_DEFAULT)) {
- item = rmi_get_register_desc_item(&f12->control_reg_desc, 20);
- if (item) {
- control_offset = rmi_register_desc_calc_reg_offset(
- &f12->control_reg_desc, 20);
-
- /*
- * The byte containing the EnableDribble bit will be
- * in either byte 0 or byte 2 of control 20. Depending
- * on the existence of subpacket 0. If control 20 is
- * larger then 3 bytes, just read the first 3.
- */
- control_size = min(item->reg_size, 3U);
-
- ret = rmi_read_block(rmi_dev, fn->fd.control_base_addr
- + control_offset, buf, control_size);
- if (ret)
- return ret;
-
- if (rmi_register_desc_has_subpacket(item, 0))
- subpacket_offset += 1;
-
- switch (f12->sensor.dribble) {
- case RMI_REG_STATE_OFF:
- buf[subpacket_offset] &= ~BIT(2);
- break;
- case RMI_REG_STATE_ON:
- buf[subpacket_offset] |= BIT(2);
- break;
- case RMI_REG_STATE_DEFAULT:
- default:
- break;
- }
+ item = rmi_get_register_desc_item(&f12->control_reg_desc, 20);
+ if (!item)
+ return 0;
- ret = rmi_write_block(rmi_dev,
- fn->fd.control_base_addr + control_offset,
- buf, control_size);
- if (ret)
- return ret;
- }
+ control_offset = rmi_register_desc_calc_reg_offset(&f12->control_reg_desc, 20);
+
+ /*
+ * The byte containing the EnableDribble bit will be
+ * in either byte 0 or byte 2 of control 20. Depending
+ * on the existence of subpacket 0. If control 20 is
+ * larger then 3 bytes, just read the first 3.
+ */
+ control_size = min(item->reg_size, 3U);
+
+ error = rmi_read_block(rmi_dev, fn->fd.control_base_addr + control_offset,
+ buf, control_size);
+ if (error)
+ return error;
+
+ if (rmi_register_desc_has_subpacket(item, 0))
+ subpacket_offset += 1;
+
+ switch (f12->sensor.dribble) {
+ case RMI_REG_STATE_OFF:
+ buf[subpacket_offset] &= ~BIT(2);
+ break;
+ case RMI_REG_STATE_ON:
+ buf[subpacket_offset] |= BIT(2);
+ break;
+ case RMI_REG_STATE_DEFAULT:
+ default:
+ break;
}
+ error = rmi_write_block(rmi_dev, fn->fd.control_base_addr + control_offset,
+ buf, control_size);
+ if (error)
+ return error;
+
return 0;
+}
+static int rmi_f12_write_control_regs(struct rmi_function *fn)
+{
+ struct f12_data *f12 = dev_get_drvdata(&fn->dev);
+
+ if (f12->has_dribble && f12->sensor.dribble != RMI_REG_STATE_DEFAULT)
+ return rmi_f12_update_dribble(fn, f12);
+
+ return 0;
}
static int rmi_f12_config(struct rmi_function *fn)
@@ -362,7 +364,7 @@ static int rmi_f12_config(struct rmi_function *fn)
ret = rmi_f12_write_control_regs(fn);
if (ret)
dev_warn(&fn->dev,
- "Failed to write F12 control registers: %d\n", ret);
+ "Failed to write F12 control registers: %d\n", ret);
return 0;
}
@@ -433,16 +435,14 @@ static int rmi_f12_probe(struct rmi_function *fn)
}
sensor->pkt_size = pkt_size;
- sensor->axis_align =
- f12->sensor_pdata.axis_align;
+ sensor->axis_align = f12->sensor_pdata.axis_align;
sensor->x_mm = f12->sensor_pdata.x_mm;
sensor->y_mm = f12->sensor_pdata.y_mm;
sensor->dribble = f12->sensor_pdata.dribble;
if (sensor->sensor_type == rmi_sensor_default)
- sensor->sensor_type =
- f12->sensor_pdata.sensor_type;
+ sensor->sensor_type = f12->sensor_pdata.sensor_type;
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "%s: data packet size: %u\n", __func__,
sensor->pkt_size);
--
2.54.0.545.g6539524ca2-goog
^ permalink raw reply related [flat|nested] 20+ messages in thread
end of thread, other threads:[~2026-05-05 5:00 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-05 4:59 [PATCH v2 01/20] Input: rmi4 - fix register descriptor address calculation Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 02/20] Input: rmi4 - refactor register descriptor parsing Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 03/20] Input: rmi4 - fix type overflow in register counts Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 04/20] Input: rmi4 - fix num_subpackets overflow in register descriptor Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 05/20] Input: rmi4 - fix memory leak in rmi_set_attn_data() Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 06/20] Input: rmi4 - iterative IRQ handler Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 07/20] Input: rmi4 - fix bit count in bitmap_copy() Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 08/20] Input: rmi4 - fix limit in rmi_register_desc_has_subpacket() Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 09/20] Input: rmi4 - use local presence map in rmi_read_register_desc() Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 10/20] Input: rmi4 - refactor function allocation and registration Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 11/20] Input: rmi4 - use kzalloc_flex() for struct rmi_function Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 12/20] Input: rmi4 - refactor F12 probe function Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 13/20] Input: rmi4 - change reg_size type to u32 Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 14/20] Input: rmi4 - use unaligned access helpers in F12 Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 15/20] Input: rmi4 - use flexible array member for IRQ masks " Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 16/20] Input: rmi4 - use devm_kmalloc for F12 data packet buffer Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 17/20] Input: rmi4 - use sizeof(*ptr) and idiomatic checks in f12 allocators Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 18/20] Input: rmi4 - simplify size calculations in F12 Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 19/20] Input: rmi4 - propagate proper error code in F12 sensor tuning Dmitry Torokhov
2026-05-05 4:59 ` [PATCH v2 20/20] Input: rmi4 - update formatting in F12 Dmitry Torokhov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox