* [PATCH v7 2/7] mfd: Add driver for ASUS Transformer embedded controller
From: Svyatoslav Ryhel @ 2026-05-18 9:59 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Dmitry Torokhov,
Lee Jones, Pavel Machek, Sebastian Reichel, Svyatoslav Ryhel,
Ion Agorria, Michał Mirosław
Cc: devicetree, linux-kernel, linux-input, linux-leds, linux-pm
In-Reply-To: <20260518095907.36158-1-clamor95@gmail.com>
From: Michał Mirosław <mirq-linux@rere.qmqm.pl>
Support Nuvoton NPCE795-based ECs as used in Asus Transformer TF201,
TF300T, TF300TG, TF300TL and TF700T pad and dock, as well as TF101 dock
and TF600T, P1801-T and TF701T pad. This is a glue driver handling
detection and common operations for EC's functions.
Co-developed-by: Svyatoslav Ryhel <clamor95@gmail.com>
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
---
drivers/mfd/Kconfig | 16 +
drivers/mfd/Makefile | 1 +
drivers/mfd/asus-transformer-ec.c | 534 ++++++++++++++++++++++++
include/linux/mfd/asus-transformer-ec.h | 92 ++++
4 files changed, 643 insertions(+)
create mode 100644 drivers/mfd/asus-transformer-ec.c
create mode 100644 include/linux/mfd/asus-transformer-ec.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 7192c9d1d268..e1c32505b97a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -137,6 +137,22 @@ config MFD_AAT2870_CORE
additional drivers must be enabled in order to use the
functionality of the device.
+config MFD_ASUS_TRANSFORMER_EC
+ tristate "ASUS Transformer's embedded controller"
+ select MFD_CORE
+ depends on I2C && OF
+ help
+ Select this to enable support for the Embedded Controller (EC)
+ found in Tegra based ASUS Transformer series tablets and mobile
+ docks.
+
+ This driver handles the core I2C communication with the EC and
+ provides support for its sub-devices, including battery management,
+ charger detection, LEDs and keyboard dock functions support.
+
+ This driver can also be built as a module. If so, the module
+ will be called asus-transformer-ec.
+
config MFD_AT91_USART
tristate "AT91 USART Driver"
select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index e75e8045c28a..fd80088d8a9a 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_MFD_88PM805) += 88pm805.o 88pm80x.o
obj-$(CONFIG_MFD_88PM886_PMIC) += 88pm886.o
obj-$(CONFIG_MFD_ACT8945A) += act8945a.o
obj-$(CONFIG_MFD_SM501) += sm501.o
+obj-$(CONFIG_MFD_ASUS_TRANSFORMER_EC) += asus-transformer-ec.o
obj-$(CONFIG_ARCH_BCM2835) += bcm2835-pm.o
obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
diff --git a/drivers/mfd/asus-transformer-ec.c b/drivers/mfd/asus-transformer-ec.c
new file mode 100644
index 000000000000..18bb3e5f384d
--- /dev/null
+++ b/drivers/mfd/asus-transformer-ec.c
@@ -0,0 +1,534 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/array_size.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/asus-transformer-ec.h>
+#include <linux/mfd/core.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/unaligned.h>
+
+#define ASUSEC_RSP_BUFFER_SIZE (DOCKRAM_ENTRIES / DOCKRAM_ENTRY_SIZE)
+
+#define ASUSEC_RESET 0
+#define ASUSEC_RETRY_MAX 3
+#define ASUSEC_ACCESS_TIMEOUT 300
+
+enum asusec_variant {
+ ASUSEC_SL101_DOCK = 1,
+ ASUSEC_TF101_DOCK,
+ ASUSEC_TF201_PAD,
+ ASUSEC_TF600T_PAD,
+ ASUSEC_MAX
+};
+
+enum asusec_mode {
+ ASUSEC_MODE_NONE,
+ ASUSEC_MODE_NORMAL,
+ ASUSEC_MODE_FACTORY,
+ ASUSEC_MODE_MAX
+};
+
+/**
+ * struct asus_ec_chip_info
+ *
+ * @name: prefix associated with the EC
+ * @variant: id of programming model of EC
+ * @mode: state of Factory Mode bit in EC control register
+ */
+struct asus_ec_chip_info {
+ const char *name;
+ enum asusec_variant variant;
+ enum asusec_mode fmode;
+};
+
+/**
+ * struct asus_ec_data
+ *
+ * @ec: public part shared with all cells (must be first)
+ * @ecreq_lock: prevents simultaneous access to EC
+ * @ecreq_gpio: EC request GPIO
+ * @client: pointer to EC's i2c_client
+ * @info: pointer to EC's version description
+ * @ec_buf: buffer for EC read
+ * @logging_disabled: flag disabling logging on reset events
+ */
+struct asus_ec_data {
+ struct asusec_core ec;
+ struct mutex ecreq_lock;
+ struct gpio_desc *ecreq_gpio;
+ struct i2c_client *client;
+ const struct asus_ec_chip_info *info;
+ u8 ec_buf[DOCKRAM_ENTRY_BUFSIZE];
+ bool logging_disabled;
+};
+
+/**
+ * struct dockram_ec_data
+ *
+ * @ctl_lock: prevent simultaneous access to Dockram
+ * @ctl_buf: buffer for Dockram read
+ */
+struct dockram_ec_data {
+ struct mutex ctl_lock;
+ u8 ctl_buf[DOCKRAM_ENTRY_BUFSIZE];
+};
+
+/**
+ * asus_dockram_access_ctl - Read from or write to the DockRAM control register.
+ * @client: Handle to the DockRAM device.
+ * @out: Pointer to a variable where the register value will be stored.
+ * @mask: Bitmask of bits to be cleared.
+ * @xor: Bitmask of bits to be set (via XOR).
+ *
+ * This performs a control register read if @out is provided and both @mask
+ * and @xor are zero. Otherwise, it performs a control register update if
+ * @mask and @xor are provided.
+ *
+ * Returns a negative errno code else zero on success.
+ */
+int asus_dockram_access_ctl(struct i2c_client *client, u64 *out, u64 mask,
+ u64 xor)
+{
+ struct dockram_ec_data *ddata = i2c_get_clientdata(client);
+ u8 *buf = ddata->ctl_buf;
+ u64 val;
+ int ret = 0;
+
+ guard(mutex)(&ddata->ctl_lock);
+
+ memset(buf, 0, DOCKRAM_ENTRY_BUFSIZE);
+ ret = i2c_smbus_read_i2c_block_data(client, ASUSEC_DOCKRAM_CONTROL,
+ DOCKRAM_ENTRY_SIZE, buf);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed to access control buffer: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (buf[0] != ASUSEC_CTL_SIZE) {
+ dev_err(&client->dev, "buffer size exceeds %d: %d\n",
+ ASUSEC_CTL_SIZE, buf[0]);
+ return -EPROTO;
+ }
+
+ val = get_unaligned_le64(buf + 1);
+
+ if (out)
+ *out = val;
+
+ if (mask || xor) {
+ put_unaligned_le64((val & ~mask) ^ xor, buf + 1);
+ ret = i2c_smbus_write_i2c_block_data(client,
+ ASUSEC_DOCKRAM_CONTROL,
+ DOCKRAM_ENTRY_SIZE, buf);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(asus_dockram_access_ctl);
+
+static int asus_ec_signal_request(struct asus_ec_data *ddata)
+{
+ guard(mutex)(&ddata->ecreq_lock);
+
+ gpiod_set_value_cansleep(ddata->ecreq_gpio, 1);
+ msleep(50);
+
+ gpiod_set_value_cansleep(ddata->ecreq_gpio, 0);
+ msleep(200);
+
+ return 0;
+}
+
+static void asus_ec_clear_buffer(struct asus_ec_data *ddata)
+{
+ int ret, retry = ASUSEC_RSP_BUFFER_SIZE;
+
+ /*
+ * Read the buffer till we get valid data by checking ASUSEC_OBF_MASK
+ * of the status byte or till we reach end of the 256 byte buffer.
+ */
+ while (retry--) {
+ ret = i2c_smbus_read_i2c_block_data(ddata->client, ASUSEC_READ_BUF,
+ sizeof(ddata->ec_buf),
+ ddata->ec_buf);
+ if (ret < 0)
+ continue;
+
+ if (ddata->ec_buf[ASUSEC_IRQ_STATUS] & ASUSEC_OBF_MASK)
+ continue;
+
+ break;
+ }
+}
+
+static int asus_ec_log_info(struct asus_ec_data *ddata, unsigned int reg,
+ const char *name, char **out)
+{
+ struct device *dev = &ddata->client->dev;
+ u8 buf[DOCKRAM_ENTRY_BUFSIZE];
+ int ret;
+
+ memset(buf, 0, DOCKRAM_ENTRY_BUFSIZE);
+ ret = i2c_smbus_read_i2c_block_data(ddata->ec.dockram, reg,
+ DOCKRAM_ENTRY_SIZE, buf);
+ if (ret < 0)
+ return ret;
+
+ if (buf[0] > DOCKRAM_ENTRY_SIZE) {
+ dev_err(dev, "bad data len; buffer: %*ph; ret: %d\n",
+ DOCKRAM_ENTRY_BUFSIZE, buf, ret);
+ return -EPROTO;
+ }
+
+ if (!ddata->logging_disabled)
+ dev_info(dev, "%-14s: %.*s\n", name, buf[0], buf + 1);
+
+ if (out)
+ *out = kstrndup(buf + 1, buf[0], GFP_KERNEL);
+
+ return 0;
+}
+
+static int asus_ec_reset(struct asus_ec_data *ddata)
+{
+ int retry, ret;
+
+ guard(mutex)(&ddata->ecreq_lock);
+
+ for (retry = 0; retry < ASUSEC_RETRY_MAX; retry++) {
+ ret = i2c_smbus_write_word_data(ddata->client, ASUSEC_WRITE_BUF,
+ ASUSEC_RESET);
+ if (!ret)
+ return 0;
+
+ msleep(ASUSEC_ACCESS_TIMEOUT);
+ }
+
+ return ret;
+}
+
+static int asus_ec_susb_on_status(struct asus_ec_data *ddata)
+{
+ u64 flag;
+ int ret;
+
+ ret = asus_dockram_access_ctl(ddata->ec.dockram, &flag, 0, 0);
+ if (ret)
+ return ret;
+
+ flag &= ASUSEC_CTL_SUSB_MODE;
+ dev_info(&ddata->client->dev, "EC FW behaviour: %s\n",
+ flag ? "susb on when receive ec_req" :
+ "susb on when system wakeup");
+
+ return 0;
+}
+
+static int asus_ec_set_factory_mode(struct asus_ec_data *ddata,
+ enum asusec_mode fmode)
+{
+ dev_info(&ddata->client->dev, "Entering %s mode.\n",
+ fmode == ASUSEC_MODE_FACTORY ? "factory" : "normal");
+
+ return asus_dockram_access_ctl(ddata->ec.dockram, NULL,
+ ASUSEC_CTL_FACTORY_MODE,
+ fmode == ASUSEC_MODE_FACTORY ?
+ ASUSEC_CTL_FACTORY_MODE : 0);
+}
+
+static int asus_ec_detect(struct asus_ec_data *ddata)
+{
+ char *model __free(kfree) = NULL;
+ int ret;
+
+ ret = asus_ec_reset(ddata);
+ if (ret)
+ goto err_exit;
+
+ asus_ec_clear_buffer(ddata);
+
+ ret = asus_ec_log_info(ddata, ASUSEC_DOCKRAM_INFO_MODEL, "Model", &model);
+ if (ret)
+ goto err_exit;
+
+ ret = asus_ec_log_info(ddata, ASUSEC_DOCKRAM_INFO_FW, "FW version", NULL);
+ if (ret)
+ goto err_exit;
+
+ ret = asus_ec_log_info(ddata, ASUSEC_DOCKRAM_INFO_CFGFMT, "Config format", NULL);
+ if (ret)
+ goto err_exit;
+
+ ret = asus_ec_log_info(ddata, ASUSEC_DOCKRAM_INFO_HW, "HW version", NULL);
+ if (ret)
+ goto err_exit;
+
+ /* Disable logging on next EC request */
+ ddata->logging_disabled = true;
+
+ /* Check and inform about EC firmware behavior */
+ ret = asus_ec_susb_on_status(ddata);
+ if (ret)
+ goto err_exit;
+
+ kfree(ddata->ec.model);
+
+ ddata->ec.model = no_free_ptr(model);
+ ddata->ec.name = ddata->info->name;
+
+ /* Some EC require factory mode to be set normal on each request */
+ if (ddata->info->fmode)
+ ret = asus_ec_set_factory_mode(ddata, ddata->info->fmode);
+
+err_exit:
+ if (ret)
+ dev_err(&ddata->client->dev, "failed to access EC: %d\n", ret);
+
+ return ret;
+}
+
+static void asus_ec_handle_smi(struct asus_ec_data *ddata, unsigned int code)
+{
+ switch (code) {
+ case ASUSEC_SMI_HANDSHAKE:
+ case ASUSEC_SMI_RESET:
+ asus_ec_detect(ddata);
+ break;
+ }
+}
+
+static irqreturn_t asus_ec_interrupt(int irq, void *dev_id)
+{
+ struct asus_ec_data *ddata = dev_id;
+ unsigned long notify_action;
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(ddata->client, ASUSEC_READ_BUF,
+ sizeof(ddata->ec_buf), ddata->ec_buf);
+ if (ret <= 0 || !(ddata->ec_buf[ASUSEC_IRQ_STATUS] & ASUSEC_OBF_MASK))
+ return IRQ_NONE;
+
+ notify_action = ddata->ec_buf[ASUSEC_IRQ_STATUS];
+ if (notify_action & ASUSEC_SMI_MASK) {
+ unsigned int code = ddata->ec_buf[ASUSEC_SMI_CODE];
+
+ asus_ec_handle_smi(ddata, code);
+
+ notify_action |= code << 8;
+ }
+
+ blocking_notifier_call_chain(&ddata->ec.notify_list,
+ notify_action, ddata->ec_buf);
+
+ return IRQ_HANDLED;
+}
+
+static void asus_ec_release_dockram_dev(void *client)
+{
+ i2c_unregister_device(client);
+}
+
+static struct i2c_client *devm_asus_dockram_get(struct device *dev)
+{
+ struct i2c_client *parent = to_i2c_client(dev);
+ struct i2c_client *dockram;
+ struct dockram_ec_data *ddata;
+ int ret;
+
+ dockram = i2c_new_ancillary_device(parent, "dockram",
+ parent->addr + 2);
+ if (IS_ERR(dockram))
+ return dockram;
+
+ ret = devm_add_action_or_reset(dev, asus_ec_release_dockram_dev,
+ dockram);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ddata = devm_kzalloc(&dockram->dev, sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
+ return ERR_PTR(-ENOMEM);
+
+ i2c_set_clientdata(dockram, ddata);
+ mutex_init(&ddata->ctl_lock);
+
+ return dockram;
+}
+
+static const struct mfd_cell asus_ec_sl101_dock_mfd_devices[] = {
+ MFD_CELL_NAME("asus-transformer-ec-kbc"),
+};
+
+static const struct mfd_cell asus_ec_tf101_dock_mfd_devices[] = {
+ MFD_CELL_BASIC("asus-transformer-ec-battery", NULL, NULL, 0, 1),
+ MFD_CELL_BASIC("asus-transformer-ec-charger", NULL, NULL, 0, 1),
+ MFD_CELL_BASIC("asus-transformer-ec-led", NULL, NULL, 0, 1),
+ MFD_CELL_NAME("asus-transformer-ec-keys"),
+ MFD_CELL_NAME("asus-transformer-ec-kbc"),
+};
+
+static const struct mfd_cell asus_ec_tf201_pad_mfd_devices[] = {
+ MFD_CELL_NAME("asus-transformer-ec-battery"),
+ MFD_CELL_NAME("asus-transformer-ec-led"),
+};
+
+static const struct mfd_cell asus_ec_tf600t_pad_mfd_devices[] = {
+ MFD_CELL_NAME("asus-transformer-ec-battery"),
+ MFD_CELL_NAME("asus-transformer-ec-charger"),
+ MFD_CELL_NAME("asus-transformer-ec-led"),
+};
+
+static int asus_ec_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct asus_ec_data *ddata;
+ const struct mfd_cell *cells;
+ unsigned int num_cells;
+ unsigned long irqflags;
+ int ret;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
+ return dev_err_probe(dev, -ENXIO,
+ "I2C bus is missing required SMBus block mode support\n");
+
+ ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
+ return -ENOMEM;
+
+ ddata->info = device_get_match_data(dev);
+ if (!ddata->info)
+ return -ENODEV;
+
+ switch (ddata->info->variant) {
+ case ASUSEC_SL101_DOCK:
+ cells = asus_ec_sl101_dock_mfd_devices;
+ num_cells = ARRAY_SIZE(asus_ec_sl101_dock_mfd_devices);
+ break;
+ case ASUSEC_TF101_DOCK:
+ cells = asus_ec_tf101_dock_mfd_devices;
+ num_cells = ARRAY_SIZE(asus_ec_tf101_dock_mfd_devices);
+ break;
+ case ASUSEC_TF201_PAD:
+ cells = asus_ec_tf201_pad_mfd_devices;
+ num_cells = ARRAY_SIZE(asus_ec_tf201_pad_mfd_devices);
+ break;
+ case ASUSEC_TF600T_PAD:
+ cells = asus_ec_tf600t_pad_mfd_devices;
+ num_cells = ARRAY_SIZE(asus_ec_tf600t_pad_mfd_devices);
+ break;
+ default:
+ return dev_err_probe(dev, -EINVAL,
+ "unknown device variant %d\n",
+ ddata->info->variant);
+ }
+
+ i2c_set_clientdata(client, ddata);
+ ddata->client = client;
+
+ ddata->ec.dockram = devm_asus_dockram_get(dev);
+ if (IS_ERR(ddata->ec.dockram))
+ return dev_err_probe(dev, PTR_ERR(ddata->ec.dockram),
+ "failed to get dockram\n");
+
+ ddata->ecreq_gpio = devm_gpiod_get(dev, "request", GPIOD_OUT_LOW);
+ if (IS_ERR(ddata->ecreq_gpio))
+ return dev_err_probe(dev, PTR_ERR(ddata->ecreq_gpio),
+ "failed to get EC request GPIO\n");
+
+ BLOCKING_INIT_NOTIFIER_HEAD(&ddata->ec.notify_list);
+ mutex_init(&ddata->ecreq_lock);
+
+ asus_ec_signal_request(ddata);
+
+ ret = asus_ec_detect(ddata);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to detect EC version\n");
+
+ /*
+ * Systems using device tree should set up interrupt via DTS,
+ * the rest will use the default low interrupt.
+ */
+ irqflags = dev->of_node ? 0 : IRQF_TRIGGER_LOW;
+
+ ret = devm_request_threaded_irq(dev, client->irq, NULL,
+ &asus_ec_interrupt,
+ IRQF_ONESHOT | irqflags,
+ client->name, ddata);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to register IRQ\n");
+
+ /* Parent I2C controller uses DMA, ASUS EC and child devices do not */
+ client->dev.coherent_dma_mask = 0;
+ client->dev.dma_mask = &client->dev.coherent_dma_mask;
+
+ return devm_mfd_add_devices(dev, 0, cells, num_cells, NULL, 0, NULL);
+}
+
+static const struct asus_ec_chip_info asus_ec_sl101_dock_data = {
+ .name = "dock",
+ .variant = ASUSEC_SL101_DOCK,
+ .fmode = ASUSEC_MODE_NONE,
+};
+
+static const struct asus_ec_chip_info asus_ec_tf101_dock_data = {
+ .name = "dock",
+ .variant = ASUSEC_TF101_DOCK,
+ .fmode = ASUSEC_MODE_NONE,
+};
+
+static const struct asus_ec_chip_info asus_ec_tf201_pad_data = {
+ .name = "pad",
+ .variant = ASUSEC_TF201_PAD,
+ .fmode = ASUSEC_MODE_NORMAL,
+};
+
+static const struct asus_ec_chip_info asus_ec_tf600t_pad_data = {
+ .name = "pad",
+ .variant = ASUSEC_TF600T_PAD,
+ .fmode = ASUSEC_MODE_NORMAL,
+};
+
+static const struct of_device_id asus_ec_match[] = {
+ {
+ .compatible = "asus,sl101-ec-dock",
+ .data = &asus_ec_sl101_dock_data
+ }, {
+ .compatible = "asus,tf101-ec-dock",
+ .data = &asus_ec_tf101_dock_data
+ }, {
+ .compatible = "asus,tf201-ec-pad",
+ .data = &asus_ec_tf201_pad_data
+ }, {
+ .compatible = "asus,tf600t-ec-pad",
+ .data = &asus_ec_tf600t_pad_data
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, asus_ec_match);
+
+static struct i2c_driver asus_ec_driver = {
+ .driver = {
+ .name = "asus-transformer-ec",
+ .of_match_table = asus_ec_match,
+ },
+ .probe = asus_ec_probe,
+};
+module_i2c_driver(asus_ec_driver);
+
+MODULE_AUTHOR("Michał Mirosław <mirq-linux@rere.qmqm.pl>");
+MODULE_AUTHOR("Svyatoslav Ryhel <clamor95@gmail.com>");
+MODULE_DESCRIPTION("ASUS Transformer's EC driver");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/asus-transformer-ec.h b/include/linux/mfd/asus-transformer-ec.h
new file mode 100644
index 000000000000..980a31f6b25c
--- /dev/null
+++ b/include/linux/mfd/asus-transformer-ec.h
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __MFD_ASUS_TRANSFORMER_EC_H
+#define __MFD_ASUS_TRANSFORMER_EC_H
+
+#include <linux/notifier.h>
+#include <linux/platform_device.h>
+
+struct i2c_client;
+
+/**
+ * struct asusec_core - public part shared with all cells
+ *
+ * @model: firmware version running on the EC
+ * @name: prefix associated with the EC
+ * @dockram: pointer to Dockram's i2c_client
+ * @notify_list: notify list used by cells
+ */
+struct asusec_core {
+ const char *model;
+ const char *name;
+ struct i2c_client *dockram;
+ struct blocking_notifier_head notify_list;
+};
+
+#define DOCKRAM_ENTRIES 0x100
+#define DOCKRAM_ENTRY_SIZE 32
+#define DOCKRAM_ENTRY_BUFSIZE (DOCKRAM_ENTRY_SIZE + 1)
+
+/* interrupt sources */
+#define ASUSEC_IRQ_STATUS 1
+#define ASUSEC_OBF_MASK BIT(0)
+#define ASUSEC_KEY_MASK BIT(2)
+#define ASUSEC_KBC_MASK BIT(3)
+#define ASUSEC_AUX_MASK BIT(5)
+#define ASUSEC_SCI_MASK BIT(6)
+#define ASUSEC_SMI_MASK BIT(7)
+
+/* SMI notification codes */
+#define ASUSEC_SMI_CODE 2
+#define ASUSEC_SMI_POWER_NOTIFY 0x31 /* USB cable plug event */
+#define ASUSEC_SMI_HANDSHAKE 0x50 /* response to ec_req edge */
+#define ASUSEC_SMI_WAKE 0x53
+#define ASUSEC_SMI_RESET 0x5f
+#define ASUSEC_SMI_ADAPTER_EVENT 0x60 /* charger to dock plug event */
+#define ASUSEC_SMI_BACKLIGHT_ON 0x63
+#define ASUSEC_SMI_AUDIO_DOCK_IN 0x70
+
+#define ASUSEC_SMI_ACTION(code) (ASUSEC_SMI_MASK | ASUSEC_OBF_MASK | \
+ (ASUSEC_SMI_##code << 8))
+
+/* control register [0x0a] layout */
+#define ASUSEC_CTL_SIZE 8
+
+/*
+ * EC reports power from 40-pin connector in the LSB of the control
+ * register. The following values have been observed (xor 0x02):
+ *
+ * PAD-ec no-plug 0x40 / PAD-ec DOCK 0x20 / DOCK-ec no-plug 0x40
+ * PAD-ec AC 0x25 / PAD-ec DOCK+AC 0x24 / DOCK-ec AC 0x25
+ * PAD-ec USB 0x45 / PAD-ec DOCK+USB 0x24 / DOCK-ec USB 0x41
+ */
+
+#define ASUSEC_CTL_DIRECT_POWER_SOURCE BIT_ULL(0)
+#define ASUSEC_STAT_CHARGING BIT_ULL(2)
+#define ASUSEC_CTL_FULL_POWER_SOURCE BIT_ULL(5)
+#define ASUSEC_CTL_SUSB_MODE BIT_ULL(9)
+#define ASUSEC_CMD_SUSPEND_S3 BIT_ULL(33)
+#define ASUSEC_CTL_TEST_DISCHARGE BIT_ULL(35)
+#define ASUSEC_CMD_SUSPEND_INHIBIT BIT_ULL(37)
+#define ASUSEC_CTL_FACTORY_MODE BIT_ULL(38)
+#define ASUSEC_CTL_KEEP_AWAKE BIT_ULL(39)
+#define ASUSEC_CTL_USB_CHARGE BIT_ULL(40)
+#define ASUSEC_CTL_LED_BLINK BIT_ULL(40)
+#define ASUSEC_CTL_LED_AMBER BIT_ULL(41)
+#define ASUSEC_CTL_LED_GREEN BIT_ULL(42)
+#define ASUSEC_CMD_SWITCH_HDMI BIT_ULL(56)
+#define ASUSEC_CMD_WIN_SHUTDOWN BIT_ULL(62)
+
+#define ASUSEC_DOCKRAM_INFO_MODEL 0x01
+#define ASUSEC_DOCKRAM_INFO_FW 0x02
+#define ASUSEC_DOCKRAM_INFO_CFGFMT 0x03
+#define ASUSEC_DOCKRAM_INFO_HW 0x04
+#define ASUSEC_DOCKRAM_CONTROL 0x0a
+#define ASUSEC_DOCKRAM_BATT_CTL 0x14
+
+#define ASUSEC_WRITE_BUF 0x64
+#define ASUSEC_READ_BUF 0x6a
+
+int asus_dockram_access_ctl(struct i2c_client *client,
+ u64 *out, u64 mask, u64 xor);
+
+#endif /* __MFD_ASUS_TRANSFORMER_EC_H */
--
2.51.0
^ permalink raw reply related
* [PATCH v7 1/7] dt-bindings: embedded-controller: document ASUS Transformer EC
From: Svyatoslav Ryhel @ 2026-05-18 9:59 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Dmitry Torokhov,
Lee Jones, Pavel Machek, Sebastian Reichel, Svyatoslav Ryhel,
Ion Agorria, Michał Mirosław
Cc: devicetree, linux-kernel, linux-input, linux-leds, linux-pm
In-Reply-To: <20260518095907.36158-1-clamor95@gmail.com>
Document embedded controller used in ASUS Transformer device series.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
.../asus,tf201-ec-pad.yaml | 119 ++++++++++++++++++
1 file changed, 119 insertions(+)
create mode 100644 Documentation/devicetree/bindings/embedded-controller/asus,tf201-ec-pad.yaml
diff --git a/Documentation/devicetree/bindings/embedded-controller/asus,tf201-ec-pad.yaml b/Documentation/devicetree/bindings/embedded-controller/asus,tf201-ec-pad.yaml
new file mode 100644
index 000000000000..60b6375864aa
--- /dev/null
+++ b/Documentation/devicetree/bindings/embedded-controller/asus,tf201-ec-pad.yaml
@@ -0,0 +1,119 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/embedded-controller/asus,tf201-ec-pad.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: ASUS Transformer's Embedded Controller
+
+description:
+ Several Nuvoton based Embedded Controllers attached to an I2C bus,
+ running a custom ASUS firmware, specific to the ASUS Transformer
+ device series.
+
+maintainers:
+ - Svyatoslav Ryhel <clamor95@gmail.com>
+
+properties:
+ compatible:
+ description:
+ The 'pad' suffix is used for the controller within the tablet, while
+ the 'dock' suffix refers to the controller in the mobile dock keyboard.
+ oneOf:
+ - enum:
+ - asus,sl101-ec-dock
+ - asus,tf101-ec-dock
+ - asus,tf201-ec-pad
+ - asus,tf600t-ec-dock
+ - asus,tf600t-ec-pad
+
+ - items:
+ - enum:
+ - asus,tf101g-ec-dock
+ - asus,tf201-ec-dock
+ - asus,tf300t-ec-dock
+ - asus,tf300tg-ec-dock
+ - asus,tf300tl-ec-dock
+ - asus,tf700t-ec-dock
+ - const: asus,tf101-ec-dock
+
+ - items:
+ - enum:
+ - asus,tf300t-ec-pad
+ - asus,tf300tg-ec-pad
+ - asus,tf300tl-ec-pad
+ - asus,tf700t-ec-pad
+ - const: asus,tf201-ec-pad
+
+ - items:
+ - enum:
+ - asus,tf701t-ec-dock
+ - const: asus,tf600t-ec-dock
+
+ - items:
+ - enum:
+ - asus,p1801-t-ec-pad
+ - asus,tf701t-ec-pad
+ - const: asus,tf600t-ec-pad
+
+ reg:
+ description:
+ The ASUS Transformer EC has a main I2C address and an associated
+ DockRAM device, which provides power-related functions for the
+ embedded controller. Both addresses are required for operation.
+ minItems: 2
+
+ reg-names:
+ items:
+ - const: ec
+ - const: dockram
+
+ interrupts:
+ maxItems: 1
+
+ request-gpios:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - reg-names
+
+allOf:
+ - $ref: /schemas/power/supply/power-supply.yaml
+ - if:
+ properties:
+ compatible:
+ not:
+ contains:
+ const: asus,tf600t-ec-dock
+ then:
+ required:
+ - interrupts
+ - request-gpios
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ embedded-controller@19 {
+ compatible = "asus,tf201-ec-dock", "asus,tf101-ec-dock";
+ reg = <0x19>, <0x1b>;
+ reg-names = "ec", "dockram";
+
+ interrupt-parent = <&gpio>;
+ interrupts = <151 IRQ_TYPE_LEVEL_LOW>;
+
+ request-gpios = <&gpio 134 GPIO_ACTIVE_LOW>;
+
+ monitored-battery = <&dock_battery>;
+ };
+ };
+...
--
2.51.0
^ permalink raw reply related
* [PATCH v7 0/7] mfd: Add support for Asus Transformer embedded controller
From: Svyatoslav Ryhel @ 2026-05-18 9:59 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Dmitry Torokhov,
Lee Jones, Pavel Machek, Sebastian Reichel, Svyatoslav Ryhel,
Ion Agorria, Michał Mirosław
Cc: devicetree, linux-kernel, linux-input, linux-leds, linux-pm
Add support for embedded controller used in Asus Transformers for
managing power and input functions.
---
Changes in v2:
- converted sysfs debug exports into debugfs
- added kernel-doc comments for exposed functions
- fixed minor typos and inconsistencies
Changes in v3:
- dropped DockRAM commits (both schema and driver)
- integrated DockRAM functionality directly into the controller driver
- EC schema moved to embedded controllers folder
- removed all cell descriptions from the schema
- removed all compatibles from the cell drivers
- adjusted naming conventions to better align with the ASUS Transformers
- defined EC variant sets to provide coverage for all known devices
Changes in v4:
- grouped known programming models of EC chronologically (both schema
and driver)
- call debugfs init only if CONFIG_DEBUG_FS is enabled
Changes in v5:
- added asus,tf600t-ec-dock compatible to schema
- rebased on top of v7.0
- kzalloc > kzalloc_obj in keys and kbc
Changes in v6:
- removed asus_ec_handle_smi casting
- asus_dockram_access_ctl > asus_ec_get_ctl in control_reg_*
- fixed battery Kconfig description
Changes in v7:
- added status check of devm_kasprintf where missing
- devm_asus_ec_register_notifier dropped, added .remove where it was used
- removed cell_to_ec, asus_dockram_read, asus_dockram_write, asus_ec_* public API
asus_ec_i2c_command, devm_asus_ec_register_notifier, asus_ec_read, asus_ec_write
- renamed asusec_info > asusec_core
- ec-kbc: added packed size check
ret > error
improved key remap logic
- ec-keys: improve formatting and comments
ret > error
switched to dev_err_probe
- ec-leds: reworked to register both leds via loop
- ec-mfd: adjusted Kconfig description
fixed smbus operation sizes
fixed saving of EC fw model
adjusted IRQ flags
converted to use definer for set cell composition
added factory mode states enum and handling
defined some "magic" values
self > client, info > ec, ecreq > ecreq_gpio, priv > ddata
asus_ec_chip_data data > asus_ec_chip_info info
ec_data > ec_buf, ctl_data > ctl_buf
added and improved comments, added structure descriptions
asus_ec_magic_debug > asus_ec_susb_on_status
removed all dev_dbg and most of dev_info
pronts with model, fw behavior, factory and susb state preserved
switched to MFD_CELL_* macros
removed debugfs
- ec-battery: swithced to BIT macro
lock usage moved to asus_ec_battery_get_value
in asus_ec_battery_poll_work fixed possible rescheduling fail
in asus_ec_battery_poll_work fixed missing not charging
- ec-charger: POWER_SUPPLY_PROP_MODEL_NAME set as the first check
---
Michał Mirosław (6):
mfd: Add driver for ASUS Transformer embedded controller
input: serio: Add driver for ASUS Transformer dock keyboard and
touchpad
input: keyboard: Add driver for ASUS Transformer dock multimedia keys
leds: Add driver for ASUS Transformer LEDs
power: supply: Add driver for ASUS Transformer battery
power: supply: Add charger driver for Asus Transformers
Svyatoslav Ryhel (1):
dt-bindings: embedded-controller: document ASUS Transformer EC
.../asus,tf201-ec-pad.yaml | 119 ++++
drivers/input/keyboard/Kconfig | 10 +
drivers/input/keyboard/Makefile | 1 +
.../input/keyboard/asus-transformer-ec-keys.c | 281 +++++++++
drivers/input/serio/Kconfig | 15 +
drivers/input/serio/Makefile | 1 +
drivers/input/serio/asus-transformer-ec-kbc.c | 157 +++++
drivers/leds/Kconfig | 11 +
drivers/leds/Makefile | 1 +
drivers/leds/leds-asus-transformer-ec.c | 109 ++++
drivers/mfd/Kconfig | 16 +
drivers/mfd/Makefile | 1 +
drivers/mfd/asus-transformer-ec.c | 534 ++++++++++++++++++
drivers/power/supply/Kconfig | 22 +
drivers/power/supply/Makefile | 2 +
.../supply/asus-transformer-ec-battery.c | 286 ++++++++++
.../supply/asus-transformer-ec-charger.c | 207 +++++++
include/linux/mfd/asus-transformer-ec.h | 92 +++
18 files changed, 1865 insertions(+)
create mode 100644 Documentation/devicetree/bindings/embedded-controller/asus,tf201-ec-pad.yaml
create mode 100644 drivers/input/keyboard/asus-transformer-ec-keys.c
create mode 100644 drivers/input/serio/asus-transformer-ec-kbc.c
create mode 100644 drivers/leds/leds-asus-transformer-ec.c
create mode 100644 drivers/mfd/asus-transformer-ec.c
create mode 100644 drivers/power/supply/asus-transformer-ec-battery.c
create mode 100644 drivers/power/supply/asus-transformer-ec-charger.c
create mode 100644 include/linux/mfd/asus-transformer-ec.h
--
2.51.0
^ permalink raw reply
* Re: [PATCH v2 5/6] tools/build: selftests: Allow versioning LLVM lld
From: James Clark @ 2026-05-18 9:47 UTC (permalink / raw)
To: sashiko-reviews; +Cc: dmitry.torokhov, linux-perf-users, bpf, linux-input
In-Reply-To: <20260518093237.90640C2BCC6@smtp.kernel.org>
On 18/05/2026 10:32 am, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] Empty USE_LD variable causes clang build failure in selftests when ld.lld is not in PATH.
> --
>
> commit 371ca22c55bb0fa6502ac06f7b33d63418ad16ff
> Author: James Clark <james.clark@linaro.org>
>
> tools/build: selftests: Allow versioning LLVM lld
>
> This commit adds an LLD variable to Makefile.include to allow versioning of
> LLVM's linker, keeping it consistent with the rest of the LLVM toolchain. It
> modifies the BPF selftests Makefile to resolve the full path of the linker
> using the command -v shell utility.
>
>> diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
>> index 6ef6872adbc3e..836e783f0170e 100644
>> --- a/tools/testing/selftests/bpf/Makefile
>> +++ b/tools/testing/selftests/bpf/Makefile
>
> [ ... ]
>
>> @@ -245,9 +245,9 @@ $(OUTPUT)/%:%.c
>>
>> # LLVM's ld.lld doesn't support all the architectures, so use it only on x86
>> ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 riscv))
>> -LLD := lld
>> +USE_LD := $(shell command -v $(LLD))
>
> Does this cause the build to fail if the toolchain directory is not in the
> system PATH?
>
> If a user explicitly specifies the compiler using an absolute path like
> CLANG=/path/to/clang, but does not add the toolchain directory to their PATH,
> the command -v utility will return an empty string.
If they don't use LLVM= and use CLANG= with an absolute path then they
need to set all the tools with an absolute path. That's the problem that
setting the path with a prefix for all tools with LLVM= solved.
I suppose this could _technically_ be a regression, but so could adding
any new build rule that added a new tool that wouldn't be set in
someones existing build command. Being that strict would mean we can't
ever add new tools so I don't think this is an issue. And I don't think
there's a way to solve this and also respect the documented rules of LLVM=
>
> This would cause USE_LD to be empty, leading to a malformed argument like
> -fuse-ld= being passed to clang later in the Makefile, which then fails with
> an invalid linker name error.
>
> Previously, passing the hardcoded lld allowed clang to natively resolve the
> linker relative to its own binary location. Is there a way to support both
> versioned linker names and absolute compiler paths without relying entirely
> on the system PATH?
>
> [ ... ]
>
^ permalink raw reply
* Re: [PATCH v2 5/6] tools/build: selftests: Allow versioning LLVM lld
From: sashiko-bot @ 2026-05-18 9:32 UTC (permalink / raw)
To: James Clark; +Cc: dmitry.torokhov, linux-perf-users, bpf, linux-input
In-Reply-To: <20260518-james-perf-llvm-version-v2-5-f12cc4f031d8@linaro.org>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Empty USE_LD variable causes clang build failure in selftests when ld.lld is not in PATH.
--
commit 371ca22c55bb0fa6502ac06f7b33d63418ad16ff
Author: James Clark <james.clark@linaro.org>
tools/build: selftests: Allow versioning LLVM lld
This commit adds an LLD variable to Makefile.include to allow versioning of
LLVM's linker, keeping it consistent with the rest of the LLVM toolchain. It
modifies the BPF selftests Makefile to resolve the full path of the linker
using the command -v shell utility.
> diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
> index 6ef6872adbc3e..836e783f0170e 100644
> --- a/tools/testing/selftests/bpf/Makefile
> +++ b/tools/testing/selftests/bpf/Makefile
[ ... ]
> @@ -245,9 +245,9 @@ $(OUTPUT)/%:%.c
>
> # LLVM's ld.lld doesn't support all the architectures, so use it only on x86
> ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 riscv))
> -LLD := lld
> +USE_LD := $(shell command -v $(LLD))
Does this cause the build to fail if the toolchain directory is not in the
system PATH?
If a user explicitly specifies the compiler using an absolute path like
CLANG=/path/to/clang, but does not add the toolchain directory to their PATH,
the command -v utility will return an empty string.
This would cause USE_LD to be empty, leading to a malformed argument like
-fuse-ld= being passed to clang later in the Makefile, which then fails with
an invalid linker name error.
Previously, passing the hardcoded lld allowed clang to natively resolve the
linker relative to its own binary location. Is there a way to support both
versioned linker names and absolute compiler paths without relying entirely
on the system PATH?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260518-james-perf-llvm-version-v2-0-f12cc4f031d8@linaro.org?part=5
^ permalink raw reply
* Re: [PATCH] HID: core: Fix size_t specifier in hid_report_raw_event()
From: Geert Uytterhoeven @ 2026-05-18 9:10 UTC (permalink / raw)
To: Nathan Chancellor
Cc: Jiri Kosina, Benjamin Tissoires, Greg Kroah-Hartman, Johan Hovold,
linux-input, linux-kernel, stable, Miguel Ojeda
In-Reply-To: <20260517-hid-core-fix-size_t-specifier-v1-1-bfdd959ec383@kernel.org>
Hi Nathan,
On Sun, 17 May 2026 at 06:51, Nathan Chancellor <nathan@kernel.org> wrote:
> When building for 32-bit platforms, for which 'size_t' is
> 'unsigned int', there are warnings around using the incorrect format
> specifier to print bsize in hid_report_raw_event():
>
> drivers/hid/hid-core.c:2054:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat]
> 2053 | hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
> | ~~~
> | %zu
> 2054 | report->id, csize, bsize);
> | ^~~~~
> drivers/hid/hid-core.c:2076:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat]
> 2075 | hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
> | ~~~
> | %zu
> 2076 | report->id, rsize, bsize);
> | ^~~~~
>
> Use the proper 'size_t' format specifier, '%zu', to clear up the
> warnings.
>
> Cc: stable@vger.kernel.org
> Fixes: 2c85c61d1332 ("HID: pass the buffer size to hid_report_raw_event")
> Reported-by: Miguel Ojeda <ojeda@kernel.org>
> Closes: https://lore.kernel.org/20260516020430.110135-1-ojeda@kernel.org/
> Signed-off-by: Nathan Chancellor <nathan@kernel.org>
Thanks, this fixes the warnings on 32-bit for me.
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -2050,7 +2050,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
> return 0;
>
> if (unlikely(bsize < csize)) {
> - hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
> + hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %zu)\n",
> report->id, csize, bsize);
Both report->id and csize are unsigned, so should use %u.
> return -EINVAL;
> }
> @@ -2072,7 +2072,7 @@ int hid_report_raw_event(struct hid_device *hid, enum hid_report_type type, u8 *
> rsize = max_buffer_size;
>
> if (bsize < rsize) {
> - hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
> + hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %zu)\n",
> report->id, rsize, bsize);
Same here.
> return -EINVAL;
> }
And more incorrect %d outside the context!
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH 5/6] tools/build: selftests: Allow versioning LLVM lld
From: James Clark @ 2026-05-18 9:05 UTC (permalink / raw)
To: Ihor Solodrai
Cc: linux-kernel, llvm, linux-input, linux-kselftest, bpf,
linux-perf-users, leo.yan, Nathan Chancellor, Nick Desaulniers,
Bill Wendling, Justin Stitt, Jiri Kosina, Benjamin Tissoires,
Shuah Khan, Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, Andrii Nakryiko, Eduard Zingerman,
Alexei Starovoitov, Daniel Borkmann, Martin KaFai Lau,
Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song
In-Reply-To: <bda702a1-18f5-47ed-8a4e-a01b94829e07@linux.dev>
On 15/05/2026 11:58 pm, Ihor Solodrai wrote:
> On 5/14/26 2:32 AM, James Clark wrote:
>> Building with LLVM=... could result in a different version of lld being
>> used than the main toolchain for liburandom_read.so because it's
>> hardcoded to "lld" in this makefile.
>>
>> Make it consistent with the rest of the LLVM toolchain by adding an LLD
>> variable to Makefile.include. Keep the fallback for other architectures
>> in tools/testing/selftests/bpf/Makefile as it seems like it's something
>> specific to this make rule and shouldn't be global.
>>
>> Clang accepts either a full path or "ld.lld-15" style inputs to
>> -fuse-ld= so this will work with LLD defined the same way as the other
>> LLVM tools. However, for full paths, we need to use ".../ld.lld" instead
>> of the generic driver "lld", but I don't think the original use of "lld"
>> was significant as this is always a linux build.
>>
>> Signed-off-by: James Clark <james.clark@linaro.org>
>> ---
>> tools/scripts/Makefile.include | 2 ++
>> tools/testing/selftests/bpf/Makefile | 8 ++++----
>> 2 files changed, 6 insertions(+), 4 deletions(-)
>>
>> diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
>> index 380ad84ac51e..5c2d505cba62 100644
>> --- a/tools/scripts/Makefile.include
>> +++ b/tools/scripts/Makefile.include
>> @@ -67,6 +67,7 @@ ifneq ($(LLVM),)
>> $(call allow-override,HOSTAR,$(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX))
>> $(call allow-override,LD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX))
>> $(call allow-override,HOSTLD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX))
>> + $(call allow-override,LLD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX))
>> $(call allow-override,CXX,$(LLVM_PREFIX)clang++$(LLVM_SUFFIX))
>> $(call allow-override,STRIP,$(LLVM_PREFIX)llvm-strip$(LLVM_SUFFIX))
>> $(call allow-override,LLVM_STRIP,$(LLVM_PREFIX)llvm-strip$(LLVM_SUFFIX))
>> @@ -91,6 +92,7 @@ else
>> # Some tools still require Clang, LLC and/or LLVM utils
>> $(call allow-override,CLANG,clang)
>> $(call allow-override,LLC,llc)
>> + $(call allow-override,LLD,ld.lld)
>> $(call allow-override,LLVM_CONFIG,llvm-config)
>> $(call allow-override,LLVM_OBJCOPY,llvm-objcopy)
>> $(call allow-override,LLVM_STRIP,llvm-strip)
>> diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
>> index 6ef6872adbc3..44ba829e5d4d 100644
>> --- a/tools/testing/selftests/bpf/Makefile
>> +++ b/tools/testing/selftests/bpf/Makefile
>> @@ -245,9 +245,9 @@ $(OUTPUT)/%:%.c
>>
>> # LLVM's ld.lld doesn't support all the architectures, so use it only on x86
>> ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 riscv))
>> -LLD := lld
>> +USE_LD := $(LLD)
>> else
>> -LLD := $(shell command -v $(LD))
>> +USE_LD := $(shell command -v $(LD))
>> endif
>>
>> # Filter out -static for liburandom_read.so and its dependent targets so that static builds
>> @@ -258,7 +258,7 @@ $(OUTPUT)/liburandom_read.so: urandom_read_lib1.c urandom_read_lib2.c liburandom
>> $(filter-out -static,$(CFLAGS) $(LDFLAGS)) \
>> $(filter %.c,$^) $(filter-out -static,$(LDLIBS)) \
>> -Wno-unused-command-line-argument \
>> - -fuse-ld=$(LLD) -Wl,-znoseparate-code -Wl,--build-id=sha1 \
>> + -fuse-ld=$(USE_LD) -Wl,-znoseparate-code -Wl,--build-id=sha1 \
>
> Hi James,
>
> This patch breaks the selftests/bpf build:
>
> $ clang --version
> clang version 22.1.3 (CentOS 22.1.3-1.el9)
> Target: x86_64-redhat-linux-gnu
> Thread model: posix
> InstalledDir: /usr/bin
> Configuration file: /etc/clang/x86_64-redhat-linux-gnu-clang.cfg
>
> $ make LLVM=1 -j$(nproc)
> [...] # ok
>
> $ make LLVM=1 -C tools/testing/selftests/bpf -j$(nproc)
>
> [...] # somewhere in the middle
>
> LIB liburandom_read.so
> clang: error: invalid linker name in argument '-fuse-ld=ld.lld'
> make: *** [Makefile:256: /home/isolodrai/workspace/review/linux/tools/testing/selftests/bpf/liburandom_read.so] Error 1
> make: Leaving directory '/home/isolodrai/workspace/review/linux/tools/testing/selftests/bpf'
>
> [...]
>
> Or a simpler reproducer:
>
> $ make LLVM=1 OUTPUT=/tmp/out /tmp/out/liburandom_read.so
> LIB liburandom_read.so
> clang: error: invalid linker name in argument '-fuse-ld=ld.lld'
> make: *** [Makefile:256: /tmp/out/liburandom_read.so] Error 1
>
> $ make LLVM=-22 OUTPUT=/tmp/out /tmp/out/liburandom_read.so
> LIB liburandom_read.so
> clang-22: error: invalid linker name in argument '-fuse-ld=ld.lld-22'
> make: *** [Makefile:256: /tmp/out/liburandom_read.so] Error 1
>
> I tried your patches, and only then noticed BPF CI caught this too:
> https://github.com/kernel-patches/bpf/actions/runs/25943477658/job/76267174885?pr=12082
>
Thanks for testing. Yeah looks like I made a mistake here testing the
various different formats of LLD. Converting it to a full path works
with both prefixed and postfixed versions, and that's what's already
done for non x86/riscv so I'll do that.
>> -Wl,--version-script=liburandom_read.map \
>> -fPIC -shared -o $@
>>
>> @@ -268,7 +268,7 @@ $(OUTPUT)/urandom_read: urandom_read.c urandom_read_aux.c $(OUTPUT)/liburandom_r
>> $(filter-out -static,$(CFLAGS) $(LDFLAGS)) $(filter %.c,$^) \
>> -Wno-unused-command-line-argument \
>> -lurandom_read $(filter-out -static,$(LDLIBS)) -L$(OUTPUT) \
>> - -fuse-ld=$(LLD) -Wl,-znoseparate-code -Wl,--build-id=sha1 \
>> + -fuse-ld=$(USE_LD) -Wl,-znoseparate-code -Wl,--build-id=sha1 \
>> -Wl,-rpath=. -o $@
>>
>> $(OUTPUT)/sign-file: ../../../../scripts/sign-file.c
>>
>
^ permalink raw reply
* [PATCH v2 6/6] tools/build: selftests: Remove some duplicate toolchain definitions
From: James Clark @ 2026-05-18 9:03 UTC (permalink / raw)
To: Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
Jiri Kosina, Benjamin Tissoires, Shuah Khan, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
Andrii Nakryiko, Eduard Zingerman, Alexei Starovoitov,
Daniel Borkmann, Martin KaFai Lau, Kumar Kartikeya Dwivedi,
Song Liu, Yonghong Song, ihor.solodrai
Cc: linux-kernel, llvm, linux-input, linux-kselftest, bpf,
linux-perf-users, James Clark
In-Reply-To: <20260518-james-perf-llvm-version-v2-0-f12cc4f031d8@linaro.org>
Try to remove some, but not all duplicate toolchain definitions. In
these instances, their makefiles already include
tools/scripts/Makefile.include which defines these in a consistent way.
STRIP is the only one that was set with an '=', but I don't think it
was significant so that difference can be dropped.
Signed-off-by: James Clark <james.clark@linaro.org>
---
tools/bpf/resolve_btfids/Makefile | 3 ---
tools/lib/api/Makefile | 4 ----
tools/lib/subcmd/Makefile | 4 ----
tools/lib/symbol/Makefile | 4 ----
tools/perf/Makefile.perf | 6 ------
tools/testing/selftests/bpf/Makefile | 1 -
6 files changed, 22 deletions(-)
diff --git a/tools/bpf/resolve_btfids/Makefile b/tools/bpf/resolve_btfids/Makefile
index 7672208f65e4..6fdb6302e0a2 100644
--- a/tools/bpf/resolve_btfids/Makefile
+++ b/tools/bpf/resolve_btfids/Makefile
@@ -20,9 +20,6 @@ HOST_OVERRIDES := AR="$(HOSTAR)" CC="$(HOSTCC)" LD="$(HOSTLD)" ARCH="$(HOSTARCH)
CROSS_COMPILE="" CLANG_CROSS_FLAGS="" EXTRA_CFLAGS="$(HOSTCFLAGS)"
RM ?= rm
-HOSTCC ?= gcc
-HOSTLD ?= ld
-HOSTAR ?= ar
HOSTPKG_CONFIG ?= pkg-config
CROSS_COMPILE =
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index 8665c799e0fa..a228fdb5adba 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -9,10 +9,6 @@ srctree := $(patsubst %/,%,$(dir $(srctree)))
#$(info Determined 'srctree' to be $(srctree))
endif
-CC ?= $(CROSS_COMPILE)gcc
-AR ?= $(CROSS_COMPILE)ar
-LD ?= $(CROSS_COMPILE)ld
-
MAKEFLAGS += --no-print-directory
INSTALL = install
diff --git a/tools/lib/subcmd/Makefile b/tools/lib/subcmd/Makefile
index 8703ab487b68..9f1ddcf0504d 100644
--- a/tools/lib/subcmd/Makefile
+++ b/tools/lib/subcmd/Makefile
@@ -9,10 +9,6 @@ srctree := $(patsubst %/,%,$(dir $(srctree)))
#$(info Determined 'srctree' to be $(srctree))
endif
-CC ?= $(CROSS_COMPILE)gcc
-LD ?= $(CROSS_COMPILE)ld
-AR ?= $(CROSS_COMPILE)ar
-
RM = rm -f
MAKEFLAGS += --no-print-directory
diff --git a/tools/lib/symbol/Makefile b/tools/lib/symbol/Makefile
index 426b845edfac..d692abe8add6 100644
--- a/tools/lib/symbol/Makefile
+++ b/tools/lib/symbol/Makefile
@@ -9,10 +9,6 @@ srctree := $(patsubst %/,%,$(dir $(srctree)))
#$(info Determined 'srctree' to be $(srctree))
endif
-CC ?= $(CROSS_COMPILE)gcc
-AR ?= $(CROSS_COMPILE)ar
-LD ?= $(CROSS_COMPILE)ld
-
MAKEFLAGS += --no-print-directory
INSTALL = install
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 63276bf55856..948abfd2ee8d 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -174,11 +174,6 @@ endef
LD += $(EXTRA_LDFLAGS)
-HOSTCC ?= gcc
-HOSTLD ?= ld
-HOSTAR ?= ar
-CLANG ?= clang
-
# Some distros provide the command $(CROSS_COMPILE)pkg-config for
# searching packges installed with Multiarch. Use it for cross
# compilation if it is existed.
@@ -213,7 +208,6 @@ FIND = find
INSTALL = install
FLEX ?= flex
BISON ?= bison
-STRIP = strip
AWK = awk
# include Makefile.config by default and rule out
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 836e783f0170..f038642b283f 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -3,7 +3,6 @@ include ../../../build/Build.include
include ../../../scripts/Makefile.arch
include ../../../scripts/Makefile.include
-CXX ?= $(CROSS_COMPILE)g++
OBJCOPY ?= $(CROSS_COMPILE)objcopy
CURDIR := $(abspath .)
--
2.34.1
^ permalink raw reply related
* [PATCH v2 5/6] tools/build: selftests: Allow versioning LLVM lld
From: James Clark @ 2026-05-18 9:03 UTC (permalink / raw)
To: Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
Jiri Kosina, Benjamin Tissoires, Shuah Khan, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
Andrii Nakryiko, Eduard Zingerman, Alexei Starovoitov,
Daniel Borkmann, Martin KaFai Lau, Kumar Kartikeya Dwivedi,
Song Liu, Yonghong Song, ihor.solodrai
Cc: linux-kernel, llvm, linux-input, linux-kselftest, bpf,
linux-perf-users, James Clark
In-Reply-To: <20260518-james-perf-llvm-version-v2-0-f12cc4f031d8@linaro.org>
Building with LLVM=... could result in a different version of lld being
used than the main toolchain for liburandom_read.so because it's
hardcoded to "lld" in this makefile.
Make it consistent with the rest of the LLVM toolchain by adding an LLD
variable to Makefile.include. Keep the fallback for other architectures
in tools/testing/selftests/bpf/Makefile as it seems like it's something
specific to this make rule and shouldn't be global.
Clang only accepts either a full path to "/x/x/ld.lld" or "lld-15" style
inputs to "-fuse-ld=", so the only way to make it work with both
prefixed and postfixed paths is to always take the full path. Also I
don't think the original use of "lld" over "ld.lld" was significant as
this is always a linux build, so that can be changed to make it work in
both cases.
Signed-off-by: James Clark <james.clark@linaro.org>
---
tools/scripts/Makefile.include | 2 ++
tools/testing/selftests/bpf/Makefile | 8 ++++----
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 380ad84ac51e..5c2d505cba62 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -67,6 +67,7 @@ ifneq ($(LLVM),)
$(call allow-override,HOSTAR,$(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX))
$(call allow-override,LD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX))
$(call allow-override,HOSTLD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX))
+ $(call allow-override,LLD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX))
$(call allow-override,CXX,$(LLVM_PREFIX)clang++$(LLVM_SUFFIX))
$(call allow-override,STRIP,$(LLVM_PREFIX)llvm-strip$(LLVM_SUFFIX))
$(call allow-override,LLVM_STRIP,$(LLVM_PREFIX)llvm-strip$(LLVM_SUFFIX))
@@ -91,6 +92,7 @@ else
# Some tools still require Clang, LLC and/or LLVM utils
$(call allow-override,CLANG,clang)
$(call allow-override,LLC,llc)
+ $(call allow-override,LLD,ld.lld)
$(call allow-override,LLVM_CONFIG,llvm-config)
$(call allow-override,LLVM_OBJCOPY,llvm-objcopy)
$(call allow-override,LLVM_STRIP,llvm-strip)
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 6ef6872adbc3..836e783f0170 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -245,9 +245,9 @@ $(OUTPUT)/%:%.c
# LLVM's ld.lld doesn't support all the architectures, so use it only on x86
ifeq ($(SRCARCH),$(filter $(SRCARCH),x86 riscv))
-LLD := lld
+USE_LD := $(shell command -v $(LLD))
else
-LLD := $(shell command -v $(LD))
+USE_LD := $(shell command -v $(LD))
endif
# Filter out -static for liburandom_read.so and its dependent targets so that static builds
@@ -258,7 +258,7 @@ $(OUTPUT)/liburandom_read.so: urandom_read_lib1.c urandom_read_lib2.c liburandom
$(filter-out -static,$(CFLAGS) $(LDFLAGS)) \
$(filter %.c,$^) $(filter-out -static,$(LDLIBS)) \
-Wno-unused-command-line-argument \
- -fuse-ld=$(LLD) -Wl,-znoseparate-code -Wl,--build-id=sha1 \
+ -fuse-ld=$(USE_LD) -Wl,-znoseparate-code -Wl,--build-id=sha1 \
-Wl,--version-script=liburandom_read.map \
-fPIC -shared -o $@
@@ -268,7 +268,7 @@ $(OUTPUT)/urandom_read: urandom_read.c urandom_read_aux.c $(OUTPUT)/liburandom_r
$(filter-out -static,$(CFLAGS) $(LDFLAGS)) $(filter %.c,$^) \
-Wno-unused-command-line-argument \
-lurandom_read $(filter-out -static,$(LDLIBS)) -L$(OUTPUT) \
- -fuse-ld=$(LLD) -Wl,-znoseparate-code -Wl,--build-id=sha1 \
+ -fuse-ld=$(USE_LD) -Wl,-znoseparate-code -Wl,--build-id=sha1 \
-Wl,-rpath=. -o $@
$(OUTPUT)/sign-file: ../../../../scripts/sign-file.c
--
2.34.1
^ permalink raw reply related
* [PATCH v2 4/6] tools/build: Allow versioning LLVM readelf
From: James Clark @ 2026-05-18 9:03 UTC (permalink / raw)
To: Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
Jiri Kosina, Benjamin Tissoires, Shuah Khan, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
Andrii Nakryiko, Eduard Zingerman, Alexei Starovoitov,
Daniel Borkmann, Martin KaFai Lau, Kumar Kartikeya Dwivedi,
Song Liu, Yonghong Song, ihor.solodrai
Cc: linux-kernel, llvm, linux-input, linux-kselftest, bpf,
linux-perf-users, James Clark
In-Reply-To: <20260518-james-perf-llvm-version-v2-0-f12cc4f031d8@linaro.org>
Documentation/kbuild/llvm.rst mentions that readelf is included in the
LLVM toolchain, but it's not currently included in this block.
Add it so that LLVM=... options also apply to readelf. Users in tools/
were Perf which was hardcoding it, and another was the BPF makefile.
Both already include Makefile.include so convert them to use the new
variable.
It also didn't have the cross compile prefix, so either readelf didn't
mind opening cross binaries, or it wasn't working for cross builds.
Signed-off-by: James Clark <james.clark@linaro.org>
---
tools/lib/bpf/Makefile | 8 ++++----
tools/perf/Makefile.perf | 1 -
tools/scripts/Makefile.include | 2 ++
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index 168140f8e646..180dca9c57c8 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -114,12 +114,12 @@ PC_FILE := $(addprefix $(OUTPUT),$(PC_FILE))
TAGS_PROG := $(if $(shell which etags 2>/dev/null),etags,ctags)
-GLOBAL_SYM_COUNT = $(shell readelf -s --wide $(BPF_IN_SHARED) | \
+GLOBAL_SYM_COUNT = $(shell $(READELF) -s --wide $(BPF_IN_SHARED) | \
cut -d "@" -f1 | sed 's/_v[0-9]_[0-9]_[0-9].*//' | \
sed 's/\[.*\]//' | \
awk '/GLOBAL/ && /DEFAULT/ && !/UND|ABS/ {print $$NF}' | \
sort -u | wc -l)
-VERSIONED_SYM_COUNT = $(shell readelf --dyn-syms --wide $(OUTPUT)libbpf.so | \
+VERSIONED_SYM_COUNT = $(shell $(READELF) --dyn-syms --wide $(OUTPUT)libbpf.so | \
sed 's/\[.*\]//' | \
awk '/GLOBAL/ && /DEFAULT/ && !/UND|ABS/ {print $$NF}' | \
grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | sort -u | wc -l)
@@ -182,12 +182,12 @@ check_abi: $(OUTPUT)libbpf.so $(VERSION_SCRIPT)
"versioned symbols in $^ ($(VERSIONED_SYM_COUNT))." \
"Please make sure all LIBBPF_API symbols are" \
"versioned in $(VERSION_SCRIPT)." >&2; \
- readelf -s --wide $(BPF_IN_SHARED) | \
+ $(READELF) -s --wide $(BPF_IN_SHARED) | \
cut -d "@" -f1 | sed 's/_v[0-9]_[0-9]_[0-9].*//' | \
sed 's/\[.*\]//' | \
awk '/GLOBAL/ && /DEFAULT/ && !/UND/ {print $$NF}'| \
sort -u > $(OUTPUT)libbpf_global_syms.tmp; \
- readelf --dyn-syms --wide $(OUTPUT)libbpf.so | \
+ $(READELF) --dyn-syms --wide $(OUTPUT)libbpf.so | \
sed 's/\[.*\]//' | \
awk '/GLOBAL/ && /DEFAULT/ && !/UND|ABS/ {print $$NF}'| \
grep -Eo '[^ ]+@LIBBPF_' | cut -d@ -f1 | \
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 0aba14f22a06..63276bf55856 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -215,7 +215,6 @@ FLEX ?= flex
BISON ?= bison
STRIP = strip
AWK = awk
-READELF ?= readelf
# include Makefile.config by default and rule out
# non-config cases
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index e81e5b479c56..380ad84ac51e 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -73,6 +73,7 @@ ifneq ($(LLVM),)
$(call allow-override,LLC,$(LLVM_PREFIX)llc$(LLVM_SUFFIX))
$(call allow-override,LLVM_CONFIG,$(LLVM_PREFIX)llvm-config$(LLVM_SUFFIX))
$(call allow-override,LLVM_OBJCOPY,$(LLVM_PREFIX)llvm-objcopy$(LLVM_SUFFIX))
+ $(call allow-override,READELF,$(LLVM_PREFIX)llvm-readelf$(LLVM_SUFFIX))
else
# Allow setting various cross-compile vars or setting CROSS_COMPILE as a prefix.
$(call allow-override,CC,$(CROSS_COMPILE)gcc)
@@ -80,6 +81,7 @@ else
$(call allow-override,LD,$(CROSS_COMPILE)ld)
$(call allow-override,CXX,$(CROSS_COMPILE)g++)
$(call allow-override,STRIP,$(CROSS_COMPILE)strip)
+ $(call allow-override,READELF,$(CROSS_COMPILE)readelf)
# Host versions aren't prefixed
$(call allow-override,HOSTAR,ar)
--
2.34.1
^ permalink raw reply related
* [PATCH v2 3/6] selftests: Remove unused LLD variable
From: James Clark @ 2026-05-18 9:03 UTC (permalink / raw)
To: Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
Jiri Kosina, Benjamin Tissoires, Shuah Khan, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
Andrii Nakryiko, Eduard Zingerman, Alexei Starovoitov,
Daniel Borkmann, Martin KaFai Lau, Kumar Kartikeya Dwivedi,
Song Liu, Yonghong Song, ihor.solodrai
Cc: linux-kernel, llvm, linux-input, linux-kselftest, bpf,
linux-perf-users, James Clark
In-Reply-To: <20260518-james-perf-llvm-version-v2-0-f12cc4f031d8@linaro.org>
This file was mostly copied from selftests/bpf/Makefile, but the LLD
variable is not used here. Also, this copied block didn't get the same
fixes as the original one did later.
Remove it to avoid confusion and so future fixes don't have to be in two
places.
Signed-off-by: James Clark <james.clark@linaro.org>
---
tools/testing/selftests/hid/Makefile | 7 -------
1 file changed, 7 deletions(-)
diff --git a/tools/testing/selftests/hid/Makefile b/tools/testing/selftests/hid/Makefile
index 50ec9e0406ab..96071b4800e8 100644
--- a/tools/testing/selftests/hid/Makefile
+++ b/tools/testing/selftests/hid/Makefile
@@ -105,13 +105,6 @@ $(MAKE_DIRS):
$(call msg,MKDIR,,$@)
$(Q)mkdir -p $@
-# LLVM's ld.lld doesn't support all the architectures, so use it only on x86
-ifeq ($(SRCARCH),x86)
-LLD := lld
-else
-LLD := ld
-endif
-
DEFAULT_BPFTOOL := $(HOST_SCRATCH_DIR)/sbin/bpftool
TEST_GEN_PROGS_EXTENDED += $(DEFAULT_BPFTOOL)
--
2.34.1
^ permalink raw reply related
* [PATCH v2 2/6] tools/build: Indent if else blocks
From: James Clark @ 2026-05-18 9:03 UTC (permalink / raw)
To: Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
Jiri Kosina, Benjamin Tissoires, Shuah Khan, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
Andrii Nakryiko, Eduard Zingerman, Alexei Starovoitov,
Daniel Borkmann, Martin KaFai Lau, Kumar Kartikeya Dwivedi,
Song Liu, Yonghong Song, ihor.solodrai
Cc: linux-kernel, llvm, linux-input, linux-kselftest, bpf,
linux-perf-users, James Clark
In-Reply-To: <20260518-james-perf-llvm-version-v2-0-f12cc4f031d8@linaro.org>
These blocks are quite big and unreadable without indentation. Indent
them.
No functional changes intended.
Signed-off-by: James Clark <james.clark@linaro.org>
---
tools/scripts/Makefile.include | 76 +++++++++++++++++++++---------------------
1 file changed, 38 insertions(+), 38 deletions(-)
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 7022e78208a2..e81e5b479c56 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -52,46 +52,46 @@ define allow-override
endef
ifneq ($(LLVM),)
-ifneq ($(filter %/,$(LLVM)),)
-LLVM_PREFIX := $(LLVM)
-else ifneq ($(filter -%,$(LLVM)),)
-LLVM_SUFFIX := $(LLVM)
-else ifneq ($(LLVM),1)
-$(error Invalid value for LLVM, see Documentation/kbuild/llvm.rst)
-endif
+ ifneq ($(filter %/,$(LLVM)),)
+ LLVM_PREFIX := $(LLVM)
+ else ifneq ($(filter -%,$(LLVM)),)
+ LLVM_SUFFIX := $(LLVM)
+ else ifneq ($(LLVM),1)
+ $(error Invalid value for LLVM, see Documentation/kbuild/llvm.rst)
+ endif
-$(call allow-override,CC,$(LLVM_PREFIX)clang$(LLVM_SUFFIX))
-$(call allow-override,CLANG,$(LLVM_PREFIX)clang$(LLVM_SUFFIX))
-$(call allow-override,HOSTCC,$(LLVM_PREFIX)clang$(LLVM_SUFFIX))
-$(call allow-override,AR,$(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX))
-$(call allow-override,HOSTAR,$(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX))
-$(call allow-override,LD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX))
-$(call allow-override,HOSTLD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX))
-$(call allow-override,CXX,$(LLVM_PREFIX)clang++$(LLVM_SUFFIX))
-$(call allow-override,STRIP,$(LLVM_PREFIX)llvm-strip$(LLVM_SUFFIX))
-$(call allow-override,LLVM_STRIP,$(LLVM_PREFIX)llvm-strip$(LLVM_SUFFIX))
-$(call allow-override,LLC,$(LLVM_PREFIX)llc$(LLVM_SUFFIX))
-$(call allow-override,LLVM_CONFIG,$(LLVM_PREFIX)llvm-config$(LLVM_SUFFIX))
-$(call allow-override,LLVM_OBJCOPY,$(LLVM_PREFIX)llvm-objcopy$(LLVM_SUFFIX))
+ $(call allow-override,CC,$(LLVM_PREFIX)clang$(LLVM_SUFFIX))
+ $(call allow-override,CLANG,$(LLVM_PREFIX)clang$(LLVM_SUFFIX))
+ $(call allow-override,HOSTCC,$(LLVM_PREFIX)clang$(LLVM_SUFFIX))
+ $(call allow-override,AR,$(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX))
+ $(call allow-override,HOSTAR,$(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX))
+ $(call allow-override,LD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX))
+ $(call allow-override,HOSTLD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX))
+ $(call allow-override,CXX,$(LLVM_PREFIX)clang++$(LLVM_SUFFIX))
+ $(call allow-override,STRIP,$(LLVM_PREFIX)llvm-strip$(LLVM_SUFFIX))
+ $(call allow-override,LLVM_STRIP,$(LLVM_PREFIX)llvm-strip$(LLVM_SUFFIX))
+ $(call allow-override,LLC,$(LLVM_PREFIX)llc$(LLVM_SUFFIX))
+ $(call allow-override,LLVM_CONFIG,$(LLVM_PREFIX)llvm-config$(LLVM_SUFFIX))
+ $(call allow-override,LLVM_OBJCOPY,$(LLVM_PREFIX)llvm-objcopy$(LLVM_SUFFIX))
else
-# Allow setting various cross-compile vars or setting CROSS_COMPILE as a prefix.
-$(call allow-override,CC,$(CROSS_COMPILE)gcc)
-$(call allow-override,AR,$(CROSS_COMPILE)ar)
-$(call allow-override,LD,$(CROSS_COMPILE)ld)
-$(call allow-override,CXX,$(CROSS_COMPILE)g++)
-$(call allow-override,STRIP,$(CROSS_COMPILE)strip)
-
-# Host versions aren't prefixed
-$(call allow-override,HOSTAR,ar)
-$(call allow-override,HOSTCC,gcc)
-$(call allow-override,HOSTLD,ld)
-
-# Some tools still require Clang, LLC and/or LLVM utils
-$(call allow-override,CLANG,clang)
-$(call allow-override,LLC,llc)
-$(call allow-override,LLVM_CONFIG,llvm-config)
-$(call allow-override,LLVM_OBJCOPY,llvm-objcopy)
-$(call allow-override,LLVM_STRIP,llvm-strip)
+ # Allow setting various cross-compile vars or setting CROSS_COMPILE as a prefix.
+ $(call allow-override,CC,$(CROSS_COMPILE)gcc)
+ $(call allow-override,AR,$(CROSS_COMPILE)ar)
+ $(call allow-override,LD,$(CROSS_COMPILE)ld)
+ $(call allow-override,CXX,$(CROSS_COMPILE)g++)
+ $(call allow-override,STRIP,$(CROSS_COMPILE)strip)
+
+ # Host versions aren't prefixed
+ $(call allow-override,HOSTAR,ar)
+ $(call allow-override,HOSTCC,gcc)
+ $(call allow-override,HOSTLD,ld)
+
+ # Some tools still require Clang, LLC and/or LLVM utils
+ $(call allow-override,CLANG,clang)
+ $(call allow-override,LLC,llc)
+ $(call allow-override,LLVM_CONFIG,llvm-config)
+ $(call allow-override,LLVM_OBJCOPY,llvm-objcopy)
+ $(call allow-override,LLVM_STRIP,llvm-strip)
endif
CC_NO_CLANG := $(shell $(CC) -dM -E -x c /dev/null | grep -Fq "__clang__"; echo $$?)
--
2.34.1
^ permalink raw reply related
* [PATCH v2 1/6] tools/build: Allow versioning of all LLVM tools defined in Makefile.include
From: James Clark @ 2026-05-18 9:03 UTC (permalink / raw)
To: Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
Jiri Kosina, Benjamin Tissoires, Shuah Khan, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
Andrii Nakryiko, Eduard Zingerman, Alexei Starovoitov,
Daniel Borkmann, Martin KaFai Lau, Kumar Kartikeya Dwivedi,
Song Liu, Yonghong Song, ihor.solodrai
Cc: linux-kernel, llvm, linux-input, linux-kselftest, bpf,
linux-perf-users, James Clark
In-Reply-To: <20260518-james-perf-llvm-version-v2-0-f12cc4f031d8@linaro.org>
The version of LLVM tools can be given on the build command with
LLVM=-15, but this isn't applied to all tools. For example $(CC) gets
versioned, but $(CLANG) doesn't. This causes a Perf build with LTO=1 to
fail with an error about mixed clang versions:
ld.lld: error: libperf/core.o: Unknown attribute kind (86)
(Producer: 'LLVM18.1.8' Reader: 'LLVM 15.0.7')
This file has two "ifneq ($(LLVM),)" blocks adjacent to each other, so
merge these blocks making it obvious that all tools should be versioned
consistently and there is nothing special about each block.
This also reveals that ?= and "allow-override" are used inconsistently
between the blocks. "allow-override" is technically only required for
builtin variables, but isn't only used on them, and doesn't do any harm
if used on a non-builtin. Make them all "allow-override" for
consistency. The only functional difference this will cause is if there
is a file level definition of one of the variables followed by an
"#include of Makefile.include" which will now overwrite. But this isn't
done and in a later commit some of the duplicate definitions will be
removed for good measure.
There are also some other LLVM tools that are not defined here and will
be moved in a later commit.
Signed-off-by: James Clark <james.clark@linaro.org>
---
tools/scripts/Makefile.include | 37 ++++++++++++++++++++-----------------
1 file changed, 20 insertions(+), 17 deletions(-)
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index 41971a68972d..7022e78208a2 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -61,10 +61,18 @@ $(error Invalid value for LLVM, see Documentation/kbuild/llvm.rst)
endif
$(call allow-override,CC,$(LLVM_PREFIX)clang$(LLVM_SUFFIX))
+$(call allow-override,CLANG,$(LLVM_PREFIX)clang$(LLVM_SUFFIX))
+$(call allow-override,HOSTCC,$(LLVM_PREFIX)clang$(LLVM_SUFFIX))
$(call allow-override,AR,$(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX))
+$(call allow-override,HOSTAR,$(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX))
$(call allow-override,LD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX))
+$(call allow-override,HOSTLD,$(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX))
$(call allow-override,CXX,$(LLVM_PREFIX)clang++$(LLVM_SUFFIX))
$(call allow-override,STRIP,$(LLVM_PREFIX)llvm-strip$(LLVM_SUFFIX))
+$(call allow-override,LLVM_STRIP,$(LLVM_PREFIX)llvm-strip$(LLVM_SUFFIX))
+$(call allow-override,LLC,$(LLVM_PREFIX)llc$(LLVM_SUFFIX))
+$(call allow-override,LLVM_CONFIG,$(LLVM_PREFIX)llvm-config$(LLVM_SUFFIX))
+$(call allow-override,LLVM_OBJCOPY,$(LLVM_PREFIX)llvm-objcopy$(LLVM_SUFFIX))
else
# Allow setting various cross-compile vars or setting CROSS_COMPILE as a prefix.
$(call allow-override,CC,$(CROSS_COMPILE)gcc)
@@ -72,26 +80,21 @@ $(call allow-override,AR,$(CROSS_COMPILE)ar)
$(call allow-override,LD,$(CROSS_COMPILE)ld)
$(call allow-override,CXX,$(CROSS_COMPILE)g++)
$(call allow-override,STRIP,$(CROSS_COMPILE)strip)
-endif
-
-CC_NO_CLANG := $(shell $(CC) -dM -E -x c /dev/null | grep -Fq "__clang__"; echo $$?)
-ifneq ($(LLVM),)
-HOSTAR ?= $(LLVM_PREFIX)llvm-ar$(LLVM_SUFFIX)
-HOSTCC ?= $(LLVM_PREFIX)clang$(LLVM_SUFFIX)
-HOSTLD ?= $(LLVM_PREFIX)ld.lld$(LLVM_SUFFIX)
-else
-HOSTAR ?= ar
-HOSTCC ?= gcc
-HOSTLD ?= ld
+# Host versions aren't prefixed
+$(call allow-override,HOSTAR,ar)
+$(call allow-override,HOSTCC,gcc)
+$(call allow-override,HOSTLD,ld)
+
+# Some tools still require Clang, LLC and/or LLVM utils
+$(call allow-override,CLANG,clang)
+$(call allow-override,LLC,llc)
+$(call allow-override,LLVM_CONFIG,llvm-config)
+$(call allow-override,LLVM_OBJCOPY,llvm-objcopy)
+$(call allow-override,LLVM_STRIP,llvm-strip)
endif
-# Some tools require Clang, LLC and/or LLVM utils
-CLANG ?= clang
-LLC ?= llc
-LLVM_CONFIG ?= llvm-config
-LLVM_OBJCOPY ?= llvm-objcopy
-LLVM_STRIP ?= llvm-strip
+CC_NO_CLANG := $(shell $(CC) -dM -E -x c /dev/null | grep -Fq "__clang__"; echo $$?)
# Some tools require bpftool
SYSTEM_BPFTOOL ?= bpftool
--
2.34.1
^ permalink raw reply related
* [PATCH v2 0/6] tools/build: Allow versioning of all LLVM tools
From: James Clark @ 2026-05-18 9:03 UTC (permalink / raw)
To: Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
Jiri Kosina, Benjamin Tissoires, Shuah Khan, Peter Zijlstra,
Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
Andrii Nakryiko, Eduard Zingerman, Alexei Starovoitov,
Daniel Borkmann, Martin KaFai Lau, Kumar Kartikeya Dwivedi,
Song Liu, Yonghong Song, ihor.solodrai
Cc: linux-kernel, llvm, linux-input, linux-kselftest, bpf,
linux-perf-users, James Clark
I ran into the build issue mentioned in the first commit, because using
an option like LLVM=-15 is a documented way to build [1], but only
some of the LLVM tools defined in tools/ support this.
After fixing that, a lot of other tidyups fell out. I didn't go too far,
for example some selftests include tools/testing/selftests/lib.mk which
reimplements some of the LLVM_SUFFIX stuff, but other selftests include
tools/scripts/Makefile.include and I stopped before touching the former.
Some other non build scripts hard code toolchains and I didn't touch
those either, this change is only focused on things that already
include Makefile.include.
[1]: Documentation/kbuild/llvm.rst
Signed-off-by: James Clark <james.clark@linaro.org>
---
Changes in v2:
- Fix selftests/bpf build. LLD needs to take the full path to be used
with -fuse-ld=
- Link to v1: https://lore.kernel.org/r/20260514-james-perf-llvm-version-v1-0-6cac1a9a4c8d@linaro.org
---
James Clark (6):
tools/build: Allow versioning of all LLVM tools defined in Makefile.include
tools/build: Indent if else blocks
selftests: Remove unused LLD variable
tools/build: Allow versioning LLVM readelf
tools/build: selftests: Allow versioning LLVM lld
tools/build: selftests: Remove some duplicate toolchain definitions
tools/bpf/resolve_btfids/Makefile | 3 --
tools/lib/api/Makefile | 4 --
tools/lib/bpf/Makefile | 8 ++--
tools/lib/subcmd/Makefile | 4 --
tools/lib/symbol/Makefile | 4 --
tools/perf/Makefile.perf | 7 ----
tools/scripts/Makefile.include | 77 ++++++++++++++++++++----------------
tools/testing/selftests/bpf/Makefile | 9 ++---
tools/testing/selftests/hid/Makefile | 7 ----
9 files changed, 50 insertions(+), 73 deletions(-)
---
base-commit: 09d355618f7ccc27ffc7fc668b2e232872962079
change-id: 20260511-james-perf-llvm-version-43ab1cb5bc7d
Best regards,
--
James Clark <james.clark@linaro.org>
^ permalink raw reply
* Re: [PATCH v1] Input: Use named initializers for arrays of i2c_device_data
From: Uwe Kleine-König (The Capable Hub) @ 2026-05-18 7:56 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Geert Uytterhoeven, Dmitry Torokhov, Anshul Dalal,
Michael Hennerich, Yassine Oudjana, Linus Walleij, Nicolas Ferre,
Alexandre Belloni, Claudiu Beznea, Support Opensource, Nick Dyer,
Hans de Goede, Job Noorman, Mika Penttilä, Maxime Coquelin,
Alexandre Torgue, Kees Cook, bui duc phuc, Thorsten Blum,
Yauhen Kharuzhy, Sakari Ailus, Marco Crivellari, Minseong Kim,
Ingo Molnar, Thomas Gleixner, Oleh Kuzhylnyi, Marek Vasut,
Krzysztof Kozlowski, Geert Uytterhoeven, Josua Mayer,
Michael Tretter, Jeff LaBundy, Javier Carrasco, David Heidelberg,
Petr Hodina, Svyatoslav Ryhel, Johannes Kirchmair, Xichao Zhao,
linux-input, linux-kernel, linux-arm-kernel, platform-driver-x86,
linux-stm32
In-Reply-To: <agrAG3cLjEAPV90B@ashevche-desk.local>
[-- Attachment #1: Type: text/plain, Size: 1215 bytes --]
On Mon, May 18, 2026 at 10:30:35AM +0300, Andy Shevchenko wrote:
> On Mon, May 18, 2026 at 09:24:35AM +0200, Geert Uytterhoeven wrote:
> > Hi Uwe,
> >
> > On Fri, 15 May 2026 at 18:48, Uwe Kleine-König (The Capable Hub)
> > <u.kleine-koenig@baylibre.com> wrote:
> > > My additional motivation for this effort is CHERI[1]. This is a hardware
> >
> > Nice!
> >
> > > extension that uses 128 bit pointers but unsigned long is still 64 bit.
> > > So with CHERI you cannot store pointers in unsigned long variables.
> >
> > Good luck fixing all implicit assumptions about this in the kernel!
> > Also, good luck convincing people to use uintptr_t instead ;-)
> >
> > https://lore.kernel.org/all/CAHk-=wj2OHy-5e+srG1fy+ZU00TmZ1NFp6kFLbVLMXHe7A1d-g@mail.gmail.com
>
> Yeah, I believe Linus will have a strong opinion about all this CHERI stuff :-)
> But let see, it might be surprising turn around.
Yeah, it's not yet the time to start that discussion, I want to have the
patch stack in a better state before that.
I think the strongest argument will be that
"unsigned long" [...] is an integer type large enough to hold a
pointer.
just isn't true for CHERI.
Best regards
Uwe
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH v1] Input: Use named initializers for arrays of i2c_device_data
From: Geert Uytterhoeven @ 2026-05-18 7:24 UTC (permalink / raw)
To: Uwe Kleine-König (The Capable Hub)
Cc: Dmitry Torokhov, Anshul Dalal, Michael Hennerich, Yassine Oudjana,
Linus Walleij, Nicolas Ferre, Alexandre Belloni, Claudiu Beznea,
Support Opensource, Nick Dyer, Hans de Goede, Job Noorman,
Mika Penttilä, Maxime Coquelin, Alexandre Torgue, Kees Cook,
bui duc phuc, Thorsten Blum, Yauhen Kharuzhy, Sakari Ailus,
Marco Crivellari, Minseong Kim, Ingo Molnar, Thomas Gleixner,
Oleh Kuzhylnyi, Marek Vasut, Krzysztof Kozlowski,
Geert Uytterhoeven, Josua Mayer, Michael Tretter, Jeff LaBundy,
Javier Carrasco, David Heidelberg, Petr Hodina, Svyatoslav Ryhel,
Johannes Kirchmair, Andy Shevchenko, Xichao Zhao, linux-input,
linux-kernel, linux-arm-kernel, platform-driver-x86, linux-stm32
In-Reply-To: <20260515164848.497608-2-u.kleine-koenig@baylibre.com>
Hi Uwe,
On Fri, 15 May 2026 at 18:48, Uwe Kleine-König (The Capable Hub)
<u.kleine-koenig@baylibre.com> wrote:
> My additional motivation for this effort is CHERI[1]. This is a hardware
Nice!
> extension that uses 128 bit pointers but unsigned long is still 64 bit.
> So with CHERI you cannot store pointers in unsigned long variables.
Good luck fixing all implicit assumptions about this in the kernel!
Also, good luck convincing people to use uintptr_t instead ;-)
https://lore.kernel.org/all/CAHk-=wj2OHy-5e+srG1fy+ZU00TmZ1NFp6kFLbVLMXHe7A1d-g@mail.gmail.com
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: [PATCH v1] Input: Use named initializers for arrays of i2c_device_data
From: Andy Shevchenko @ 2026-05-18 7:30 UTC (permalink / raw)
To: Geert Uytterhoeven
Cc: Uwe Kleine-König (The Capable Hub), Dmitry Torokhov,
Anshul Dalal, Michael Hennerich, Yassine Oudjana, Linus Walleij,
Nicolas Ferre, Alexandre Belloni, Claudiu Beznea,
Support Opensource, Nick Dyer, Hans de Goede, Job Noorman,
Mika Penttilä, Maxime Coquelin, Alexandre Torgue, Kees Cook,
bui duc phuc, Thorsten Blum, Yauhen Kharuzhy, Sakari Ailus,
Marco Crivellari, Minseong Kim, Ingo Molnar, Thomas Gleixner,
Oleh Kuzhylnyi, Marek Vasut, Krzysztof Kozlowski,
Geert Uytterhoeven, Josua Mayer, Michael Tretter, Jeff LaBundy,
Javier Carrasco, David Heidelberg, Petr Hodina, Svyatoslav Ryhel,
Johannes Kirchmair, Xichao Zhao, linux-input, linux-kernel,
linux-arm-kernel, platform-driver-x86, linux-stm32
In-Reply-To: <CAMuHMdWGSBbQtKaoFej1Qm-SUgDenLMDF0psD9o07wyHKu8A+w@mail.gmail.com>
On Mon, May 18, 2026 at 09:24:35AM +0200, Geert Uytterhoeven wrote:
> Hi Uwe,
>
> On Fri, 15 May 2026 at 18:48, Uwe Kleine-König (The Capable Hub)
> <u.kleine-koenig@baylibre.com> wrote:
> > My additional motivation for this effort is CHERI[1]. This is a hardware
>
> Nice!
>
> > extension that uses 128 bit pointers but unsigned long is still 64 bit.
> > So with CHERI you cannot store pointers in unsigned long variables.
>
> Good luck fixing all implicit assumptions about this in the kernel!
> Also, good luck convincing people to use uintptr_t instead ;-)
>
> https://lore.kernel.org/all/CAHk-=wj2OHy-5e+srG1fy+ZU00TmZ1NFp6kFLbVLMXHe7A1d-g@mail.gmail.com
Yeah, I believe Linus will have a strong opinion about all this CHERI stuff :-)
But let see, it might be surprising turn around.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH] Input: mtk-pmic-keys - use of_device_get_match_data()
From: Rosen Penev @ 2026-05-18 6:37 UTC (permalink / raw)
To: sashiko-reviews, Rosen Penev; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260518043409.EC97EC2BCB7@smtp.kernel.org>
On Sun May 17, 2026 at 9:34 PM PDT, sashiko-bot wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> - [High] Missing NULL check for of_device_get_match_data() result leads to NULL pointer dereference.
> - [High] Mismatch between child counting and iteration logic can cause out-of-bounds array accesses.
> --
>
> commit 0ee3fee49ccf02b7e629f90533e67fc9b40d2b9e
> Author: Rosen Penev <rosenp@gmail.com>
>
> Input: mtk-pmic-keys - use of_device_get_match_data()
>
> This commit simplifies the driver to fetch PMIC key register data directly
> using of_device_get_match_data(). It also removes the unneeded of_device.h
> include.
>
>> diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
>> index c78d9f6d97c4f..fd684ac169386 100644
>> --- a/drivers/input/keyboard/mtk-pmic-keys.c
>> +++ b/drivers/input/keyboard/mtk-pmic-keys.c
> [ ... ]
>> @@ -342,7 +339,7 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)
>>
>> keys->dev = &pdev->dev;
>> keys->regmap = pmic_chip->regmap;
>> - mtk_pmic_regs = of_id->data;
>> + mtk_pmic_regs = of_device_get_match_data(&pdev->dev);
>
> While this isn't a new issue introduced by this patch, can mtk_pmic_regs be
> NULL here if the device is bound manually via sysfs without a matching
> device tree node?
>
> If mtk_pmic_regs is NULL, it appears it is unconditionally dereferenced
> later when calling mtk_pmic_keys_lp_reset_setup().
>
> Would it make sense to add a check for !mtk_pmic_regs right after fetching
> the match data?
No because every compatible has a non NULL data component.
>
>
> Also, while reviewing this probe function, I noticed another pre-existing
> issue further down:
>
> keycount = of_get_available_child_count(node);
> if (keycount > MTK_PMIC_MAX_KEY_COUNT ||
> keycount > ARRAY_SIZE(irqnames)) {
> dev_err(keys->dev, "too many keys defined (%d)\n", keycount);
> return -EINVAL;
> }
>
> for_each_child_of_node_scoped(node, child) {
> keys->keys[index].regs = &mtk_pmic_regs->keys_regs[index];
>
> Is there a mismatch between the child counting and iteration logic?
>
> The validation check uses of_get_available_child_count(), which ignores
> disabled nodes. But the loop uses for_each_child_of_node_scoped(), which
> iterates over all children, including disabled ones.
>
> If a disabled child node exists in the device tree alongside available ones,
> could the loop execute more times than the initial validation accounted for?
> This might increment the index variable past the allocated array bounds,
> leading to out-of-bounds accesses on irqnames[] and keys->keys[].
>
> Would updating the loop to use for_each_available_child_of_node_scoped()
> prevent this?
Yes. Interesting that pre-existing issues are flagged...
^ permalink raw reply
* [PATCH v3] Input: elan_i2c - prevent division by zero on invalid device parameters
From: Ranjan Kumar @ 2026-05-18 6:26 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: bleung, bentiss, linux-input, linux-kernel, Ranjan Kumar
In-Reply-To: <20260515071052.7DDA0C2BCB0@smtp.kernel.org>
The Elan I2C touchpad driver queries the device for its physical
dimensions and trace counts to calculate the device resolution and width.
However, if the device firmware or device tree provides invalid zero
values for x_traces, y_traces, x_mm, or y_mm, it results in a fatal
division-by-zero exception leading to a kernel panic during device probe.
Add sanity checks to ensure these physical parameters are non-zero
before performing the division. If invalid trace values are detected,
log a warning and fall back to ETP_FWIDTH_REDUCE to prevent arithmetic
underflow during touch reporting. For invalid physical dimensions, fall
back to a safe default of 1.
This prevents the kernel panic while allowing the probe to complete
successfully. Completing the probe ensures the sysfs nodes are created,
keeping the firmware update path intact so a recovery firmware can be
flashed to the device.
Fixes: 6696777c6506 ("Input: add driver for Elan I2C/SMbus touchpad")
Fixes: e3a9a1290688 ("Input: elan_i2c - do not query the info if they are provided")
Signed-off-by: Ranjan Kumar <kumarranja@chromium.org>
---
Changes in v3:
- Changed trace fallback values from 1 to ETP_FWIDTH_REDUCE to prevent
an unsigned integer underflow in elan_report_absolute().
Changes in v2:
- Changed error handling from aborting probe with -EINVAL to logging a
warning and falling back to default values.
drivers/input/mouse/elan_i2c_core.c | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c
index fee1796da3d0..c64e1dd1e60b 100644
--- a/drivers/input/mouse/elan_i2c_core.c
+++ b/drivers/input/mouse/elan_i2c_core.c
@@ -425,8 +425,17 @@ static int elan_query_device_parameters(struct elan_tp_data *data)
if (error)
return error;
}
- data->width_x = data->max_x / x_traces;
- data->width_y = data->max_y / y_traces;
+
+ if (unlikely(x_traces == 0 || y_traces == 0)) {
+ dev_warn(&client->dev,
+ "invalid trace numbers: x=%u, y=%u\n",
+ x_traces, y_traces);
+ data->width_x = ETP_FWIDTH_REDUCE;
+ data->width_y = ETP_FWIDTH_REDUCE;
+ } else {
+ data->width_x = data->max_x / x_traces;
+ data->width_y = data->max_y / y_traces;
+ }
if (device_property_read_u32(&client->dev,
"touchscreen-x-mm", &x_mm) ||
@@ -440,8 +449,16 @@ static int elan_query_device_parameters(struct elan_tp_data *data)
data->x_res = elan_convert_resolution(hw_x_res, data->pattern);
data->y_res = elan_convert_resolution(hw_y_res, data->pattern);
} else {
- data->x_res = (data->max_x + 1) / x_mm;
- data->y_res = (data->max_y + 1) / y_mm;
+ if (unlikely(x_mm == 0 || y_mm == 0)) {
+ dev_warn(&client->dev,
+ "invalid physical dimensions: x_mm=%u, y_mm=%u\n",
+ x_mm, y_mm);
+ data->x_res = 1;
+ data->y_res = 1;
+ } else {
+ data->x_res = (data->max_x + 1) / x_mm;
+ data->y_res = (data->max_y + 1) / y_mm;
+ }
}
if (device_property_read_bool(&client->dev, "elan,clickpad"))
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related
* Re: [PATCH] Input: mtk-pmic-keys - use of_device_get_match_data()
From: sashiko-bot @ 2026-05-18 4:34 UTC (permalink / raw)
To: Rosen Penev; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260518042046.981861-1-rosenp@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Missing NULL check for of_device_get_match_data() result leads to NULL pointer dereference.
- [High] Mismatch between child counting and iteration logic can cause out-of-bounds array accesses.
--
commit 0ee3fee49ccf02b7e629f90533e67fc9b40d2b9e
Author: Rosen Penev <rosenp@gmail.com>
Input: mtk-pmic-keys - use of_device_get_match_data()
This commit simplifies the driver to fetch PMIC key register data directly
using of_device_get_match_data(). It also removes the unneeded of_device.h
include.
> diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
> index c78d9f6d97c4f..fd684ac169386 100644
> --- a/drivers/input/keyboard/mtk-pmic-keys.c
> +++ b/drivers/input/keyboard/mtk-pmic-keys.c
[ ... ]
> @@ -342,7 +339,7 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)
>
> keys->dev = &pdev->dev;
> keys->regmap = pmic_chip->regmap;
> - mtk_pmic_regs = of_id->data;
> + mtk_pmic_regs = of_device_get_match_data(&pdev->dev);
While this isn't a new issue introduced by this patch, can mtk_pmic_regs be
NULL here if the device is bound manually via sysfs without a matching
device tree node?
If mtk_pmic_regs is NULL, it appears it is unconditionally dereferenced
later when calling mtk_pmic_keys_lp_reset_setup().
Would it make sense to add a check for !mtk_pmic_regs right after fetching
the match data?
Also, while reviewing this probe function, I noticed another pre-existing
issue further down:
keycount = of_get_available_child_count(node);
if (keycount > MTK_PMIC_MAX_KEY_COUNT ||
keycount > ARRAY_SIZE(irqnames)) {
dev_err(keys->dev, "too many keys defined (%d)\n", keycount);
return -EINVAL;
}
for_each_child_of_node_scoped(node, child) {
keys->keys[index].regs = &mtk_pmic_regs->keys_regs[index];
Is there a mismatch between the child counting and iteration logic?
The validation check uses of_get_available_child_count(), which ignores
disabled nodes. But the loop uses for_each_child_of_node_scoped(), which
iterates over all children, including disabled ones.
If a disabled child node exists in the device tree alongside available ones,
could the loop execute more times than the initial validation accounted for?
This might increment the index variable past the allocated array bounds,
leading to out-of-bounds accesses on irqnames[] and keys->keys[].
Would updating the loop to use for_each_available_child_of_node_scoped()
prevent this?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260518042046.981861-1-rosenp@gmail.com?part=1
^ permalink raw reply
* [PATCH] Input: mtk-pmic-keys - use of_device_get_match_data()
From: Rosen Penev @ 2026-05-18 4:20 UTC (permalink / raw)
To: linux-input
Cc: Dmitry Torokhov, Matthias Brugger, AngeloGioacchino Del Regno,
open list:ARM/Mediatek SoC support,
moderated list:ARM/Mediatek SoC support,
moderated list:ARM/Mediatek SoC support
Use of_device_get_match_data() to fetch the PMIC key register data directly instead of open-coding an of_match_device() lookup.
This also lets the driver drop the of_device.h include.
Assisted-by: Codex:GPT-5.5
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
drivers/input/keyboard/mtk-pmic-keys.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
index c78d9f6d97c4..fd684ac16938 100644
--- a/drivers/input/keyboard/mtk-pmic-keys.c
+++ b/drivers/input/keyboard/mtk-pmic-keys.c
@@ -16,7 +16,6 @@
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/registers.h>
#include <linux/module.h>
-#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@@ -333,8 +332,6 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)
struct mtk_pmic_keys *keys;
const struct mtk_pmic_regs *mtk_pmic_regs;
struct input_dev *input_dev;
- const struct of_device_id *of_id =
- of_match_device(of_mtk_pmic_keys_match_tbl, &pdev->dev);
keys = devm_kzalloc(&pdev->dev, sizeof(*keys), GFP_KERNEL);
if (!keys)
@@ -342,7 +339,7 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)
keys->dev = &pdev->dev;
keys->regmap = pmic_chip->regmap;
- mtk_pmic_regs = of_id->data;
+ mtk_pmic_regs = of_device_get_match_data(&pdev->dev);
keys->input_dev = input_dev = devm_input_allocate_device(keys->dev);
if (!input_dev) {
--
2.54.0
^ permalink raw reply related
* Re:i2c_hid_acpi: ELAN2514 touchscreen causes IRQ flood on HP Omnibook X 14 (Lunar Lake)
From: Dennis Foster @ 2026-05-17 23:49 UTC (permalink / raw)
To: linux-input; +Cc: linux-i2c, benjamintissoires, jikos
In-Reply-To: <19e3435bff9.5159b6ff3377555.4429246136901518864@dennisfoster.us>
Couple of corrections.
The machine is actually an HP OmniBook X Flip 16, not the
"Omnibook X 14" I wrote in the original - my mistake. Also bumped to
kernel 7.0.9 today; same behavior. BIOS is HP F.11
(03/04/2026), board 8DA1.
I disabled the udev workaround briefly to get an actual rate. With the
driver bound for ~40 seconds, /proc/interrupts went from 18,811 to
1,778,374 on IRQ 20, i.e. roughly 42,900/s pinned on CPU5. Kernel
never marks the line bad - no "nobody cared", no "disabling IRQ", it
just keeps fasteoi'ing.
One thing I missed in the DSDT that might be relevant: TPL1's
interrupt isn't a GpioInt() resource, it's a regular Interrupt()
template with the vector patched in at _INI:
Name (SBFI, ResourceTemplate ()
{
Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, ,, _Y4F)
{ 0x00000000, }
})
Method (_INI, ...)
{
...
INT2 = INUM (GPLI)
...
}
That's why it surfaces as IR-IO-APIC 20-fasteoi rather than something
gpiolib-backed. _CRS picks between this template and a G_IN()/GpioInt
template based on the BIOS variable TPLM, and this firmware ships
with TPLM != 0 so we end up on the APIC path. I don't see a setup
option to flip it.
Probably unrelated but in the same area of the DSDT - this prints
once at boot:
ACPI BIOS Error (bug): Could not resolve symbol
[\_SB.PC00.I2C5.TPL1], AE_NOT_FOUND
I2C5 has no TPL1 in this firmware (the touchscreen is on I2C4).
Happy to send the full decompiled DSDT/SSDTs, a fuller dmesg with
i2c_hid dyndbg enabled, or test patches.
--
Dennis
^ permalink raw reply
* Re: [PATCH v3 0/9] iio: introduce devm_ API for hid sensro setup and cleanup
From: Sanjay Chitroda @ 2026-05-17 20:19 UTC (permalink / raw)
To: Zhang, Lixu
Cc: jikos@kernel.org, jic23@kernel.org,
srinivas.pandruvada@linux.intel.com, Lechner, David,
nuno.sa@analog.com, andy@kernel.org, sakari.ailus@linux.intel.com,
linux-input@vger.kernel.org, linux-iio@vger.kernel.org,
linux-kernel@vger.kernel.org
In-Reply-To: <SJ0PR11MB5613D4ECB8081985C3F2D82293072@SJ0PR11MB5613.namprd11.prod.outlook.com>
On Thu, May 14, 2026 at 02:47:52AM +0000, Zhang, Lixu wrote:
> Tested-by: Zhang Lixu <lixu.zhang@intel.com>
Hi Zhang,
Thanks for the testing and validaiton.
I hope you validated the complete series, including the unbind flow for the
drivers using devm API.
Hi Jonathan,
How should we take this series forward? should I extend the series to
cover remaining HID IIO drivers for this devm API, or this series can
applied to IIO tree first and sent followup patches on top of that?
Thanks, Sanjay
>
> >-----Original Message-----
> >From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
> >Sent: Saturday, May 9, 2026 6:11 PM
> >To: jikos@kernel.org; jic23@kernel.org; srinivas.pandruvada@linux.intel.com
> >Cc: Lechner, David <dlechner@baylibre.com>; nuno.sa@analog.com;
> >andy@kernel.org; sanjayembeddedse@gmail.com;
> >sakari.ailus@linux.intel.com; linux-input@vger.kernel.org; linux-
> >iio@vger.kernel.org; linux-kernel@vger.kernel.org
> >Subject: [PATCH v3 0/9] iio: introduce devm_ API for hid sensro setup and
> >cleanup
> >
> >From: Sanjay Chitroda <sanjayembeddedse@gmail.com>
> >
> >Key highlights:
> >- Prepare change as pre-requisite for devm conversion for HID IIO
> > drivers by removing redundant argument
> >- Add devm API to setup trigger and clenaup resource using
> > devm_add_action_or_reset()
> >- few cleanup and prepratory changes before updating driver for devm_
> >- few sample driver update using devm conversion to auto release resource
> >
> >changes in v3:
> >- Added cleanup and prepratory changes before adding devm_ API
> > conversion based on self review: 0002, 0004, 0006, 0007 and 0008
> >- Address andy's review comment on commit message and coding style
> >- v2 series -> https://lore.kernel.org/all/20260429175918.2541914-1-
> >sanjayembedded@gmail.com/
> >changes in v2:
> >- Following input from Jonathan and Andy, squash initial patch v1
> > series in single change as individual change should not break anything
> >- Add devm API support and two driver using the same
> >- v1 series -> https://lore.kernel.org/all/20260428071613.1134053-1-
> >sanjayembedded@gmail.com/
> >
> >Testing:
> > - Compiled with W=1
> > - Build-tested on QEMU x86_64
> >
> >Based on further feedback and reviews, I would extend this series to convert all
> >HID IIO driver to use devm_* API.
> >
> >Thanks,
> >Sanjay Chitroda
> >
> >
> >Sanjay Chitroda (9):
> > iio: hid-sensors: drop redundant iio_dev argument
> > iio: hid-sensors: cleanup codestyle warning
> > iio: hid-sensors: introduce device managed API
> > iio: gyro: hid-sensor-gyro-3d: cleanup codestyle warning
> > iio: gyro: hid-sensor-gyro-3d: drop hid_sensor_remove_trigger() using
> > devm API
> > iio: humidity: hid-sensor-humidity: cleanup codestyle check
> > iio: humidity: hid-sensor-humidity: use common device for devres
> > iio: humidity: hid-sensor-humidity: use local struct device
> > iio: humidity: hid-sensor-humidity: drop hid_sensor_remove_trigger()
> > using devm API
> >
> > drivers/iio/accel/hid-sensor-accel-3d.c | 4 +-
> > .../common/hid-sensors/hid-sensor-trigger.c | 24 +++++++-
> > .../common/hid-sensors/hid-sensor-trigger.h | 5 +-
> > drivers/iio/gyro/hid-sensor-gyro-3d.c | 16 ++---
> > drivers/iio/humidity/hid-sensor-humidity.c | 61 +++++++++----------
> > drivers/iio/light/hid-sensor-als.c | 4 +-
> > drivers/iio/light/hid-sensor-prox.c | 4 +-
> > drivers/iio/magnetometer/hid-sensor-magn-3d.c | 4 +-
> >drivers/iio/orientation/hid-sensor-incl-3d.c | 4 +- drivers/iio/orientation/hid-
> >sensor-rotation.c | 4 +- .../position/hid-sensor-custom-intel-hinge.c | 4 +-
> > drivers/iio/pressure/hid-sensor-press.c | 4 +-
> > .../iio/temperature/hid-sensor-temperature.c | 4 +-
> > 13 files changed, 78 insertions(+), 64 deletions(-)
> >
> >
> >base-commit: 39b80c5c9830d12d2d6531059001301c4265322a
> >--
> >2.34.1
> >
>
^ permalink raw reply
* Re: [PATCH 4/4] HID: wacom: validate report length for 24HDT and 27QHDT handlers
From: sashiko-bot @ 2026-05-17 15:45 UTC (permalink / raw)
To: Jinmo Yang; +Cc: linux-input, dmitry.torokhov
In-Reply-To: <20260517135215.2220117-5-jinmo44.yang@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The patch provides an incomplete fix for out-of-bounds reads caused by short HID reports. It adds length checks for `WACOM_24HDT` and `WACOM_27QHDT`, but misses the exact same vulnerability in numerous other device handlers called by `wacom_wac_irq()`.
--
commit 46cbf4294f0d1877c7d3c2555971c064f005babf
Author: Jinmo Yang <jinmo44.yang@gmail.com>
HID: wacom: validate report length for 24HDT and 27QHDT handlers
This commit adds length checks to wacom_wac_irq to prevent out-of-bounds
reads for WACOM_24HDT and WACOM_27QHDT devices when they receive short HID
reports.
> diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
> index 269e8318f79af..2fd1c4e80a72b 100644
> --- a/drivers/hid/wacom_wac.c
> +++ b/drivers/hid/wacom_wac.c
> @@ -3509,7 +3509,14 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
> break;
>
> case WACOM_24HDT:
> + if (len < 62)
> + return;
> + sync = wacom_24hdt_irq(wacom_wac);
> + break;
> +
> case WACOM_27QHDT:
> + if (len < 64)
> + return;
> sync = wacom_24hdt_irq(wacom_wac);
> break;
While this prevents out-of-bounds reads for WACOM_24HDT and WACOM_27QHDT,
are there other device handlers in this switch statement that also need
report length validation?
For example, handlers like INTUOSP2_BT, REMOTE, INTUOS, and PENPARTNER
appear to process reports without validating the buffer length.
Looking at wacom_intuos_pro2_bt_irq(), it receives the length but seems to
unconditionally call wacom_intuos_pro2_bt_pen():
wacom_wac_irq() -> wacom_intuos_pro2_bt_irq() -> wacom_intuos_pro2_bt_pen()
Does this allow wacom_intuos_pro2_bt_pen() to read up to data[107] without
validating the buffer size?
Similarly, does wacom_remote_status_irq() read up to data[30] to populate
remote serial numbers without checking the length?
Could a malicious device sending short reports still trigger regressions
like slab-out-of-bounds reads or information leaks to userspace through
these other handlers?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260517135215.2220117-1-jinmo44.yang@gmail.com?part=4
^ permalink raw reply
* Re: [PATCH v2] platform/x86/lenovo: add Yoga Book 9 keyboard dock driver
From: sashiko-bot @ 2026-05-17 15:25 UTC (permalink / raw)
To: Dave Carey; +Cc: dmitry.torokhov, linux-input
In-Reply-To: <20260517150224.50191-1-carvsdriver@gmail.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [Critical] NULL Pointer Dereference on sysfs read for QUERY device and DMI check bypass
- [High] Use-After-Free due to unreferenced QUERY WMI device pointer
- [Medium] Race condition exposing incorrect initial switch state to userspace
--
commit f26ec3cd843093c54646b94f3331c501f619e886
Author: Dave Carey <carvsdriver@gmail.com>
platform/x86/lenovo: add Yoga Book 9 keyboard dock driver
This commit adds a new driver, lenovo-yb9-kbdock, to support the detachable
keyboard dock on the Lenovo Yoga Book 9 14IAH10. It queries the BKBD state
via WMI to report SW_TABLET_MODE input events and exposes the raw position
to userspace via sysfs.
> diff --git a/drivers/platform/x86/lenovo/yb9-kbdock.c b/drivers/platform/x86/lenovo/yb9-kbdock.c
> new file mode 100644
> index 0000000000000..ba0579f7981a3
> --- /dev/null
> +++ b/drivers/platform/x86/lenovo/yb9-kbdock.c
[ ... ]
> +static int yb9_kbdock_probe(struct wmi_device *wdev, const void *ctx)
> +{
> + enum yb9_guid_type type = (enum yb9_guid_type)(uintptr_t)ctx;
> + struct yb9_kbdock_priv *priv;
> + struct input_dev *input_dev;
> + struct wmi_device *qwdev;
> + int err;
> +
> + if (type == YB9_GUID_QUERY) {
> + mutex_lock(&yb9_query_lock);
> + yb9_query_wdev = wdev;
> + mutex_unlock(&yb9_query_lock);
> + return 0;
> + }
The wmi_driver struct sets .dev_groups to yb9_kbdock_groups, which means the
keyboard_position sysfs attribute is created for all devices binding to this
driver, including the query WMI device.
If userspace reads this sysfs attribute on the query device, won't
keyboard_position_show() receive a NULL pointer from dev_get_drvdata()
and dereference it when accessing priv->bkbd?
Also, because this returns before dmi_check_system() is called, does this
allow the driver to bind to the query GUID on unsupported hardware?
> +
> + if (!dmi_check_system(yb9_kbdock_dmi_table))
> + return -ENODEV;
[ ... ]
> + input_set_capability(input_dev, EV_SW, SW_TABLET_MODE);
> +
> + err = input_register_device(input_dev);
> + if (err) {
> + dev_err(&wdev->dev, "failed to register input device: %d\n", err);
> + return err;
> + }
> +
> + priv->query_wdev = qwdev;
Is a device link or reference count via get_device() needed here?
If the query WMI device is unbound or its parent ACPI device is hot-removed,
could priv->query_wdev become a dangling pointer that gets used in
yb9_kbdock_notify() when a WMI event fires?
> + priv->input_dev = input_dev;
> + dev_set_drvdata(&wdev->dev, priv);
> +
> + yb9_kbdock_update(wdev);
Could this expose an incorrect initial switch state to userspace?
Since input_register_device() makes the device visible before
yb9_kbdock_update() queries the hardware state, userspace might
read the default laptop mode (0) even if the keyboard is detached.
Can the initial hardware state be queried and reported before registering
the input device?
> + return 0;
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260517150224.50191-1-carvsdriver@gmail.com?part=1
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox