* [PATCH] Add common hall sensor drivers
From: 756271518 @ 2026-01-21 8:59 UTC (permalink / raw)
To: dmitry.torokhov
Cc: linusw, brgl, linux-kernel, linux-input, linux-gpio, xuchen
From: xuchen <756271518@qq.com>
This patch adds support for common hall sensor ICs used in Qualcomm
reference designs. The driver handles both rising and falling edges
to detect magnetic field changes.
Signed-off-by: xuchen <756271518@qq.com>
---
drivers/input/keyboard/pogo_switch.c | 323 +++++++++++++++++++++++++++
1 file changed, 323 insertions(+)
create mode 100644 drivers/input/keyboard/pogo_switch.c
diff --git a/drivers/input/keyboard/pogo_switch.c b/drivers/input/keyboard/pogo_switch.c
new file mode 100644
index 000000000000..ea91037caeb3
--- /dev/null
+++ b/drivers/input/keyboard/pogo_switch.c
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Pogo switch/hall sensor driver
+ *
+ * Copyright (c) 2024 faiot.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+#include <linux/workqueue.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/spinlock.h>
+#include <dt-bindings/input/gpio-keys.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+
+#define LID_DEV_NAME "hall_sensor"
+#define HALL_INPUT "/dev/input/hall_dev"
+#define KEY_HALL 84
+
+struct hall_data {
+ int gpio; /* device use gpio number */
+ int irq; /* device request irq number */
+ int active_low; /* gpio active high or low for valid value */
+ bool wakeup; /* device can wakeup system or not */
+ struct input_dev *hall_dev;
+ struct device *dev;
+ int detect_irq;
+ struct workqueue_struct *hall_wq;
+ struct delayed_work hall_debounce_work_det;
+};
+
+static struct hall_data *p_hall_data;
+static struct class extbd_ctrl_class;
+static int g_extbd_status;
+
+static void hall_driver_remove(struct platform_device *dev);
+
+static int hall_parse_dt(struct device *dev, struct hall_data *data)
+{
+ struct device_node *np = dev->of_node;
+
+ data->gpio = of_get_named_gpio(np, "faiot,hall-int", 0);
+ if (!gpio_is_valid(data->gpio)) {
+ dev_err(dev, "hall gpio is not valid\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static irqreturn_t hall_interrupt_handler(int irq, void *dev)
+{
+ if (p_hall_data == NULL || p_hall_data->hall_wq == NULL) {
+ pr_err("zy : irq resource not rdy\n");
+ return IRQ_HANDLED;
+ }
+
+ queue_delayed_work(p_hall_data->hall_wq,
+ &p_hall_data->hall_debounce_work_det,
+ msecs_to_jiffies(50));
+ return IRQ_HANDLED;
+}
+
+static void hall_det_debounce_work_func(struct work_struct *work)
+{
+ int value;
+
+ value = (gpio_get_value_cansleep(p_hall_data->gpio) ? 1 : 0) ^
+ p_hall_data->active_low;
+ if (value) {
+ input_report_key(p_hall_data->hall_dev, KEY_HALL, 0);
+ input_sync(p_hall_data->hall_dev);
+ dev_info(&p_hall_data->hall_dev->dev,
+ "hall_interrupt_handler near\n");
+ } else {
+ input_report_key(p_hall_data->hall_dev, KEY_HALL, 1);
+ input_sync(p_hall_data->hall_dev);
+ dev_info(&p_hall_data->hall_dev->dev,
+ "hall_interrupt_handler far\n");
+ }
+}
+
+static int hall_input_init(struct platform_device *pdev,
+ struct hall_data *data)
+{
+ int err;
+
+ data->hall_dev = devm_input_allocate_device(&pdev->dev);
+ if (!data->hall_dev) {
+ dev_err(&pdev->dev, "input device allocation failed\n");
+ return -EINVAL;
+ }
+
+ data->hall_dev->name = LID_DEV_NAME;
+ data->hall_dev->phys = HALL_INPUT;
+ set_bit(EV_KEY, data->hall_dev->evbit);
+ set_bit(KEY_HALL, data->hall_dev->keybit);
+
+ err = input_register_device(data->hall_dev);
+ if (err < 0) {
+ dev_err(&pdev->dev, "unable to register input device %s\n",
+ LID_DEV_NAME);
+ return err;
+ }
+
+ return 0;
+}
+
+static ssize_t extbd_status_store(const struct class *c,
+ const struct class_attribute *attr,
+ const char *buf, size_t count)
+{
+ if (kstrtoint(buf, 0, &g_extbd_status))
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t extbd_status_show(const struct class *c,
+ const struct class_attribute *attr,
+ char *buf)
+{
+ g_extbd_status = (gpio_get_value_cansleep(p_hall_data->gpio) ? 1 : 0) ^
+ p_hall_data->active_low;
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", g_extbd_status);
+}
+
+static CLASS_ATTR_RW(extbd_status);
+
+static struct attribute *extbd_ctrl_class_attrs[] = {
+ &class_attr_extbd_status.attr,
+ NULL,
+};
+
+ATTRIBUTE_GROUPS(extbd_ctrl_class);
+
+static int hall_driver_probe(struct platform_device *dev)
+{
+ struct hall_data *data;
+ int err;
+ int irq_flags;
+
+ dev_info(&dev->dev, "hall_driver probe\n");
+
+ data = devm_kzalloc(&dev->dev, sizeof(struct hall_data), GFP_KERNEL);
+ if (data == NULL) {
+ err = -ENOMEM;
+ dev_err(&dev->dev, "failed to allocate memory %d\n", err);
+ goto exit;
+ }
+
+ data->dev = &dev->dev;
+ dev_set_drvdata(&dev->dev, data);
+
+ err = hall_parse_dt(&dev->dev, data);
+ if (err < 0) {
+ dev_err(&dev->dev, "Failed to parse device tree\n");
+ goto exit;
+ }
+
+ err = hall_input_init(dev, data);
+ if (err < 0) {
+ dev_err(&dev->dev, "input init failed\n");
+ goto exit;
+ }
+
+ if (!gpio_is_valid(data->gpio)) {
+ dev_err(&dev->dev, "gpio is not valid\n");
+ err = -EINVAL;
+ goto free_gpio;
+ }
+
+ irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+ err = gpio_request_one(data->gpio, GPIOF_IN, "hall_sensor_irq");
+ if (err) {
+ dev_err(&dev->dev, "unable to request gpio %d\n", data->gpio);
+ goto exit;
+ }
+
+ data->irq = gpio_to_irq(data->gpio);
+ err = devm_request_threaded_irq(&dev->dev, data->irq, NULL,
+ hall_interrupt_handler,
+ irq_flags, "hall_sensor", data);
+ if (err < 0)
+ goto free_irq;
+
+ data->hall_wq = create_singlethread_workqueue("hall_wq");
+ if (!data->hall_wq)
+ return -EINVAL;
+
+ INIT_DELAYED_WORK(&data->hall_debounce_work_det,
+ hall_det_debounce_work_func);
+
+ /*
+ * err = sysfs_create_group(&data->dev->kobj, &hall_attr_group);
+ * if (err) {
+ * printk(KERN_ERR "%s sysfs_create_group fail\n", __func__);
+ * return err;
+ * }
+ */
+
+ extbd_ctrl_class.name = "extbd_ctrl";
+ extbd_ctrl_class.class_groups = extbd_ctrl_class_groups;
+ err = class_register(&extbd_ctrl_class);
+ if (err < 0)
+ dev_err(&dev->dev, "Failed to create extbd_ctrl_class rc=%d\n",
+ err);
+
+ p_hall_data = data;
+ device_init_wakeup(&dev->dev, data->wakeup);
+ enable_irq_wake(data->irq);
+
+ dev_info(&dev->dev, "guh hall probe end");
+
+ return 0;
+
+free_irq:
+ disable_irq_wake(data->irq);
+ device_init_wakeup(&dev->dev, 0);
+free_gpio:
+ gpio_free(data->gpio);
+exit:
+ return err;
+}
+
+static void hall_driver_remove(struct platform_device *dev)
+{
+ struct hall_data *data = dev_get_drvdata(&dev->dev);
+
+ disable_irq_wake(data->irq);
+ device_init_wakeup(&dev->dev, 0);
+ if (data->gpio)
+ gpio_free(data->gpio);
+}
+
+static int hall_driver_suspend(struct platform_device *dev,
+ pm_message_t state)
+{
+ /*
+ * struct hall_data *data = dev_get_drvdata(&dev->dev);
+ * gpio_direction_output(data->extbd_power, 0);
+ */
+
+ return 0;
+}
+
+static int hall_driver_resume(struct platform_device *dev)
+{
+ /*
+ * struct hall_data *data = dev_get_drvdata(&dev->dev);
+ * gpio_direction_output(data->extbd_power, 1);
+ */
+
+ return 0;
+}
+
+static struct platform_device_id hall_id[] = {
+ { LID_DEV_NAME, 0 },
+ { },
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id hall_match_table[] = {
+ { .compatible = "hall-switch", },
+ { },
+};
+#endif
+
+static struct platform_driver hall_driver = {
+ .driver = {
+ .name = LID_DEV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(hall_match_table),
+ },
+ .probe = hall_driver_probe,
+ .remove = hall_driver_remove,
+ .suspend = hall_driver_suspend,
+ .resume = hall_driver_resume,
+ .id_table = hall_id,
+};
+
+static int __init hall_init(void)
+{
+ return platform_driver_register(&hall_driver);
+}
+
+static void __exit hall_exit(void)
+{
+ platform_driver_unregister(&hall_driver);
+}
+
+module_init(hall_init);
+module_exit(hall_exit);
+
+MODULE_DESCRIPTION("Hall sensor driver");
+MODULE_LICENSE("GPL");
^ permalink raw reply related
* Re: [PATCH] Input: atmel_mxt_ts - fix NULL pointer dereference in mxt_object_show
From: 齐柯宇 @ 2026-01-21 8:54 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: nick, rydberg, jy0922.shim, bleung, ezequiel, linux-input,
linux-kernel
In-Reply-To: <4mtpditwnavptpvstqphwa2auhb6wcd63gi76w2dekw7ryn2bp@au7dyelbvzmi>
Hi Dmitry,
Thank you for the review.
You're absolutely right. The NULL check only narrows the race window but
does not eliminate the race condition - the pointers can still be
invalidated between the check and the actual dereference.
I will rework the patch with proper synchronization to fully address this
issue.
regards,
Kery
Dmitry Torokhov <dmitry.torokhov@gmail.com> 于2026年1月21日周三 02:22写道:
>
> Hi,
>
> On Thu, Jan 15, 2026 at 03:43:37AM +0800, 齐柯宇 wrote:
> > diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c
> > b/drivers/input/touchscreen/atmel_mxt_ts.c
> > index dd0544cc1bc1..401fcae2264d 100644
> > --- a/drivers/input/touchscreen/atmel_mxt_ts.c
> > +++ b/drivers/input/touchscreen/atmel_mxt_ts.c
> > @@ -2859,6 +2859,10 @@ static ssize_t mxt_object_show(struct device *dev,
> > int error;
> > u8 *obuf;
> >
> > + /* Check for NULL to prevent race condition during firmware update */
> > + if (!data->info || !data->object_table)
> > + return -ENODEV;
> > +
>
> What stops the pointers from being invalidated right here?
>
> > /* Pre-allocate buffer large enough to hold max sized object. */
> > obuf = kmalloc(256, GFP_KERNEL);
> > if (!obuf)
>
> Thanks.
>
> --
> Dmitry
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: input: novatek,nvt-ts: Add nt36672a-e7t-ts compatible
From: Krzysztof Kozlowski @ 2026-01-21 8:18 UTC (permalink / raw)
To: Gianluca Boiano
Cc: hansg, dmitry.torokhov, robh, krzk+dt, conor+dt, linux-input,
devicetree, linux-kernel
In-Reply-To: <20260120193600.1089458-1-morf3089@gmail.com>
On Tue, Jan 20, 2026 at 08:35:59PM +0100, Gianluca Boiano wrote:
> Add compatible string for the Novatek NT36672A e7t touchscreen variant
> found on the Xiaomi Redmi Note 6 Pro (tulip).
>
> This variant uses different chip parameters compared to the standard
> NT36672A, specifically a different wake_type value.
>
> Signed-off-by: Gianluca Boiano <morf3089@gmail.com>
> ---
> .../devicetree/bindings/input/touchscreen/novatek,nvt-ts.yaml | 1 +
> 1 file changed, 1 insertion(+)
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 2/2] input: touchscreen: novatek-nvt-ts: Add support for NT36672A e7t variant
From: Krzysztof Kozlowski @ 2026-01-21 8:18 UTC (permalink / raw)
To: Gianluca Boiano
Cc: hansg, dmitry.torokhov, robh, krzk+dt, conor+dt, linux-input,
devicetree, linux-kernel
In-Reply-To: <20260120193600.1089458-2-morf3089@gmail.com>
On Tue, Jan 20, 2026 at 08:36:00PM +0100, Gianluca Boiano wrote:
> Add support for the Novatek NT36672A touchscreen variant found on the
> Xiaomi Redmi Note 6 Pro (tulip) which uses a different wake_type value
> (0x02 instead of 0x01).
>
> The touchscreen was failing to initialize with error -5 due to the
> wake_type parameter mismatch during probe. This adds a new chip data
> structure for the e7t variant with the correct wake_type value.
>
> Closes: https://github.com/sdm660-mainline/linux/issues/155
I don't think this is useful, because it's downstream/fork/distro with
at least 100 patches on top of v6.18 (so not even current mainline!).
Calling a repo "mainline" does not make it mainline and we do not track
distro bugs.
Also, lack of a feature is not a bug which needs to be closed.
Drop the tag.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH] arm64: dts: qcom: milos-fairphone-fp6: Add Hall Effect sensor
From: Luca Weiss @ 2026-01-21 8:07 UTC (permalink / raw)
To: Dmitry Baryshkov, Luca Weiss, Dmitry Torokhov
Cc: Konrad Dybcio, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, ~postmarketos/upstreaming,
phone-devel, linux-arm-msm, devicetree, linux-kernel, linux-input
In-Reply-To: <wpjvuclvpjft7y2rlrmfgszkzmc5vvmohif3etqrtvymxjjyjk@h2dujh5egdvd>
On Wed Jan 21, 2026 at 12:05 AM CET, Dmitry Baryshkov wrote:
> On Mon, Jan 19, 2026 at 04:52:23PM +0100, Luca Weiss wrote:
>> On Mon Jan 19, 2026 at 3:41 PM CET, Konrad Dybcio wrote:
>> > On 1/16/26 3:22 PM, Luca Weiss wrote:
>> >> Add a node for the Hall Effect sensor, used to detect whether the Flip
>> >> Cover is closed or not.
>> >>
>> >> The sensor is powered through vreg_l10b, so let's put a
>> >> regulator-always-on on that to make sure the sensor gets power.
>> >
>> > Is there anything else on L10B? Can we turn it off if the hall sensor
>> > is e.g. user-disabled?
>>
>> It's the voltage source for pull-up of sensor I2C bus (so
>> ADSP-managed?), DVDD for amplifiers and VDD for a most sensors like
>> the gyro.
>>
>> So realistically, it'll probably be (nearly) always on anyways. And I
>> don't want to shave another yak by adding vdd support to gpio-keys...
>
> Why? If it is exactly what happens on the board: the device producing
> GPIO events _is_ powered via a vdd. Added Input maintainer / list to cc.
Yes, the hall sensor which is connected to the GPIO on the SoC, has an
extra VDD input which needs to be on in order for the Hall-effect sensor
to be on.
See page 133 "HALL" in the center of the page
https://www.fairphone.com/wp-content/uploads/2025/08/Fairphone-Gen.-6_-Information-on-how-to-repair-dispose-of-and-recycle-EN-NL-FR-DE.pdf
The IC is OCH166AEV4AD where VDD is (as expected) "Power Supply Input":
https://www.orient-chip.com/Public/Uploads/uploadfile/files/20231014/1OCH166Adatasheet202203221.pdf
Regards
Luca
>
>>
>> Regards
>> Luca
>>
>> >
>> > Konrad
>> >
>> >>
>> >> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
>> >> ---
>> >> arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts | 12 ++++++++++++
>> >> 1 file changed, 12 insertions(+)
>> >>
>> >> diff --git a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
>> >> index 7629ceddde2a..98b3fc654206 100644
>> >> --- a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
>> >> +++ b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
>> >> @@ -32,6 +32,16 @@ gpio-keys {
>> >> pinctrl-0 = <&volume_up_default>;
>> >> pinctrl-names = "default";
>> >>
>> >> + /* Powered by the always-on vreg_l10b */
>> >> + event-hall-sensor {
>> >> + label = "Hall Effect Sensor";
>> >> + gpios = <&tlmm 70 GPIO_ACTIVE_LOW>;
>> >> + linux,input-type = <EV_SW>;
>> >> + linux,code = <SW_LID>;
>> >> + linux,can-disable;
>> >> + wakeup-source;
>> >> + };
>> >> +
>> >> key-volume-up {
>> >> label = "Volume Up";
>> >> gpios = <&pm7550_gpios 6 GPIO_ACTIVE_LOW>;
>> >> @@ -316,6 +326,8 @@ vreg_l10b: ldo10 {
>> >> regulator-min-microvolt = <1800000>;
>> >> regulator-max-microvolt = <1800000>;
>> >> regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
>> >> + /* Hall sensor VDD */
>> >> + regulator-always-on;
>> >> };
>> >>
>> >> vreg_l11b: ldo11 {
>> >>
>> >> ---
>> >> base-commit: ef1c7b875741bef0ff37ae8ab8a9aaf407dc141c
>> >> change-id: 20260116-fp6-hall-sensor-1049f2f872ac
>> >>
>> >> Best regards,
>>
^ permalink raw reply
* [PATCH v2] Input: synaptics_i2c - guard polling restart in resume
From: Minseong Kim @ 2026-01-21 6:37 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: linux-input, linux-kernel, stable, Minseong Kim
synaptics_i2c_resume() restarts delayed work unconditionally, even when
the input device is not opened. Guard the polling restart by taking the
input device mutex and checking input_device_enabled() before re-queuing
the delayed work.
Fixes: eef3e4cab72ea ("Input: add driver for Synaptics I2C touchpad")
Cc: stable@vger.kernel.org
Signed-off-by: Minseong Kim <ii4gsp@gmail.com>
---
drivers/input/mouse/synaptics_i2c.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
index a0d707e47d93..fc65e28c1b31 100644
--- a/drivers/input/mouse/synaptics_i2c.c
+++ b/drivers/input/mouse/synaptics_i2c.c
@@ -615,13 +615,17 @@ static int synaptics_i2c_resume(struct device *dev)
int ret;
struct i2c_client *client = to_i2c_client(dev);
struct synaptics_i2c *touch = i2c_get_clientdata(client);
+ struct input_dev *input = touch->input;
ret = synaptics_i2c_reset_config(client);
if (ret)
return ret;
- mod_delayed_work(system_wq, &touch->dwork,
+ mutex_lock(&input->mutex);
+ if (input_device_enabled(input))
+ mod_delayed_work(system_wq, &touch->dwork,
msecs_to_jiffies(NO_DATA_SLEEP_MSECS));
+ mutex_unlock(&input->mutex);
return 0;
}
--
2.48.1
^ permalink raw reply related
* Re: [PATCH v6 2/2] HID: i2c-hid: Add FocalTech FT8112
From: Dmitry Torokhov @ 2026-01-21 5:39 UTC (permalink / raw)
To: daniel_peng, Benjamin Tissoires, Jiri Kosina
Cc: linux-input, LKML, Douglas Anderson, Pin-yen Lin
In-Reply-To: <20251117094041.300083-2-Daniel_Peng@pegatron.corp-partner.google.com>
On Mon, Nov 17, 2025 at 05:40:41PM +0800, daniel_peng@pegatron.corp-partner.google.com wrote:
> From: Daniel Peng <Daniel_Peng@pegatron.corp-partner.google.com>
>
> Information for touchscreen model HKO/RB116AS01-2 as below:
> - HID :FTSC1000
> - slave address:0X38
> - Interface:HID over I2C
> - Touch control lC:FT8112
> - I2C ID: PNP0C50
>
> Signed-off-by: Daniel Peng <Daniel_Peng@pegatron.corp-partner.google.com>
Jiri, Benjamin, do you want to take it (and the binding) through the HID
tree or should I take it through input?
> ---
>
> Changes in v6:
> - No changed with the v5 due to relation chain.
>
> drivers/hid/i2c-hid/i2c-hid-of-elan.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/drivers/hid/i2c-hid/i2c-hid-of-elan.c b/drivers/hid/i2c-hid/i2c-hid-of-elan.c
> index 0215f217f6d8..b81fcc6ff49e 100644
> --- a/drivers/hid/i2c-hid/i2c-hid-of-elan.c
> +++ b/drivers/hid/i2c-hid/i2c-hid-of-elan.c
> @@ -168,6 +168,13 @@ static const struct elan_i2c_hid_chip_data elan_ekth6a12nay_chip_data = {
> .power_after_backlight = true,
> };
>
> +static const struct elan_i2c_hid_chip_data focaltech_ft8112_chip_data = {
> + .post_power_delay_ms = 10,
> + .post_gpio_reset_on_delay_ms = 150,
> + .hid_descriptor_address = 0x0001,
> + .main_supply_name = "vcc33",
> +};
> +
> static const struct elan_i2c_hid_chip_data ilitek_ili9882t_chip_data = {
> .post_power_delay_ms = 1,
> .post_gpio_reset_on_delay_ms = 200,
> @@ -191,6 +198,7 @@ static const struct elan_i2c_hid_chip_data ilitek_ili2901_chip_data = {
> static const struct of_device_id elan_i2c_hid_of_match[] = {
> { .compatible = "elan,ekth6915", .data = &elan_ekth6915_chip_data },
> { .compatible = "elan,ekth6a12nay", .data = &elan_ekth6a12nay_chip_data },
> + { .compatible = "focaltech,ft8112", .data = &focaltech_ft8112_chip_data },
> { .compatible = "ilitek,ili9882t", .data = &ilitek_ili9882t_chip_data },
> { .compatible = "ilitek,ili2901", .data = &ilitek_ili2901_chip_data },
> { }
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH] input: synaptics_i2c - cancel delayed work before freeing device
From: Dmitry Torokhov @ 2026-01-21 5:34 UTC (permalink / raw)
To: Mike Rapoport, Marek Vasut
Cc: Minseong Kim, linux-input, linux-kernel, stable
In-Reply-To: <py7u3qpp6s4nfdceefufkjpbyhkj7wp2kyetlw54vlhdp4gmwn@6vghr6bqkbxc>
On Fri, Dec 12, 2025 at 08:38:23PM -0800, Dmitry Torokhov wrote:
> On Wed, Dec 10, 2025 at 09:25:38PM +0900, Mike Rapoport wrote:
> > Hi,
> >
> > On Tue, Dec 09, 2025 at 08:40:54PM -0800, Dmitry Torokhov wrote:
> > > Hi Minseong,
> > >
> > > On Wed, Dec 10, 2025 at 12:20:27PM +0900, Minseong Kim wrote:
> > > > synaptics_i2c_irq() schedules touch->dwork via mod_delayed_work().
> > > > The delayed work performs I2C transactions and may still be running
> > > > (or get queued) when the device is removed.
> > > >
> > > > synaptics_i2c_remove() currently frees 'touch' without canceling
> > > > touch->dwork. If removal happens while the work is pending/running,
> > > > the work handler may dereference freed memory, leading to a potential
> > > > use-after-free.
> > > >
> > > > Cancel the delayed work synchronously before unregistering/freeing
> > > > the device.
> > > >
> > > > Fixes: eef3e4cab72e Input: add driver for Synaptics I2C touchpad
> > > > Reported-by: Minseong Kim <ii4gsp@gmail.com>
> > > > Cc: stable@vger.kernel.org
> > > > Signed-off-by: Minseong Kim <ii4gsp@gmail.com>
> > > > ---
> > > > drivers/input/mouse/synaptics_i2c.c | 2 ++
> > > > 1 file changed, 2 insertions(+)
> > > >
> > > > diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c
> > > > index a0d707e47d93..fe30bf9aea3a 100644
> > > > --- a/drivers/input/mouse/synaptics_i2c.c
> > > > +++ b/drivers/input/mouse/synaptics_i2c.c
> > > > @@ -593,6 +593,8 @@ static void synaptics_i2c_remove(struct i2c_client *client)
> > > > if (!polling_req)
> > > > free_irq(client->irq, touch);
> > > >
> > > > + cancel_delayed_work_sync(&touch->dwork);
> > > > +
> > >
> > > The call to cancel_delayed_work_sync() happens in the close() handler
> > > for the device. I see that in resume we restart the polling without
> > > checking if the device is opened, so if we want to fix it we should add
> > > the checks there.
> > >
> > > However support for the PXA board using in the device with this touch
> > > controller (eXeda) was removed a while ago. Mike, you're one of the
> > > authors, any objections to simply removing the driver?
> >
> > No objections from my side.
>
> Hmm, it looks like it is still referenced from
> arch/arm/boot/dts/nxp/mxs/imx23-sansa.dts
>
> Marek, is this device still relevant?
I see these devices (SanDisk Sansa Fuze+) for sale on e-bay, so I guess
there is a chance it will be used...
Minseong, could you please prepare a v2 that would check if the device
is opened in resume before restarting polling? It should take input
device's mutex and then use input_device_enabled().
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v4 3/3] Input: ili210x - add support for polling mode
From: Dmitry Torokhov @ 2026-01-21 5:23 UTC (permalink / raw)
To: Marek Vasut
Cc: linux-input, Conor Dooley, Frank Li, Job Noorman,
Krzysztof Kozlowski, Rob Herring, devicetree, linux-kernel,
linux-renesas-soc
In-Reply-To: <bbb7fb54-5b04-4c38-840b-8cab58eeec7b@mailbox.org>
On Tue, Jan 20, 2026 at 11:50:53PM +0100, Marek Vasut wrote:
> On 1/20/26 7:31 PM, Dmitry Torokhov wrote:
> > Hi Marek,
> >
> > On Sat, Jan 17, 2026 at 01:12:04AM +0100, Marek Vasut wrote:
> > > @@ -860,16 +893,12 @@ static ssize_t ili210x_firmware_update_store(struct device *dev,
> > > * the touch controller to disable the IRQs during update, so we have
> > > * to do it this way here.
> > > */
> > > - scoped_guard(disable_irq, &client->irq) {
> > > - dev_dbg(dev, "Firmware update started, firmware=%s\n", fwname);
> > > -
> > > - ili210x_hardware_reset(priv->reset_gpio);
> > > -
> > > - error = ili210x_do_firmware_update(priv, fwbuf, ac_end, df_end);
> > > -
> > > - ili210x_hardware_reset(priv->reset_gpio);
> > > -
> > > - dev_dbg(dev, "Firmware update ended, error=%i\n", error);
> > > + if (client->irq > 0) {
> > > + scoped_guard(disable_irq, &client->irq) {
> > > + error = ili210x_firmware_update_noirq(dev, fwbuf, ac_end, df_end);
> > > + }
> >
> > You already have a scope here, no need to establish a new one:
> >
> > guard(disable_irq)(&client->irq);
> > error = ili210x_firmware_update_noirq(dev, fwbuf, ac_end, df_end);
>
> This part ^ I do not understand. If there is no IRQ defined in DT, I need to
> call ili210x_firmware_update_noirq() without the guard because I cannot
> disable_irq() with client->irq < 0, else I need to call
> ili210x_firmware_update_noirq() within the scoped_guard() to disable IRQs to
> avoid spurious IRQs that would interfere with the firmware update ?
You do not need to use scoped_guard() because you already define a scope
in your if statement:
if (client->irq > 0) {
guard(disable_irq)(&client->irq);
error = ili210x_firmware_update_noirq(dev, fwbuf, ac_end, df_end);
} else {
error = ili210x_firmware_update_noirq(dev, fwbuf, ac_end, df_end);
}
This is sill a bit awkward. Maybe we could add to interrupt.h
void __disable_valid_irq(unsigned int irq)
{
if (irq > 0)
disable_irq(irq);
}
void __enable_valid_irq(unsigned int irq)
{
if (irq > 0)
enable_irq(irq);
}
DEFINE_LOCK_GUARD_1(disable_valid_irq, int,
disable_valid_irq(*_T->lock), enable_valid_irq(*_T->lock))
and then we'd be able to keep the driver as is (just adjust the type of
the original scoped_guard).
>
> > BTW, not a fan of the "_noirq" suffix... Maybe drop it and add
> > lockdep_is_held() there?
>
> This part I understand even less, how does lockdep play into this ? The
> scoped_guard() disables and enables IRQs if they are available.
Ah, sorry, brainfart on my part. I got confused by _noirq suffix.
Thanks.
--
Dmitry
^ permalink raw reply
* Re: [PATCH v4 3/3] Input: ili210x - add support for polling mode
From: Marek Vasut @ 2026-01-20 22:50 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: linux-input, Conor Dooley, Frank Li, Job Noorman,
Krzysztof Kozlowski, Rob Herring, devicetree, linux-kernel,
linux-renesas-soc
In-Reply-To: <wv3vil4b4lgfrqt4qnzxiffnniw422xjfdiz4svkklnfrslz3g@yzqc265pj5t5>
On 1/20/26 7:31 PM, Dmitry Torokhov wrote:
> Hi Marek,
>
> On Sat, Jan 17, 2026 at 01:12:04AM +0100, Marek Vasut wrote:
>> @@ -860,16 +893,12 @@ static ssize_t ili210x_firmware_update_store(struct device *dev,
>> * the touch controller to disable the IRQs during update, so we have
>> * to do it this way here.
>> */
>> - scoped_guard(disable_irq, &client->irq) {
>> - dev_dbg(dev, "Firmware update started, firmware=%s\n", fwname);
>> -
>> - ili210x_hardware_reset(priv->reset_gpio);
>> -
>> - error = ili210x_do_firmware_update(priv, fwbuf, ac_end, df_end);
>> -
>> - ili210x_hardware_reset(priv->reset_gpio);
>> -
>> - dev_dbg(dev, "Firmware update ended, error=%i\n", error);
>> + if (client->irq > 0) {
>> + scoped_guard(disable_irq, &client->irq) {
>> + error = ili210x_firmware_update_noirq(dev, fwbuf, ac_end, df_end);
>> + }
>
> You already have a scope here, no need to establish a new one:
>
> guard(disable_irq)(&client->irq);
> error = ili210x_firmware_update_noirq(dev, fwbuf, ac_end, df_end);
This part ^ I do not understand. If there is no IRQ defined in DT, I
need to call ili210x_firmware_update_noirq() without the guard because I
cannot disable_irq() with client->irq < 0, else I need to call
ili210x_firmware_update_noirq() within the scoped_guard() to disable
IRQs to avoid spurious IRQs that would interfere with the firmware update ?
> BTW, not a fan of the "_noirq" suffix... Maybe drop it and add
> lockdep_is_held() there?
This part I understand even less, how does lockdep play into this ? The
scoped_guard() disables and enables IRQs if they are available.
^ permalink raw reply
* Re: [PATCH bpf-next v3 03/13] bpf: Verifier support for KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-21 0:35 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
Alan Maguire, Benjamin Tissoires, Jiri Kosina, Amery Hung, bpf,
LKML, open list:HID CORE LAYER, sched-ext
In-Reply-To: <CAADnVQKtN9HS7sWE_fZex4hT=ZEGDQX+C7tS6jc2+8ixC+Jexw@mail.gmail.com>
On 1/20/26 4:30 PM, Alexei Starovoitov wrote:
> On Tue, Jan 20, 2026 at 2:27 PM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>>
>> Introduction of KF_IMPLICIT_ARGS revealed an issue with zero-extension
>> tracking, because an explicit rX = 0 in place of the verifier-supplied
>> argument is now absent if the arg is implicit (the BPF prog doesn't
>> pass a dummy NULL anymore). To mitigate this, reset the subreg_def of
>> all caller saved registers in check_kfunc_call() [1].
>>
>> [1] https://lore.kernel.org/bpf/b4a760ef828d40dac7ea6074d39452bb0dc82caa.camel@gmail.com/
>
> ...
>
>> - for (i = 0; i < CALLER_SAVED_REGS; i++)
>> - mark_reg_not_init(env, regs, caller_saved[i]);
>> + for (i = 0; i < CALLER_SAVED_REGS; i++) {
>> + u32 regno = caller_saved[i];
>> +
>> + mark_reg_not_init(env, regs, regno);
>> + regs[regno].subreg_def = DEF_NOT_SUBREG;
>> + }
>
> I'm reading that no follow up is necessary anymore and
> the new selftests cover this part automatically.
With respect to this series, the hunk above is good enough.
But we haven't tracked down why doing
.subreg_def = DEF_NOT_SUBREG
inside mark_reg_not_init() breaks zero-extension tracking.
May be a dormant bug somewhere.
^ permalink raw reply
* Re: [PATCH bpf-next v3 03/13] bpf: Verifier support for KF_IMPLICIT_ARGS
From: Alexei Starovoitov @ 2026-01-21 0:30 UTC (permalink / raw)
To: Ihor Solodrai
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
Alan Maguire, Benjamin Tissoires, Jiri Kosina, Amery Hung, bpf,
LKML, open list:HID CORE LAYER, sched-ext
In-Reply-To: <20260120222638.3976562-4-ihor.solodrai@linux.dev>
On Tue, Jan 20, 2026 at 2:27 PM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> Introduction of KF_IMPLICIT_ARGS revealed an issue with zero-extension
> tracking, because an explicit rX = 0 in place of the verifier-supplied
> argument is now absent if the arg is implicit (the BPF prog doesn't
> pass a dummy NULL anymore). To mitigate this, reset the subreg_def of
> all caller saved registers in check_kfunc_call() [1].
>
> [1] https://lore.kernel.org/bpf/b4a760ef828d40dac7ea6074d39452bb0dc82caa.camel@gmail.com/
...
> - for (i = 0; i < CALLER_SAVED_REGS; i++)
> - mark_reg_not_init(env, regs, caller_saved[i]);
> + for (i = 0; i < CALLER_SAVED_REGS; i++) {
> + u32 regno = caller_saved[i];
> +
> + mark_reg_not_init(env, regs, regno);
> + regs[regno].subreg_def = DEF_NOT_SUBREG;
> + }
I'm reading that no follow up is necessary anymore and
the new selftests cover this part automatically.
^ permalink raw reply
* Re: [PATCH bpf-next v3 00/13] bpf: Kernel functions with KF_IMPLICIT_ARGS
From: patchwork-bot+netdevbpf @ 2026-01-21 0:30 UTC (permalink / raw)
To: Ihor Solodrai
Cc: ast, daniel, andrii, martin.lau, eddyz87, yatsenko, tj,
alan.maguire, bentiss, jikos, ameryhung, bpf, linux-kernel,
linux-input, sched-ext
In-Reply-To: <20260120222638.3976562-1-ihor.solodrai@linux.dev>
Hello:
This series was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast@kernel.org>:
On Tue, 20 Jan 2026 14:26:25 -0800 you wrote:
> This series implements a generic "implicit arguments" feature for BPF
> kernel functions. For context see prior work [1][2].
>
> A mechanism is created for kfuncs to have arguments that are not
> visible to the BPF programs, and are provided to the kernel function
> implementation by the verifier.
>
> [...]
Here is the summary with links:
- [bpf-next,v3,01/13] bpf: Refactor btf_kfunc_id_set_contains
https://git.kernel.org/bpf/bpf-next/c/ea073d1818e2
- [bpf-next,v3,02/13] bpf: Introduce struct bpf_kfunc_meta
https://git.kernel.org/bpf/bpf-next/c/08ca87d63243
- [bpf-next,v3,03/13] bpf: Verifier support for KF_IMPLICIT_ARGS
https://git.kernel.org/bpf/bpf-next/c/64e1360524b9
- [bpf-next,v3,04/13] resolve_btfids: Introduce finalize_btf() step
https://git.kernel.org/bpf/bpf-next/c/2583e81fd885
- [bpf-next,v3,05/13] resolve_btfids: Support for KF_IMPLICIT_ARGS
https://git.kernel.org/bpf/bpf-next/c/9d199965990c
- [bpf-next,v3,06/13] selftests/bpf: Add tests for KF_IMPLICIT_ARGS
https://git.kernel.org/bpf/bpf-next/c/e939f3d16d77
- [bpf-next,v3,07/13] bpf: Migrate bpf_wq_set_callback_impl() to KF_IMPLICIT_ARGS
https://git.kernel.org/bpf/bpf-next/c/b97931a25a4b
- [bpf-next,v3,08/13] HID: Use bpf_wq_set_callback kernel function
https://git.kernel.org/bpf/bpf-next/c/8157cc739ad3
- [bpf-next,v3,09/13] bpf: Migrate bpf_task_work_schedule_* kfuncs to KF_IMPLICIT_ARGS
(no matching commit)
- [bpf-next,v3,10/13] bpf: Migrate bpf_stream_vprintk() to KF_IMPLICIT_ARGS
https://git.kernel.org/bpf/bpf-next/c/d806f3101276
- [bpf-next,v3,11/13] selftests/bpf: Migrate struct_ops_assoc test to KF_IMPLICIT_ARGS
https://git.kernel.org/bpf/bpf-next/c/bd06b977e02d
- [bpf-next,v3,12/13] bpf: Remove __prog kfunc arg annotation
https://git.kernel.org/bpf/bpf-next/c/aed57a363871
- [bpf-next,v3,13/13] bpf,docs: Document KF_IMPLICIT_ARGS flag
https://git.kernel.org/bpf/bpf-next/c/74bc4f612720
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH bpf-next v3 09/13] bpf: Migrate bpf_task_work_schedule_* kfuncs to KF_IMPLICIT_ARGS
From: Alexei Starovoitov @ 2026-01-21 0:28 UTC (permalink / raw)
To: Ihor Solodrai
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Mykyta Yatsenko, Tejun Heo,
Alan Maguire, Benjamin Tissoires, Jiri Kosina, Amery Hung, bpf,
LKML, open list:HID CORE LAYER, sched-ext
In-Reply-To: <20260120222638.3976562-10-ihor.solodrai@linux.dev>
On Tue, Jan 20, 2026 at 2:27 PM Ihor Solodrai <ihor.solodrai@linux.dev> wrote:
>
> return 0;
> - bpf_task_work_schedule_signal_impl(task, &work->tw, &arrmap, process_work, NULL);
> +
> + bpf_task_work_schedule_signal(task, &work->tw, &arrmap, process_work);
> +
> return 0;
> }
>
> @@ -102,6 +105,8 @@ int oncpu_lru_map(struct pt_regs *args)
> work = bpf_map_lookup_elem(&lrumap, &key);
> if (!work || work->data[0])
> return 0;
> - bpf_task_work_schedule_resume_impl(task, &work->tw, &lrumap, process_work, NULL);
> +
> + bpf_task_work_schedule_resume(task, &work->tw, &lrumap, process_work);
> +
> return 0;
I removed extra empty lines, since they don't fit the style
of these tests.
While applying.
^ permalink raw reply
* Re: [PATCH] arm64: dts: qcom: milos-fairphone-fp6: Add Hall Effect sensor
From: Dmitry Baryshkov @ 2026-01-20 23:05 UTC (permalink / raw)
To: Luca Weiss, Dmitry Torokhov
Cc: Konrad Dybcio, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, ~postmarketos/upstreaming,
phone-devel, linux-arm-msm, devicetree, linux-kernel, linux-input
In-Reply-To: <DFSOPXFSOUY2.2Z6XCLCD796Q@fairphone.com>
On Mon, Jan 19, 2026 at 04:52:23PM +0100, Luca Weiss wrote:
> On Mon Jan 19, 2026 at 3:41 PM CET, Konrad Dybcio wrote:
> > On 1/16/26 3:22 PM, Luca Weiss wrote:
> >> Add a node for the Hall Effect sensor, used to detect whether the Flip
> >> Cover is closed or not.
> >>
> >> The sensor is powered through vreg_l10b, so let's put a
> >> regulator-always-on on that to make sure the sensor gets power.
> >
> > Is there anything else on L10B? Can we turn it off if the hall sensor
> > is e.g. user-disabled?
>
> It's the voltage source for pull-up of sensor I2C bus (so
> ADSP-managed?), DVDD for amplifiers and VDD for a most sensors like
> the gyro.
>
> So realistically, it'll probably be (nearly) always on anyways. And I
> don't want to shave another yak by adding vdd support to gpio-keys...
Why? If it is exactly what happens on the board: the device producing
GPIO events _is_ powered via a vdd. Added Input maintainer / list to cc.
>
> Regards
> Luca
>
> >
> > Konrad
> >
> >>
> >> Signed-off-by: Luca Weiss <luca.weiss@fairphone.com>
> >> ---
> >> arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts | 12 ++++++++++++
> >> 1 file changed, 12 insertions(+)
> >>
> >> diff --git a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
> >> index 7629ceddde2a..98b3fc654206 100644
> >> --- a/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
> >> +++ b/arch/arm64/boot/dts/qcom/milos-fairphone-fp6.dts
> >> @@ -32,6 +32,16 @@ gpio-keys {
> >> pinctrl-0 = <&volume_up_default>;
> >> pinctrl-names = "default";
> >>
> >> + /* Powered by the always-on vreg_l10b */
> >> + event-hall-sensor {
> >> + label = "Hall Effect Sensor";
> >> + gpios = <&tlmm 70 GPIO_ACTIVE_LOW>;
> >> + linux,input-type = <EV_SW>;
> >> + linux,code = <SW_LID>;
> >> + linux,can-disable;
> >> + wakeup-source;
> >> + };
> >> +
> >> key-volume-up {
> >> label = "Volume Up";
> >> gpios = <&pm7550_gpios 6 GPIO_ACTIVE_LOW>;
> >> @@ -316,6 +326,8 @@ vreg_l10b: ldo10 {
> >> regulator-min-microvolt = <1800000>;
> >> regulator-max-microvolt = <1800000>;
> >> regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
> >> + /* Hall sensor VDD */
> >> + regulator-always-on;
> >> };
> >>
> >> vreg_l11b: ldo11 {
> >>
> >> ---
> >> base-commit: ef1c7b875741bef0ff37ae8ab8a9aaf407dc141c
> >> change-id: 20260116-fp6-hall-sensor-1049f2f872ac
> >>
> >> Best regards,
>
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH bpf-next v3 07/13] bpf: Migrate bpf_wq_set_callback_impl() to KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-20 23:04 UTC (permalink / raw)
To: bot+bpf-ci, ast, daniel, andrii, martin.lau, eddyz87
Cc: yatsenko, tj, alan.maguire, bentiss, jikos, ameryhung, bpf,
linux-kernel, linux-input, sched-ext, martin.lau, yonghong.song,
clm
In-Reply-To: <e8677fdf7cbe2c1174d7047c51f02516d92a91f9a649a30f0041e0f4bfc0b0a6@mail.kernel.org>
On 1/20/26 2:55 PM, bot+bpf-ci@kernel.org wrote:
>> diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
>> index 2cd9165c7348..68a49b1f77ae 100644
>> --- a/tools/testing/selftests/bpf/bpf_experimental.h
>> +++ b/tools/testing/selftests/bpf/bpf_experimental.h
>> @@ -580,11 +580,6 @@ extern void bpf_iter_css_destroy(struct bpf_iter_css *it) __weak __ksym;
>>
>> extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
>> extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
>> -extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
>> - int (callback_fn)(void *map, int *key, void *value),
>> - unsigned int flags__k, void *aux__ign) __ksym;
>> -#define bpf_wq_set_callback(timer, cb, flags) \
>> - bpf_wq_set_callback_impl(timer, cb, flags, NULL)
>
> The old bpf_wq_set_callback_impl declaration and bpf_wq_set_callback macro
> are removed here, but there does not appear to be a replacement declaration
> for the new bpf_wq_set_callback kfunc.
>
> Test files wq.c and wq_failures.c include bpf_experimental.h but do not
> include vmlinux.h. They continue to call bpf_wq_set_callback() after this
Looks like AI failed to notice, that vmlinux.h is included in
bpf_experimental.h
https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/tree/tools/testing/selftests/bpf/bpf_experimental.h#n4
So the old extern declaration of bpf_wq_set_callback_impl() wasn't
necessary too, although the macro was.
> change. Without an extern declaration such as:
>
> extern int bpf_wq_set_callback(struct bpf_wq *wq,
> int (callback_fn)(void *map, int *key, void *value),
> unsigned int flags) __weak __ksym;
>
> should these test files fail to compile due to the missing declaration?
> The kfunc_implicit_args.c test (from the earlier commit in this series)
> demonstrates that explicit __ksym declarations are needed for kfuncs that
> are not obtained from vmlinux.h.
>
> [ ... ]
>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/21190053819
^ permalink raw reply
* Re: [PATCH bpf-next v3 07/13] bpf: Migrate bpf_wq_set_callback_impl() to KF_IMPLICIT_ARGS
From: bot+bpf-ci @ 2026-01-20 22:55 UTC (permalink / raw)
To: ihor.solodrai, ast, daniel, andrii, martin.lau, eddyz87
Cc: yatsenko, tj, alan.maguire, bentiss, jikos, ameryhung, bpf,
linux-kernel, linux-input, sched-ext, ast, andrii, daniel,
martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
In-Reply-To: <20260120222638.3976562-8-ihor.solodrai@linux.dev>
[-- Attachment #1: Type: text/plain, Size: 1863 bytes --]
> diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
> index 2cd9165c7348..68a49b1f77ae 100644
> --- a/tools/testing/selftests/bpf/bpf_experimental.h
> +++ b/tools/testing/selftests/bpf/bpf_experimental.h
> @@ -580,11 +580,6 @@ extern void bpf_iter_css_destroy(struct bpf_iter_css *it) __weak __ksym;
>
> extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
> extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
> -extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
> - int (callback_fn)(void *map, int *key, void *value),
> - unsigned int flags__k, void *aux__ign) __ksym;
> -#define bpf_wq_set_callback(timer, cb, flags) \
> - bpf_wq_set_callback_impl(timer, cb, flags, NULL)
The old bpf_wq_set_callback_impl declaration and bpf_wq_set_callback macro
are removed here, but there does not appear to be a replacement declaration
for the new bpf_wq_set_callback kfunc.
Test files wq.c and wq_failures.c include bpf_experimental.h but do not
include vmlinux.h. They continue to call bpf_wq_set_callback() after this
change. Without an extern declaration such as:
extern int bpf_wq_set_callback(struct bpf_wq *wq,
int (callback_fn)(void *map, int *key, void *value),
unsigned int flags) __weak __ksym;
should these test files fail to compile due to the missing declaration?
The kfunc_implicit_args.c test (from the earlier commit in this series)
demonstrates that explicit __ksym declarations are needed for kfuncs that
are not obtained from vmlinux.h.
[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/21190053819
^ permalink raw reply
* [PATCH bpf-next v3 13/13] bpf,docs: Document KF_IMPLICIT_ARGS flag
From: Ihor Solodrai @ 2026-01-20 22:30 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman
Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
Jiri Kosina, Amery Hung, bpf, linux-kernel, linux-input,
sched-ext
In-Reply-To: <20260120222638.3976562-1-ihor.solodrai@linux.dev>
Add a section explaining KF_IMPLICIT_ARGS kfunc flag. Remove __prog
arg annotation, as it is no longer supported.
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
Documentation/bpf/kfuncs.rst | 49 +++++++++++++++++++++++-------------
1 file changed, 32 insertions(+), 17 deletions(-)
diff --git a/Documentation/bpf/kfuncs.rst b/Documentation/bpf/kfuncs.rst
index 3eb59a8f9f34..75e6c078e0e7 100644
--- a/Documentation/bpf/kfuncs.rst
+++ b/Documentation/bpf/kfuncs.rst
@@ -232,23 +232,6 @@ Or::
...
}
-2.3.6 __prog Annotation
----------------------------
-This annotation is used to indicate that the argument needs to be fixed up to
-the bpf_prog_aux of the caller BPF program. Any value passed into this argument
-is ignored, and rewritten by the verifier.
-
-An example is given below::
-
- __bpf_kfunc int bpf_wq_set_callback_impl(struct bpf_wq *wq,
- int (callback_fn)(void *map, int *key, void *value),
- unsigned int flags,
- void *aux__prog)
- {
- struct bpf_prog_aux *aux = aux__prog;
- ...
- }
-
.. _BPF_kfunc_nodef:
2.4 Using an existing kernel function
@@ -381,6 +364,38 @@ encouraged to make their use-cases known as early as possible, and participate
in upstream discussions regarding whether to keep, change, deprecate, or remove
those kfuncs if and when such discussions occur.
+2.5.9 KF_IMPLICIT_ARGS flag
+------------------------------------
+
+The KF_IMPLICIT_ARGS flag is used to indicate that the BPF signature
+of the kfunc is different from it's kernel signature, and the values
+for implicit arguments are provided at load time by the verifier.
+
+Only arguments of specific types are implicit.
+Currently only ``struct bpf_prog_aux *`` type is supported.
+
+A kfunc with KF_IMPLICIT_ARGS flag therefore has two types in BTF: one
+function matching the kernel declaration (with _impl suffix in the
+name by convention), and another matching the intended BPF API.
+
+Verifier only allows calls to the non-_impl version of a kfunc, that
+uses a signature without the implicit arguments.
+
+Example declaration:
+
+.. code-block:: c
+
+ __bpf_kfunc int bpf_task_work_schedule_signal(struct task_struct *task, struct bpf_task_work *tw,
+ void *map__map, bpf_task_work_callback_t callback,
+ struct bpf_prog_aux *aux) { ... }
+
+Example usage in BPF program:
+
+.. code-block:: c
+
+ /* note that the last argument is omitted */
+ bpf_task_work_schedule_signal(task, &work->tw, &arrmap, task_work_callback);
+
2.6 Registering the kfuncs
--------------------------
--
2.52.0
^ permalink raw reply related
* [PATCH bpf-next v3 12/13] bpf: Remove __prog kfunc arg annotation
From: Ihor Solodrai @ 2026-01-20 22:26 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman
Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
Jiri Kosina, Amery Hung, bpf, linux-kernel, linux-input,
sched-ext
In-Reply-To: <20260120222638.3976562-1-ihor.solodrai@linux.dev>
Now that all the __prog suffix users in the kernel tree migrated to
KF_IMPLICIT_ARGS, remove it from the verifier.
See prior discussion for context [1].
[1] https://lore.kernel.org/bpf/CAEf4BzbgPfRm9BX=TsZm-TsHFAHcwhPY4vTt=9OT-uhWqf8tqw@mail.gmail.com/
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
kernel/bpf/verifier.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 8e8570e9d167..919556614505 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -12211,13 +12211,6 @@ static bool is_kfunc_arg_irq_flag(const struct btf *btf, const struct btf_param
return btf_param_match_suffix(btf, arg, "__irq_flag");
}
-static bool is_kfunc_arg_prog_aux(const struct btf *btf, const struct btf_param *arg);
-
-static bool is_kfunc_arg_prog(const struct btf *btf, const struct btf_param *arg)
-{
- return btf_param_match_suffix(btf, arg, "__prog") || is_kfunc_arg_prog_aux(btf, arg);
-}
-
static bool is_kfunc_arg_scalar_with_name(const struct btf *btf,
const struct btf_param *arg,
const char *name)
@@ -13280,8 +13273,8 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
if (is_kfunc_arg_ignore(btf, &args[i]))
continue;
- if (is_kfunc_arg_prog(btf, &args[i])) {
- /* Used to reject repeated use of __prog. */
+ if (is_kfunc_arg_prog_aux(btf, &args[i])) {
+ /* Reject repeated use bpf_prog_aux */
if (meta->arg_prog) {
verifier_bug(env, "Only 1 prog->aux argument supported per-kfunc");
return -EFAULT;
--
2.52.0
^ permalink raw reply related
* [PATCH bpf-next v3 11/13] selftests/bpf: Migrate struct_ops_assoc test to KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-20 22:26 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman
Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
Jiri Kosina, Amery Hung, bpf, linux-kernel, linux-input,
sched-ext
In-Reply-To: <20260120222638.3976562-1-ihor.solodrai@linux.dev>
A test kfunc named bpf_kfunc_multi_st_ops_test_1_impl() is a user of
__prog suffix. Subsequent patch removes __prog support in favor of
KF_IMPLICIT_ARGS, so migrate this kfunc to use implicit argument.
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
tools/testing/selftests/bpf/progs/struct_ops_assoc.c | 8 ++++----
.../selftests/bpf/progs/struct_ops_assoc_in_timer.c | 4 ++--
.../testing/selftests/bpf/progs/struct_ops_assoc_reuse.c | 6 +++---
tools/testing/selftests/bpf/test_kmods/bpf_testmod.c | 9 ++++-----
.../testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h | 6 ++++--
5 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/tools/testing/selftests/bpf/progs/struct_ops_assoc.c b/tools/testing/selftests/bpf/progs/struct_ops_assoc.c
index 8f1097903e22..68842e3f936b 100644
--- a/tools/testing/selftests/bpf/progs/struct_ops_assoc.c
+++ b/tools/testing/selftests/bpf/progs/struct_ops_assoc.c
@@ -32,7 +32,7 @@ int BPF_PROG(sys_enter_prog_a, struct pt_regs *regs, long id)
if (!test_pid || task->pid != test_pid)
return 0;
- ret = bpf_kfunc_multi_st_ops_test_1_impl(&args, NULL);
+ ret = bpf_kfunc_multi_st_ops_test_1_assoc(&args);
if (ret != MAP_A_MAGIC)
test_err_a++;
@@ -45,7 +45,7 @@ int syscall_prog_a(void *ctx)
struct st_ops_args args = {};
int ret;
- ret = bpf_kfunc_multi_st_ops_test_1_impl(&args, NULL);
+ ret = bpf_kfunc_multi_st_ops_test_1_assoc(&args);
if (ret != MAP_A_MAGIC)
test_err_a++;
@@ -79,7 +79,7 @@ int BPF_PROG(sys_enter_prog_b, struct pt_regs *regs, long id)
if (!test_pid || task->pid != test_pid)
return 0;
- ret = bpf_kfunc_multi_st_ops_test_1_impl(&args, NULL);
+ ret = bpf_kfunc_multi_st_ops_test_1_assoc(&args);
if (ret != MAP_B_MAGIC)
test_err_b++;
@@ -92,7 +92,7 @@ int syscall_prog_b(void *ctx)
struct st_ops_args args = {};
int ret;
- ret = bpf_kfunc_multi_st_ops_test_1_impl(&args, NULL);
+ ret = bpf_kfunc_multi_st_ops_test_1_assoc(&args);
if (ret != MAP_B_MAGIC)
test_err_b++;
diff --git a/tools/testing/selftests/bpf/progs/struct_ops_assoc_in_timer.c b/tools/testing/selftests/bpf/progs/struct_ops_assoc_in_timer.c
index d5a2ea934284..0bed49e9f217 100644
--- a/tools/testing/selftests/bpf/progs/struct_ops_assoc_in_timer.c
+++ b/tools/testing/selftests/bpf/progs/struct_ops_assoc_in_timer.c
@@ -31,7 +31,7 @@ __noinline static int timer_cb(void *map, int *key, struct bpf_timer *timer)
struct st_ops_args args = {};
recur++;
- timer_test_1_ret = bpf_kfunc_multi_st_ops_test_1_impl(&args, NULL);
+ timer_test_1_ret = bpf_kfunc_multi_st_ops_test_1_assoc(&args);
recur--;
timer_cb_run++;
@@ -64,7 +64,7 @@ int syscall_prog(void *ctx)
struct st_ops_args args = {};
int ret;
- ret = bpf_kfunc_multi_st_ops_test_1_impl(&args, NULL);
+ ret = bpf_kfunc_multi_st_ops_test_1_assoc(&args);
if (ret != MAP_MAGIC)
test_err++;
diff --git a/tools/testing/selftests/bpf/progs/struct_ops_assoc_reuse.c b/tools/testing/selftests/bpf/progs/struct_ops_assoc_reuse.c
index 5bb6ebf5eed4..396b3e58c729 100644
--- a/tools/testing/selftests/bpf/progs/struct_ops_assoc_reuse.c
+++ b/tools/testing/selftests/bpf/progs/struct_ops_assoc_reuse.c
@@ -23,7 +23,7 @@ int BPF_PROG(test_1_a, struct st_ops_args *args)
if (!recur) {
recur++;
- ret = bpf_kfunc_multi_st_ops_test_1_impl(args, NULL);
+ ret = bpf_kfunc_multi_st_ops_test_1_assoc(args);
if (ret != -1)
test_err_a++;
recur--;
@@ -40,7 +40,7 @@ int syscall_prog_a(void *ctx)
struct st_ops_args args = {};
int ret;
- ret = bpf_kfunc_multi_st_ops_test_1_impl(&args, NULL);
+ ret = bpf_kfunc_multi_st_ops_test_1_assoc(&args);
if (ret != MAP_A_MAGIC)
test_err_a++;
@@ -62,7 +62,7 @@ int syscall_prog_b(void *ctx)
struct st_ops_args args = {};
int ret;
- ret = bpf_kfunc_multi_st_ops_test_1_impl(&args, NULL);
+ ret = bpf_kfunc_multi_st_ops_test_1_assoc(&args);
if (ret != MAP_A_MAGIC)
test_err_b++;
diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
index a996b816ecc4..0d542ba64365 100644
--- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
+++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
@@ -1140,7 +1140,7 @@ __bpf_kfunc int bpf_kfunc_st_ops_inc10(struct st_ops_args *args)
}
__bpf_kfunc int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id);
-__bpf_kfunc int bpf_kfunc_multi_st_ops_test_1_impl(struct st_ops_args *args, void *aux_prog);
+__bpf_kfunc int bpf_kfunc_multi_st_ops_test_1_assoc(struct st_ops_args *args, struct bpf_prog_aux *aux);
__bpf_kfunc int bpf_kfunc_implicit_arg(int a, struct bpf_prog_aux *aux);
__bpf_kfunc int bpf_kfunc_implicit_arg_legacy(int a, int b, struct bpf_prog_aux *aux);
@@ -1187,7 +1187,7 @@ BTF_ID_FLAGS(func, bpf_kfunc_st_ops_test_epilogue, KF_SLEEPABLE)
BTF_ID_FLAGS(func, bpf_kfunc_st_ops_test_pro_epilogue, KF_SLEEPABLE)
BTF_ID_FLAGS(func, bpf_kfunc_st_ops_inc10)
BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1)
-BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1_impl)
+BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1_assoc, KF_IMPLICIT_ARGS)
BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg, KF_IMPLICIT_ARGS)
BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg_legacy, KF_IMPLICIT_ARGS)
BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg_legacy_impl)
@@ -1669,13 +1669,12 @@ int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id)
}
/* Call test_1() of the associated struct_ops map */
-int bpf_kfunc_multi_st_ops_test_1_impl(struct st_ops_args *args, void *aux__prog)
+int bpf_kfunc_multi_st_ops_test_1_assoc(struct st_ops_args *args, struct bpf_prog_aux *aux)
{
- struct bpf_prog_aux *prog_aux = (struct bpf_prog_aux *)aux__prog;
struct bpf_testmod_multi_st_ops *st_ops;
int ret = -1;
- st_ops = (struct bpf_testmod_multi_st_ops *)bpf_prog_get_assoc_struct_ops(prog_aux);
+ st_ops = (struct bpf_testmod_multi_st_ops *)bpf_prog_get_assoc_struct_ops(aux);
if (st_ops)
ret = st_ops->test_1(args);
diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h b/tools/testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h
index 2357a0340ffe..225ea30c4e3d 100644
--- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h
+++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h
@@ -161,7 +161,9 @@ void bpf_kfunc_rcu_task_test(struct task_struct *ptr) __ksym;
struct task_struct *bpf_kfunc_ret_rcu_test(void) __ksym;
int *bpf_kfunc_ret_rcu_test_nostruct(int rdonly_buf_size) __ksym;
-int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id) __ksym;
-int bpf_kfunc_multi_st_ops_test_1_impl(struct st_ops_args *args, void *aux__prog) __ksym;
+#ifndef __KERNEL__
+extern int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id) __weak __ksym;
+extern int bpf_kfunc_multi_st_ops_test_1_assoc(struct st_ops_args *args) __weak __ksym;
+#endif
#endif /* _BPF_TESTMOD_KFUNC_H */
--
2.52.0
^ permalink raw reply related
* [PATCH bpf-next v3 10/13] bpf: Migrate bpf_stream_vprintk() to KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-20 22:26 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman
Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
Jiri Kosina, Amery Hung, bpf, linux-kernel, linux-input,
sched-ext
In-Reply-To: <20260120222638.3976562-1-ihor.solodrai@linux.dev>
Implement bpf_stream_vprintk with an implicit bpf_prog_aux argument,
and remote bpf_stream_vprintk_impl from the kernel.
Update the selftests to use the new API with implicit argument.
bpf_stream_vprintk macro is changed to use the new bpf_stream_vprintk
kfunc, and the extern definition of bpf_stream_vprintk_impl is
replaced accordingly.
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
kernel/bpf/helpers.c | 2 +-
kernel/bpf/stream.c | 5 ++---
tools/lib/bpf/bpf_helpers.h | 6 +++---
tools/testing/selftests/bpf/progs/stream_fail.c | 6 +++---
4 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index f2f974b5fb3b..f8aa1320e2f7 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -4533,7 +4533,7 @@ BTF_ID_FLAGS(func, bpf_strncasestr);
#if defined(CONFIG_BPF_LSM) && defined(CONFIG_CGROUPS)
BTF_ID_FLAGS(func, bpf_cgroup_read_xattr, KF_RCU)
#endif
-BTF_ID_FLAGS(func, bpf_stream_vprintk_impl)
+BTF_ID_FLAGS(func, bpf_stream_vprintk, KF_IMPLICIT_ARGS)
BTF_ID_FLAGS(func, bpf_task_work_schedule_signal, KF_IMPLICIT_ARGS)
BTF_ID_FLAGS(func, bpf_task_work_schedule_resume, KF_IMPLICIT_ARGS)
BTF_ID_FLAGS(func, bpf_dynptr_from_file)
diff --git a/kernel/bpf/stream.c b/kernel/bpf/stream.c
index 0b6bc3f30335..24730df55e69 100644
--- a/kernel/bpf/stream.c
+++ b/kernel/bpf/stream.c
@@ -212,14 +212,13 @@ __bpf_kfunc_start_defs();
* Avoid using enum bpf_stream_id so that kfunc users don't have to pull in the
* enum in headers.
*/
-__bpf_kfunc int bpf_stream_vprintk_impl(int stream_id, const char *fmt__str, const void *args,
- u32 len__sz, void *aux__prog)
+__bpf_kfunc int bpf_stream_vprintk(int stream_id, const char *fmt__str, const void *args,
+ u32 len__sz, struct bpf_prog_aux *aux)
{
struct bpf_bprintf_data data = {
.get_bin_args = true,
.get_buf = true,
};
- struct bpf_prog_aux *aux = aux__prog;
u32 fmt_size = strlen(fmt__str) + 1;
struct bpf_stream *stream;
u32 data_len = len__sz;
diff --git a/tools/lib/bpf/bpf_helpers.h b/tools/lib/bpf/bpf_helpers.h
index d4e4e388e625..c145da05a67c 100644
--- a/tools/lib/bpf/bpf_helpers.h
+++ b/tools/lib/bpf/bpf_helpers.h
@@ -315,8 +315,8 @@ enum libbpf_tristate {
___param, sizeof(___param)); \
})
-extern int bpf_stream_vprintk_impl(int stream_id, const char *fmt__str, const void *args,
- __u32 len__sz, void *aux__prog) __weak __ksym;
+extern int bpf_stream_vprintk(int stream_id, const char *fmt__str, const void *args,
+ __u32 len__sz) __weak __ksym;
#define bpf_stream_printk(stream_id, fmt, args...) \
({ \
@@ -328,7 +328,7 @@ extern int bpf_stream_vprintk_impl(int stream_id, const char *fmt__str, const vo
___bpf_fill(___param, args); \
_Pragma("GCC diagnostic pop") \
\
- bpf_stream_vprintk_impl(stream_id, ___fmt, ___param, sizeof(___param), NULL); \
+ bpf_stream_vprintk(stream_id, ___fmt, ___param, sizeof(___param)); \
})
/* Use __bpf_printk when bpf_printk call has 3 or fewer fmt args
diff --git a/tools/testing/selftests/bpf/progs/stream_fail.c b/tools/testing/selftests/bpf/progs/stream_fail.c
index 3662515f0107..8e8249f3521c 100644
--- a/tools/testing/selftests/bpf/progs/stream_fail.c
+++ b/tools/testing/selftests/bpf/progs/stream_fail.c
@@ -10,7 +10,7 @@ SEC("syscall")
__failure __msg("Possibly NULL pointer passed")
int stream_vprintk_null_arg(void *ctx)
{
- bpf_stream_vprintk_impl(BPF_STDOUT, "", NULL, 0, NULL);
+ bpf_stream_vprintk(BPF_STDOUT, "", NULL, 0);
return 0;
}
@@ -18,7 +18,7 @@ SEC("syscall")
__failure __msg("R3 type=scalar expected=")
int stream_vprintk_scalar_arg(void *ctx)
{
- bpf_stream_vprintk_impl(BPF_STDOUT, "", (void *)46, 0, NULL);
+ bpf_stream_vprintk(BPF_STDOUT, "", (void *)46, 0);
return 0;
}
@@ -26,7 +26,7 @@ SEC("syscall")
__failure __msg("arg#1 doesn't point to a const string")
int stream_vprintk_string_arg(void *ctx)
{
- bpf_stream_vprintk_impl(BPF_STDOUT, ctx, NULL, 0, NULL);
+ bpf_stream_vprintk(BPF_STDOUT, ctx, NULL, 0);
return 0;
}
--
2.52.0
^ permalink raw reply related
* [PATCH bpf-next v3 09/13] bpf: Migrate bpf_task_work_schedule_* kfuncs to KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-20 22:26 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman
Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
Jiri Kosina, Amery Hung, bpf, linux-kernel, linux-input,
sched-ext
In-Reply-To: <20260120222638.3976562-1-ihor.solodrai@linux.dev>
Implement bpf_task_work_schedule_* with an implicit bpf_prog_aux
argument, and remove corresponding _impl funcs from the kernel.
Update special kfunc checks in the verifier accordingly.
Update the selftests to use the new API with implicit argument.
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
kernel/bpf/helpers.c | 30 +++++++++----------
kernel/bpf/verifier.c | 12 ++++----
.../testing/selftests/bpf/progs/file_reader.c | 4 ++-
tools/testing/selftests/bpf/progs/task_work.c | 11 +++++--
.../selftests/bpf/progs/task_work_fail.c | 16 +++++++---
.../selftests/bpf/progs/task_work_stress.c | 5 ++--
.../bpf/progs/verifier_async_cb_context.c | 6 ++--
7 files changed, 50 insertions(+), 34 deletions(-)
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index c76a9003b221..f2f974b5fb3b 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -4274,41 +4274,39 @@ static int bpf_task_work_schedule(struct task_struct *task, struct bpf_task_work
}
/**
- * bpf_task_work_schedule_signal_impl - Schedule BPF callback using task_work_add with TWA_SIGNAL
+ * bpf_task_work_schedule_signal - Schedule BPF callback using task_work_add with TWA_SIGNAL
* mode
* @task: Task struct for which callback should be scheduled
* @tw: Pointer to struct bpf_task_work in BPF map value for internal bookkeeping
* @map__map: bpf_map that embeds struct bpf_task_work in the values
* @callback: pointer to BPF subprogram to call
- * @aux__prog: user should pass NULL
+ * @aux: pointer to bpf_prog_aux of the caller BPF program, implicitly set by the verifier
*
* Return: 0 if task work has been scheduled successfully, negative error code otherwise
*/
-__bpf_kfunc int bpf_task_work_schedule_signal_impl(struct task_struct *task,
- struct bpf_task_work *tw, void *map__map,
- bpf_task_work_callback_t callback,
- void *aux__prog)
+__bpf_kfunc int bpf_task_work_schedule_signal(struct task_struct *task, struct bpf_task_work *tw,
+ void *map__map, bpf_task_work_callback_t callback,
+ struct bpf_prog_aux *aux)
{
- return bpf_task_work_schedule(task, tw, map__map, callback, aux__prog, TWA_SIGNAL);
+ return bpf_task_work_schedule(task, tw, map__map, callback, aux, TWA_SIGNAL);
}
/**
- * bpf_task_work_schedule_resume_impl - Schedule BPF callback using task_work_add with TWA_RESUME
+ * bpf_task_work_schedule_resume - Schedule BPF callback using task_work_add with TWA_RESUME
* mode
* @task: Task struct for which callback should be scheduled
* @tw: Pointer to struct bpf_task_work in BPF map value for internal bookkeeping
* @map__map: bpf_map that embeds struct bpf_task_work in the values
* @callback: pointer to BPF subprogram to call
- * @aux__prog: user should pass NULL
+ * @aux: pointer to bpf_prog_aux of the caller BPF program, implicitly set by the verifier
*
* Return: 0 if task work has been scheduled successfully, negative error code otherwise
*/
-__bpf_kfunc int bpf_task_work_schedule_resume_impl(struct task_struct *task,
- struct bpf_task_work *tw, void *map__map,
- bpf_task_work_callback_t callback,
- void *aux__prog)
+__bpf_kfunc int bpf_task_work_schedule_resume(struct task_struct *task, struct bpf_task_work *tw,
+ void *map__map, bpf_task_work_callback_t callback,
+ struct bpf_prog_aux *aux)
{
- return bpf_task_work_schedule(task, tw, map__map, callback, aux__prog, TWA_RESUME);
+ return bpf_task_work_schedule(task, tw, map__map, callback, aux, TWA_RESUME);
}
static int make_file_dynptr(struct file *file, u32 flags, bool may_sleep,
@@ -4536,8 +4534,8 @@ BTF_ID_FLAGS(func, bpf_strncasestr);
BTF_ID_FLAGS(func, bpf_cgroup_read_xattr, KF_RCU)
#endif
BTF_ID_FLAGS(func, bpf_stream_vprintk_impl)
-BTF_ID_FLAGS(func, bpf_task_work_schedule_signal_impl)
-BTF_ID_FLAGS(func, bpf_task_work_schedule_resume_impl)
+BTF_ID_FLAGS(func, bpf_task_work_schedule_signal, KF_IMPLICIT_ARGS)
+BTF_ID_FLAGS(func, bpf_task_work_schedule_resume, KF_IMPLICIT_ARGS)
BTF_ID_FLAGS(func, bpf_dynptr_from_file)
BTF_ID_FLAGS(func, bpf_dynptr_file_discard)
BTF_KFUNCS_END(common_btf_ids)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 51e8c9f70868..8e8570e9d167 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -12457,8 +12457,8 @@ enum special_kfunc_type {
KF_bpf_dynptr_from_file,
KF_bpf_dynptr_file_discard,
KF___bpf_trap,
- KF_bpf_task_work_schedule_signal_impl,
- KF_bpf_task_work_schedule_resume_impl,
+ KF_bpf_task_work_schedule_signal,
+ KF_bpf_task_work_schedule_resume,
KF_bpf_arena_alloc_pages,
KF_bpf_arena_free_pages,
KF_bpf_arena_reserve_pages,
@@ -12534,16 +12534,16 @@ BTF_ID(func, bpf_res_spin_unlock_irqrestore)
BTF_ID(func, bpf_dynptr_from_file)
BTF_ID(func, bpf_dynptr_file_discard)
BTF_ID(func, __bpf_trap)
-BTF_ID(func, bpf_task_work_schedule_signal_impl)
-BTF_ID(func, bpf_task_work_schedule_resume_impl)
+BTF_ID(func, bpf_task_work_schedule_signal)
+BTF_ID(func, bpf_task_work_schedule_resume)
BTF_ID(func, bpf_arena_alloc_pages)
BTF_ID(func, bpf_arena_free_pages)
BTF_ID(func, bpf_arena_reserve_pages)
static bool is_task_work_add_kfunc(u32 func_id)
{
- return func_id == special_kfunc_list[KF_bpf_task_work_schedule_signal_impl] ||
- func_id == special_kfunc_list[KF_bpf_task_work_schedule_resume_impl];
+ return func_id == special_kfunc_list[KF_bpf_task_work_schedule_signal] ||
+ func_id == special_kfunc_list[KF_bpf_task_work_schedule_resume];
}
static bool is_kfunc_ret_null(struct bpf_kfunc_call_arg_meta *meta)
diff --git a/tools/testing/selftests/bpf/progs/file_reader.c b/tools/testing/selftests/bpf/progs/file_reader.c
index 4d756b623557..ff3270a0cb9b 100644
--- a/tools/testing/selftests/bpf/progs/file_reader.c
+++ b/tools/testing/selftests/bpf/progs/file_reader.c
@@ -77,7 +77,9 @@ int on_open_validate_file_read(void *c)
err = 1;
return 0;
}
- bpf_task_work_schedule_signal_impl(task, &work->tw, &arrmap, task_work_callback, NULL);
+
+ bpf_task_work_schedule_signal(task, &work->tw, &arrmap, task_work_callback);
+
return 0;
}
diff --git a/tools/testing/selftests/bpf/progs/task_work.c b/tools/testing/selftests/bpf/progs/task_work.c
index 663a80990f8f..eec422af20b8 100644
--- a/tools/testing/selftests/bpf/progs/task_work.c
+++ b/tools/testing/selftests/bpf/progs/task_work.c
@@ -66,7 +66,8 @@ int oncpu_hash_map(struct pt_regs *args)
if (!work)
return 0;
- bpf_task_work_schedule_resume_impl(task, &work->tw, &hmap, process_work, NULL);
+ bpf_task_work_schedule_resume(task, &work->tw, &hmap, process_work);
+
return 0;
}
@@ -80,7 +81,9 @@ int oncpu_array_map(struct pt_regs *args)
work = bpf_map_lookup_elem(&arrmap, &key);
if (!work)
return 0;
- bpf_task_work_schedule_signal_impl(task, &work->tw, &arrmap, process_work, NULL);
+
+ bpf_task_work_schedule_signal(task, &work->tw, &arrmap, process_work);
+
return 0;
}
@@ -102,6 +105,8 @@ int oncpu_lru_map(struct pt_regs *args)
work = bpf_map_lookup_elem(&lrumap, &key);
if (!work || work->data[0])
return 0;
- bpf_task_work_schedule_resume_impl(task, &work->tw, &lrumap, process_work, NULL);
+
+ bpf_task_work_schedule_resume(task, &work->tw, &lrumap, process_work);
+
return 0;
}
diff --git a/tools/testing/selftests/bpf/progs/task_work_fail.c b/tools/testing/selftests/bpf/progs/task_work_fail.c
index 1270953fd092..557bdf9eb0fc 100644
--- a/tools/testing/selftests/bpf/progs/task_work_fail.c
+++ b/tools/testing/selftests/bpf/progs/task_work_fail.c
@@ -53,7 +53,9 @@ int mismatch_map(struct pt_regs *args)
work = bpf_map_lookup_elem(&arrmap, &key);
if (!work)
return 0;
- bpf_task_work_schedule_resume_impl(task, &work->tw, &hmap, process_work, NULL);
+
+ bpf_task_work_schedule_resume(task, &work->tw, &hmap, process_work);
+
return 0;
}
@@ -65,7 +67,9 @@ int no_map_task_work(struct pt_regs *args)
struct bpf_task_work tw;
task = bpf_get_current_task_btf();
- bpf_task_work_schedule_resume_impl(task, &tw, &hmap, process_work, NULL);
+
+ bpf_task_work_schedule_resume(task, &tw, &hmap, process_work);
+
return 0;
}
@@ -76,7 +80,9 @@ int task_work_null(struct pt_regs *args)
struct task_struct *task;
task = bpf_get_current_task_btf();
- bpf_task_work_schedule_resume_impl(task, NULL, &hmap, process_work, NULL);
+
+ bpf_task_work_schedule_resume(task, NULL, &hmap, process_work);
+
return 0;
}
@@ -91,6 +97,8 @@ int map_null(struct pt_regs *args)
work = bpf_map_lookup_elem(&arrmap, &key);
if (!work)
return 0;
- bpf_task_work_schedule_resume_impl(task, &work->tw, NULL, process_work, NULL);
+
+ bpf_task_work_schedule_resume(task, &work->tw, NULL, process_work);
+
return 0;
}
diff --git a/tools/testing/selftests/bpf/progs/task_work_stress.c b/tools/testing/selftests/bpf/progs/task_work_stress.c
index 55e555f7f41b..0cba36569714 100644
--- a/tools/testing/selftests/bpf/progs/task_work_stress.c
+++ b/tools/testing/selftests/bpf/progs/task_work_stress.c
@@ -51,8 +51,9 @@ int schedule_task_work(void *ctx)
if (!work)
return 0;
}
- err = bpf_task_work_schedule_signal_impl(bpf_get_current_task_btf(), &work->tw, &hmap,
- process_work, NULL);
+ err = bpf_task_work_schedule_signal(bpf_get_current_task_btf(), &work->tw, &hmap,
+ process_work);
+
if (err)
__sync_fetch_and_add(&schedule_error, 1);
else
diff --git a/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c b/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c
index 5d5e1cd4d51d..f47c78719639 100644
--- a/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c
+++ b/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c
@@ -156,7 +156,8 @@ int task_work_non_sleepable_prog(void *ctx)
if (!task)
return 0;
- bpf_task_work_schedule_resume_impl(task, &val->tw, &task_work_map, task_work_cb, NULL);
+ bpf_task_work_schedule_resume(task, &val->tw, &task_work_map, task_work_cb);
+
return 0;
}
@@ -176,6 +177,7 @@ int task_work_sleepable_prog(void *ctx)
if (!task)
return 0;
- bpf_task_work_schedule_resume_impl(task, &val->tw, &task_work_map, task_work_cb, NULL);
+ bpf_task_work_schedule_resume(task, &val->tw, &task_work_map, task_work_cb);
+
return 0;
}
--
2.52.0
^ permalink raw reply related
* [PATCH bpf-next v3 08/13] HID: Use bpf_wq_set_callback kernel function
From: Ihor Solodrai @ 2026-01-20 22:26 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman
Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
Jiri Kosina, Amery Hung, bpf, linux-kernel, linux-input,
sched-ext
In-Reply-To: <20260120222638.3976562-1-ihor.solodrai@linux.dev>
Remove extern declaration of bpf_wq_set_callback_impl() from
hid_bpf_helpers.h and replace bpf_wq_set_callback macro with a
corresponding new declaration.
Tested with:
# append tools/testing/selftests/hid/config and build the kernel
$ make -C tools/testing/selftests/hid
# in built kernel
$ ./tools/testing/selftests/hid/hid_bpf -t test_multiply_events_wq
TAP version 13
1..1
# Starting 1 tests from 1 test cases.
# RUN hid_bpf.test_multiply_events_wq ...
[ 2.575520] hid-generic 0003:0001:0A36.0001: hidraw0: USB HID v0.00 Device [test-uhid-device-138] on 138
# OK hid_bpf.test_multiply_events_wq
ok 1 hid_bpf.test_multiply_events_wq
# PASSED: 1 / 1 tests passed.
# Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0
PASS
Acked-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
drivers/hid/bpf/progs/hid_bpf_helpers.h | 8 +++-----
tools/testing/selftests/hid/progs/hid_bpf_helpers.h | 8 +++-----
2 files changed, 6 insertions(+), 10 deletions(-)
diff --git a/drivers/hid/bpf/progs/hid_bpf_helpers.h b/drivers/hid/bpf/progs/hid_bpf_helpers.h
index bf19785a6b06..228f8d787567 100644
--- a/drivers/hid/bpf/progs/hid_bpf_helpers.h
+++ b/drivers/hid/bpf/progs/hid_bpf_helpers.h
@@ -33,11 +33,9 @@ extern int hid_bpf_try_input_report(struct hid_bpf_ctx *ctx,
/* bpf_wq implementation */
extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
-extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
- int (callback_fn)(void *map, int *key, void *value),
- unsigned int flags__k, void *aux__ign) __ksym;
-#define bpf_wq_set_callback(wq, cb, flags) \
- bpf_wq_set_callback_impl(wq, cb, flags, NULL)
+extern int bpf_wq_set_callback(struct bpf_wq *wq,
+ int (*callback_fn)(void *, int *, void *),
+ unsigned int flags) __weak __ksym;
#define HID_MAX_DESCRIPTOR_SIZE 4096
#define HID_IGNORE_EVENT -1
diff --git a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
index 531228b849da..80ab60905865 100644
--- a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
+++ b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
@@ -116,10 +116,8 @@ extern int hid_bpf_try_input_report(struct hid_bpf_ctx *ctx,
/* bpf_wq implementation */
extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
-extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
- int (callback_fn)(void *map, int *key, void *wq),
- unsigned int flags__k, void *aux__ign) __weak __ksym;
-#define bpf_wq_set_callback(timer, cb, flags) \
- bpf_wq_set_callback_impl(timer, cb, flags, NULL)
+extern int bpf_wq_set_callback(struct bpf_wq *wq,
+ int (*callback_fn)(void *, int *, void *),
+ unsigned int flags) __weak __ksym;
#endif /* __HID_BPF_HELPERS_H */
--
2.52.0
^ permalink raw reply related
* [PATCH bpf-next v3 07/13] bpf: Migrate bpf_wq_set_callback_impl() to KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-20 22:26 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman
Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
Jiri Kosina, Amery Hung, bpf, linux-kernel, linux-input,
sched-ext
In-Reply-To: <20260120222638.3976562-1-ihor.solodrai@linux.dev>
Implement bpf_wq_set_callback() with an implicit bpf_prog_aux
argument, and remove bpf_wq_set_callback_impl().
Update special kfunc checks in the verifier accordingly.
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
kernel/bpf/helpers.c | 11 +++++------
kernel/bpf/verifier.c | 16 ++++++++--------
tools/testing/selftests/bpf/bpf_experimental.h | 5 -----
.../bpf/progs/verifier_async_cb_context.c | 4 ++--
tools/testing/selftests/bpf/progs/wq_failures.c | 4 ++--
5 files changed, 17 insertions(+), 23 deletions(-)
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 9eaa4185e0a7..c76a9003b221 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -3120,12 +3120,11 @@ __bpf_kfunc int bpf_wq_start(struct bpf_wq *wq, unsigned int flags)
return 0;
}
-__bpf_kfunc int bpf_wq_set_callback_impl(struct bpf_wq *wq,
- int (callback_fn)(void *map, int *key, void *value),
- unsigned int flags,
- void *aux__prog)
+__bpf_kfunc int bpf_wq_set_callback(struct bpf_wq *wq,
+ int (callback_fn)(void *map, int *key, void *value),
+ unsigned int flags,
+ struct bpf_prog_aux *aux)
{
- struct bpf_prog_aux *aux = (struct bpf_prog_aux *)aux__prog;
struct bpf_async_kern *async = (struct bpf_async_kern *)wq;
if (flags)
@@ -4488,7 +4487,7 @@ BTF_ID_FLAGS(func, bpf_dynptr_memset)
BTF_ID_FLAGS(func, bpf_modify_return_test_tp)
#endif
BTF_ID_FLAGS(func, bpf_wq_init)
-BTF_ID_FLAGS(func, bpf_wq_set_callback_impl)
+BTF_ID_FLAGS(func, bpf_wq_set_callback, KF_IMPLICIT_ARGS)
BTF_ID_FLAGS(func, bpf_wq_start)
BTF_ID_FLAGS(func, bpf_preempt_disable)
BTF_ID_FLAGS(func, bpf_preempt_enable)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index adc24a2ce5b6..51e8c9f70868 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -520,7 +520,7 @@ static bool is_async_callback_calling_kfunc(u32 btf_id);
static bool is_callback_calling_kfunc(u32 btf_id);
static bool is_bpf_throw_kfunc(struct bpf_insn *insn);
-static bool is_bpf_wq_set_callback_impl_kfunc(u32 btf_id);
+static bool is_bpf_wq_set_callback_kfunc(u32 btf_id);
static bool is_task_work_add_kfunc(u32 func_id);
static bool is_sync_callback_calling_function(enum bpf_func_id func_id)
@@ -562,7 +562,7 @@ static bool is_async_cb_sleepable(struct bpf_verifier_env *env, struct bpf_insn
/* bpf_wq and bpf_task_work callbacks are always sleepable. */
if (bpf_pseudo_kfunc_call(insn) && insn->off == 0 &&
- (is_bpf_wq_set_callback_impl_kfunc(insn->imm) || is_task_work_add_kfunc(insn->imm)))
+ (is_bpf_wq_set_callback_kfunc(insn->imm) || is_task_work_add_kfunc(insn->imm)))
return true;
verifier_bug(env, "unhandled async callback in is_async_cb_sleepable");
@@ -12437,7 +12437,7 @@ enum special_kfunc_type {
KF_bpf_percpu_obj_new_impl,
KF_bpf_percpu_obj_drop_impl,
KF_bpf_throw,
- KF_bpf_wq_set_callback_impl,
+ KF_bpf_wq_set_callback,
KF_bpf_preempt_disable,
KF_bpf_preempt_enable,
KF_bpf_iter_css_task_new,
@@ -12501,7 +12501,7 @@ BTF_ID(func, bpf_dynptr_clone)
BTF_ID(func, bpf_percpu_obj_new_impl)
BTF_ID(func, bpf_percpu_obj_drop_impl)
BTF_ID(func, bpf_throw)
-BTF_ID(func, bpf_wq_set_callback_impl)
+BTF_ID(func, bpf_wq_set_callback)
BTF_ID(func, bpf_preempt_disable)
BTF_ID(func, bpf_preempt_enable)
#ifdef CONFIG_CGROUPS
@@ -12994,7 +12994,7 @@ static bool is_sync_callback_calling_kfunc(u32 btf_id)
static bool is_async_callback_calling_kfunc(u32 btf_id)
{
- return btf_id == special_kfunc_list[KF_bpf_wq_set_callback_impl] ||
+ return is_bpf_wq_set_callback_kfunc(btf_id) ||
is_task_work_add_kfunc(btf_id);
}
@@ -13004,9 +13004,9 @@ static bool is_bpf_throw_kfunc(struct bpf_insn *insn)
insn->imm == special_kfunc_list[KF_bpf_throw];
}
-static bool is_bpf_wq_set_callback_impl_kfunc(u32 btf_id)
+static bool is_bpf_wq_set_callback_kfunc(u32 btf_id)
{
- return btf_id == special_kfunc_list[KF_bpf_wq_set_callback_impl];
+ return btf_id == special_kfunc_list[KF_bpf_wq_set_callback];
}
static bool is_callback_calling_kfunc(u32 btf_id)
@@ -14085,7 +14085,7 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
meta.r0_rdonly = false;
}
- if (is_bpf_wq_set_callback_impl_kfunc(meta.func_id)) {
+ if (is_bpf_wq_set_callback_kfunc(meta.func_id)) {
err = push_callback_call(env, insn, insn_idx, meta.subprogno,
set_timer_callback_state);
if (err) {
diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
index 2cd9165c7348..68a49b1f77ae 100644
--- a/tools/testing/selftests/bpf/bpf_experimental.h
+++ b/tools/testing/selftests/bpf/bpf_experimental.h
@@ -580,11 +580,6 @@ extern void bpf_iter_css_destroy(struct bpf_iter_css *it) __weak __ksym;
extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
-extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
- int (callback_fn)(void *map, int *key, void *value),
- unsigned int flags__k, void *aux__ign) __ksym;
-#define bpf_wq_set_callback(timer, cb, flags) \
- bpf_wq_set_callback_impl(timer, cb, flags, NULL)
struct bpf_iter_kmem_cache;
extern int bpf_iter_kmem_cache_new(struct bpf_iter_kmem_cache *it) __weak __ksym;
diff --git a/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c b/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c
index 7efa9521105e..5d5e1cd4d51d 100644
--- a/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c
+++ b/tools/testing/selftests/bpf/progs/verifier_async_cb_context.c
@@ -96,7 +96,7 @@ int wq_non_sleepable_prog(void *ctx)
if (bpf_wq_init(&val->w, &wq_map, 0) != 0)
return 0;
- if (bpf_wq_set_callback_impl(&val->w, wq_cb, 0, NULL) != 0)
+ if (bpf_wq_set_callback(&val->w, wq_cb, 0) != 0)
return 0;
return 0;
}
@@ -114,7 +114,7 @@ int wq_sleepable_prog(void *ctx)
if (bpf_wq_init(&val->w, &wq_map, 0) != 0)
return 0;
- if (bpf_wq_set_callback_impl(&val->w, wq_cb, 0, NULL) != 0)
+ if (bpf_wq_set_callback(&val->w, wq_cb, 0) != 0)
return 0;
return 0;
}
diff --git a/tools/testing/selftests/bpf/progs/wq_failures.c b/tools/testing/selftests/bpf/progs/wq_failures.c
index d06f6d40594a..3767f5595bbc 100644
--- a/tools/testing/selftests/bpf/progs/wq_failures.c
+++ b/tools/testing/selftests/bpf/progs/wq_failures.c
@@ -97,7 +97,7 @@ __failure
/* check that the first argument of bpf_wq_set_callback()
* is a correct bpf_wq pointer.
*/
-__msg(": (85) call bpf_wq_set_callback_impl#") /* anchor message */
+__msg(": (85) call bpf_wq_set_callback#") /* anchor message */
__msg("arg#0 doesn't point to a map value")
long test_wrong_wq_pointer(void *ctx)
{
@@ -123,7 +123,7 @@ __failure
/* check that the first argument of bpf_wq_set_callback()
* is a correct bpf_wq pointer.
*/
-__msg(": (85) call bpf_wq_set_callback_impl#") /* anchor message */
+__msg(": (85) call bpf_wq_set_callback#") /* anchor message */
__msg("off 1 doesn't point to 'struct bpf_wq' that is at 0")
long test_wrong_wq_pointer_offset(void *ctx)
{
--
2.52.0
^ permalink raw reply related
* [PATCH bpf-next v3 06/13] selftests/bpf: Add tests for KF_IMPLICIT_ARGS
From: Ihor Solodrai @ 2026-01-20 22:26 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman
Cc: Mykyta Yatsenko, Tejun Heo, Alan Maguire, Benjamin Tissoires,
Jiri Kosina, Amery Hung, bpf, linux-kernel, linux-input,
sched-ext
In-Reply-To: <20260120222638.3976562-1-ihor.solodrai@linux.dev>
Add trivial end-to-end tests to validate that KF_IMPLICIT_ARGS flag is
properly handled by both resolve_btfids and the verifier.
Declare kfuncs in bpf_testmod. Check that bpf_prog_aux pointer is set
in the kfunc implementation. Verify that calls with implicit args and
a legacy case all work.
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
---
.../bpf/prog_tests/kfunc_implicit_args.c | 10 +++++
.../selftests/bpf/progs/kfunc_implicit_args.c | 41 +++++++++++++++++++
.../selftests/bpf/test_kmods/bpf_testmod.c | 26 ++++++++++++
3 files changed, 77 insertions(+)
create mode 100644 tools/testing/selftests/bpf/prog_tests/kfunc_implicit_args.c
create mode 100644 tools/testing/selftests/bpf/progs/kfunc_implicit_args.c
diff --git a/tools/testing/selftests/bpf/prog_tests/kfunc_implicit_args.c b/tools/testing/selftests/bpf/prog_tests/kfunc_implicit_args.c
new file mode 100644
index 000000000000..5e4793c9c29a
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/kfunc_implicit_args.c
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
+
+#include <test_progs.h>
+#include "kfunc_implicit_args.skel.h"
+
+void test_kfunc_implicit_args(void)
+{
+ RUN_TESTS(kfunc_implicit_args);
+}
diff --git a/tools/testing/selftests/bpf/progs/kfunc_implicit_args.c b/tools/testing/selftests/bpf/progs/kfunc_implicit_args.c
new file mode 100644
index 000000000000..89b6a47e22dd
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/kfunc_implicit_args.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
+
+#include <vmlinux.h>
+#include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
+
+extern int bpf_kfunc_implicit_arg(int a) __weak __ksym;
+extern int bpf_kfunc_implicit_arg_impl(int a, struct bpf_prog_aux *aux) __weak __ksym; /* illegal */
+extern int bpf_kfunc_implicit_arg_legacy(int a, int b) __weak __ksym;
+extern int bpf_kfunc_implicit_arg_legacy_impl(int a, int b, struct bpf_prog_aux *aux) __weak __ksym;
+
+char _license[] SEC("license") = "GPL";
+
+SEC("syscall")
+__retval(5)
+int test_kfunc_implicit_arg(void *ctx)
+{
+ return bpf_kfunc_implicit_arg(5);
+}
+
+SEC("syscall")
+__failure __msg("cannot find address for kernel function bpf_kfunc_implicit_arg_impl")
+int test_kfunc_implicit_arg_impl_illegal(void *ctx)
+{
+ return bpf_kfunc_implicit_arg_impl(5, NULL);
+}
+
+SEC("syscall")
+__retval(7)
+int test_kfunc_implicit_arg_legacy(void *ctx)
+{
+ return bpf_kfunc_implicit_arg_legacy(3, 4);
+}
+
+SEC("syscall")
+__retval(11)
+int test_kfunc_implicit_arg_legacy_impl(void *ctx)
+{
+ return bpf_kfunc_implicit_arg_legacy_impl(5, 6, NULL);
+}
diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
index bc07ce9d5477..a996b816ecc4 100644
--- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
+++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
@@ -1142,6 +1142,10 @@ __bpf_kfunc int bpf_kfunc_st_ops_inc10(struct st_ops_args *args)
__bpf_kfunc int bpf_kfunc_multi_st_ops_test_1(struct st_ops_args *args, u32 id);
__bpf_kfunc int bpf_kfunc_multi_st_ops_test_1_impl(struct st_ops_args *args, void *aux_prog);
+__bpf_kfunc int bpf_kfunc_implicit_arg(int a, struct bpf_prog_aux *aux);
+__bpf_kfunc int bpf_kfunc_implicit_arg_legacy(int a, int b, struct bpf_prog_aux *aux);
+__bpf_kfunc int bpf_kfunc_implicit_arg_legacy_impl(int a, int b, struct bpf_prog_aux *aux);
+
BTF_KFUNCS_START(bpf_testmod_check_kfunc_ids)
BTF_ID_FLAGS(func, bpf_testmod_test_mod_kfunc)
BTF_ID_FLAGS(func, bpf_kfunc_call_test1)
@@ -1184,6 +1188,9 @@ BTF_ID_FLAGS(func, bpf_kfunc_st_ops_test_pro_epilogue, KF_SLEEPABLE)
BTF_ID_FLAGS(func, bpf_kfunc_st_ops_inc10)
BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1)
BTF_ID_FLAGS(func, bpf_kfunc_multi_st_ops_test_1_impl)
+BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg, KF_IMPLICIT_ARGS)
+BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg_legacy, KF_IMPLICIT_ARGS)
+BTF_ID_FLAGS(func, bpf_kfunc_implicit_arg_legacy_impl)
BTF_KFUNCS_END(bpf_testmod_check_kfunc_ids)
static int bpf_testmod_ops_init(struct btf *btf)
@@ -1675,6 +1682,25 @@ int bpf_kfunc_multi_st_ops_test_1_impl(struct st_ops_args *args, void *aux__prog
return ret;
}
+int bpf_kfunc_implicit_arg(int a, struct bpf_prog_aux *aux)
+{
+ if (aux && a > 0)
+ return a;
+ return -EINVAL;
+}
+
+int bpf_kfunc_implicit_arg_legacy(int a, int b, struct bpf_prog_aux *aux)
+{
+ if (aux)
+ return a + b;
+ return -EINVAL;
+}
+
+int bpf_kfunc_implicit_arg_legacy_impl(int a, int b, struct bpf_prog_aux *aux)
+{
+ return bpf_kfunc_implicit_arg_legacy(a, b, aux);
+}
+
static int multi_st_ops_reg(void *kdata, struct bpf_link *link)
{
struct bpf_testmod_multi_st_ops *st_ops =
--
2.52.0
^ permalink raw reply related
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