[PATCH v2] Input: pinephone-keyboard - fix firmware node reference leak
From: Wentao Liang
Date: Fri Nov 06 2026 - 06:03:56 EST
of_get_child_by_name() returns a reference which is stored in the
adapter's device but never released, leaking one reference on every
probe.
The adapter device needs its firmware node while it is registered, so keep
the reference for as long as the adapter lives: register the release as a
devres action before the adapter is added, so that it runs after the
adapter has been removed.
While here, use device_set_node() so that dev.fwnode and dev.of_node point
to the same node.
Fixes: 63c5eb157cfd ("Input: pinephone-keyboard - support the proxied I2C bus")
Reported-by: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx>
Closes: https://lore.kernel.org/all/aqwBtYAcIiwSSMmK@xxxxxxxxxx/
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Wentao Liang <vulab@xxxxxxxxxxx>
---
Changes in v2:
- Keep the firmware node reference for as long as the adapter device is
registered and release it from a devres action, as suggested.
- Apologies for the very late reply.
drivers/input/keyboard/pinephone-keyboard.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/drivers/input/keyboard/pinephone-keyboard.c b/drivers/input/keyboard/pinephone-keyboard.c
index 86f21045c69b..b6a70e8a8a0b 100644
--- a/drivers/input/keyboard/pinephone-keyboard.c
+++ b/drivers/input/keyboard/pinephone-keyboard.c
@@ -317,13 +317,18 @@ static void ppkb_close(struct input_dev *input)
ppkb_set_scan(client, false);
}
+static void ppkb_put_fwnode(void *data)
+{
+ fwnode_handle_put(data);
+}
+
static int ppkb_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
unsigned int phys_rows, phys_cols;
struct pinephone_keyboard *ppkb;
u8 info[PPKB_MATRIX_SIZE + 1];
- struct device_node *i2c_bus;
+ struct fwnode_handle *fwnode;
int ret;
int error;
@@ -371,15 +376,20 @@ static int ppkb_probe(struct i2c_client *client)
i2c_set_clientdata(client, ppkb);
- i2c_bus = of_get_child_by_name(dev->of_node, "i2c");
- if (i2c_bus) {
+ fwnode = device_get_named_child_node(dev, "i2c");
+ if (fwnode) {
ppkb->adapter.owner = THIS_MODULE;
ppkb->adapter.algo = &ppkb_adap_algo;
ppkb->adapter.algo_data = client;
ppkb->adapter.dev.parent = dev;
- ppkb->adapter.dev.of_node = i2c_bus;
strscpy(ppkb->adapter.name, DRV_NAME, sizeof(ppkb->adapter.name));
+ error = devm_add_action_or_reset(dev, ppkb_put_fwnode, fwnode);
+ if (error)
+ return error;
+
+ device_set_node(&ppkb->adapter.dev, fwnode);
+
error = devm_i2c_add_adapter(dev, &ppkb->adapter);
if (error) {
dev_err(dev, "Failed to add I2C adapter: %d\n", error);
--
2.25.1