linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH 1/2] Input: uinput - Allow uinput_request_submit wait interrupting
From: Vicki Pfau @ 2025-12-10  3:37 UTC (permalink / raw)
  To: Dmitry Torokhov, Rafael J. Wysocki; +Cc: linux-input
In-Reply-To: <Za3pB5_n0udgD4d1@google.com>

Hi Dmitry,

It's been nearly 2 years with no updates on this, so I'm going to press on this some again.

On 1/21/24 8:03 PM, Dmitry Torokhov wrote:
> Hi Vicki,
> 
> On Thu, Dec 14, 2023 at 07:04:09PM -0800, Vicki Pfau wrote:
>> Hi Dmitry
>>
>> On 12/8/23 19:24, Vicki Pfau wrote:
>>> Hi Dmitry,
>>>
>>> On 12/8/23 11:32, Dmitry Torokhov wrote:
>>>> Hi Vicki,
>>>>
>>>> On Wed, Dec 06, 2023 at 10:34:05PM -0800, Vicki Pfau wrote:
>>>>> Currently, uinput_request_submit will only fail if the request wait times out.
>>>>> However, in other places this wait is interruptable, and in this specific
>>>>> location it can lead to issues, such as causing system suspend to hang until
>>>>> the request times out.
>>>>
>>>> Could you please explain how a sleeping process can cause suspend to
>>>> hang?
>>>
>>> While I'm not 100% sure how it happens, given I found this by
>>> reproducing it before I came up with a theory for why it happened,
>>> my guess is that as it's trying to suspend all of userspace
>>> programs, it suspends the process that owns the uinput handle, so it
>>> can't continue to service requests, while the other process hangs in
>>> the uninterruptable call, blocking suspend for 30 seconds until the
>>> call times out.
>>>
>>>>
>>>>> Since the timeout is so long, this can cause the
>>>>> appearance of a total system freeze. Making the wait interruptable resolves
>>>>> this and possibly further issues.
>>>>
>>>> I think you are trying to find a justification too hard and it does not
>>>> make sense, however I agree that allowing to kill the process issuing
>>>> the request without waiting for the timeout to expire if the other side
>>>> is stuck might be desirable.
>>>
>>> This isn't reaching. As I said above, I discovered the patched line
>>> of code *after* observing suspend hanging for 30 seconds while
>>> trying to reproduce another bug. I wrote this patch, retested, and
>>> found that it now suspended immediately, leading to a visible
>>> -ERESTARTSYS in strace on coming back from suspend.
>>>
> 
> I must apologize, you indeed weren't reaching. As far as I can see,
> putting tasks into the freezer (which happens during system suspend) is
> done via delivering a fake signal to the task. So the task indeed needs
> to be in an interruptible state, uninterruptible tasks result in system
> failing to suspend.
> 
>>> I can post the reproduction case somewhere, but the test program is
>>> only the evdev client end, with the uinput side being Steam, which I
>>> don't have source code for.
>>>
>>>>
>>>> I think the best way to use wait_for_completion_killable_timeout()
>>>> so that stray signals do not disturb userspace, but the processes can
>>>> still be terminated.
>>>
>>> There's already a mutex_lock_interruptable in uinput_request_send
>>> that could cause this to fall back to userspace under similar
>>> circumstances. The only difference I can find, which is admittedly a
>>> bug in this patch now that I look at it again, is that
>>> uinput_dev_event would get called twice, leading to the request
>>> getting duplicated.
>>
>> After further investigation, it seems this would still be the case
>> even if the request times out--an invalid request would get left in
>> the buffer, which means that while this is a new way to trigger the
>> issue, it's not actually a new issue.
> 
> No, I disagree that it is the same issue. The timeout condition is
> pretty much fatal, I expect the caller to exit or stop using the device
> if request times out (because either the real device is not responding,
> or userspace is not responding, and there is no indication that they
> will start responding any time soon). That is why the timeout value is
> so generous (30 seconds). In this case we definitely not expect the
> request to be re-submitted, either automatically, or explicitly by
> userspace.
> 
> If we make waiting on the request interruptible we may get interrupted
> by a stray signal, and I do not know how both producer (the process
> issuing the uinput request) and consumer of the request, will react to
> essentially duplicate requests being sent.
> 
> I believe we can split this into 2 separate issues:
> 
> 1. The fact that it is not possible terminate the producer process while
> it is waiting for request to be handled (for 30 seconds). I think this
> can be safely resolved by switching to
> wait_for_completion_killable_timeout(). This will allow fatal signals to
> break the wait, and for the process to exit.
> 
> 2. Producer task failing to enter refrigerator and breaking suspend.
> I wonder if the best way to handle that is for uinput to create and
> register wakeup source, and then use __pm_stay_awake() and __pm_relax()
> to indicate to the rest of the system that suspend is blocked. I believe
> userspace should be able to handle this and repeat suspend attempt when
> the condition clears...
> 
> Rafael, do you have any suggestions here? And I wonder, could we make
> killable tasks also enter refrigerator?
> 
> 
> Also, now that I think about it more, we should not use slot number for
> request->id, as I expect the common situation is to have 1 outstanding
> request, so all requests have id 0. Instead we should have a counter and
> increase it. This way timeout handling will be more robust, we will not
> mistake delayed response to the previous request as response to the
> current one.
> 
> Thanks.
> 

Though it may not be the "best" approach, the patch I posted has been shipping in SteamOS for 2 years with, as far as I'm aware, no issues. For obvious reasons, I don't want to be carrying downstream patches for any longer than necessary, so I'd like to see what needs to be done to get this properly fixed. I don't think I'm really familiar enough with the subsystem to fix it in the desired way, but hopefully Rafael can chime in this time, or someone else who is more familiar can make some progress.

Vicki

^ permalink raw reply

* [PATCH] input: synaptics_i2c - cancel delayed work before freeing device
From: Minseong Kim @ 2025-12-10  3:20 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input, linux-kernel, stable, Minseong Kim

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);
+
 	input_unregister_device(touch->input);
 	kfree(touch);
 }
-- 
2.39.5


^ permalink raw reply related

* [dtor-input:for-linus] BUILD SUCCESS 429c4727011ead99129b14dc9ff4c87a747a50ab
From: kernel test robot @ 2025-12-10  3:07 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git for-linus
branch HEAD: 429c4727011ead99129b14dc9ff4c87a747a50ab  Merge branch 'next' into for-linus

elapsed time: 1459m

configs tested: 333
configs skipped: 2

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-15.1.0
alpha                            allyesconfig    gcc-15.1.0
alpha                               defconfig    gcc-15.1.0
arc                              allmodconfig    clang-16
arc                              allmodconfig    gcc-15.1.0
arc                               allnoconfig    gcc-15.1.0
arc                              allyesconfig    clang-22
arc                              allyesconfig    gcc-15.1.0
arc                                 defconfig    gcc-15.1.0
arc                   randconfig-001-20251209    clang-22
arc                   randconfig-001-20251209    gcc-13.4.0
arc                   randconfig-001-20251210    gcc-11.5.0
arc                   randconfig-002-20251209    clang-22
arc                   randconfig-002-20251209    gcc-9.5.0
arc                   randconfig-002-20251210    gcc-11.5.0
arc                        vdk_hs38_defconfig    gcc-15.1.0
arc                    vdk_hs38_smp_defconfig    clang-22
arm                               allnoconfig    gcc-15.1.0
arm                              allyesconfig    clang-16
arm                              allyesconfig    gcc-15.1.0
arm                                 defconfig    clang-22
arm                                 defconfig    gcc-15.1.0
arm                      jornada720_defconfig    clang-22
arm                            mps2_defconfig    clang-22
arm                   randconfig-001-20251209    clang-19
arm                   randconfig-001-20251209    clang-22
arm                   randconfig-001-20251210    gcc-11.5.0
arm                   randconfig-002-20251209    clang-20
arm                   randconfig-002-20251209    clang-22
arm                   randconfig-002-20251210    gcc-11.5.0
arm                   randconfig-003-20251209    clang-22
arm                   randconfig-003-20251210    gcc-11.5.0
arm                   randconfig-004-20251209    clang-22
arm                   randconfig-004-20251210    gcc-11.5.0
arm64                            allmodconfig    clang-19
arm64                            allmodconfig    clang-22
arm64                             allnoconfig    gcc-15.1.0
arm64                               defconfig    gcc-15.1.0
arm64                 randconfig-001-20251209    gcc-8.5.0
arm64                 randconfig-001-20251209    gcc-9.5.0
arm64                 randconfig-001-20251210    clang-17
arm64                 randconfig-002-20251209    gcc-9.5.0
arm64                 randconfig-002-20251210    clang-17
arm64                 randconfig-003-20251209    clang-22
arm64                 randconfig-003-20251209    gcc-9.5.0
arm64                 randconfig-003-20251210    clang-17
arm64                 randconfig-004-20251209    gcc-11.5.0
arm64                 randconfig-004-20251209    gcc-9.5.0
arm64                 randconfig-004-20251210    clang-17
csky                             allmodconfig    gcc-15.1.0
csky                              allnoconfig    gcc-15.1.0
csky                                defconfig    gcc-15.1.0
csky                  randconfig-001-20251209    gcc-15.1.0
csky                  randconfig-001-20251209    gcc-9.5.0
csky                  randconfig-001-20251210    clang-17
csky                  randconfig-002-20251209    gcc-15.1.0
csky                  randconfig-002-20251209    gcc-9.5.0
csky                  randconfig-002-20251210    clang-17
hexagon                          allmodconfig    clang-17
hexagon                          allmodconfig    gcc-15.1.0
hexagon                           allnoconfig    gcc-15.1.0
hexagon                             defconfig    clang-22
hexagon                             defconfig    gcc-15.1.0
hexagon               randconfig-001-20251209    clang-22
hexagon               randconfig-001-20251210    gcc-10.5.0
hexagon               randconfig-002-20251209    clang-22
hexagon               randconfig-002-20251210    gcc-10.5.0
i386                             allmodconfig    clang-20
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-15.1.0
i386                             allyesconfig    clang-20
i386                             allyesconfig    gcc-14
i386        buildonly-randconfig-001-20251209    clang-20
i386        buildonly-randconfig-001-20251209    gcc-14
i386        buildonly-randconfig-001-20251210    clang-20
i386        buildonly-randconfig-002-20251209    clang-20
i386        buildonly-randconfig-002-20251209    gcc-14
i386        buildonly-randconfig-002-20251210    clang-20
i386        buildonly-randconfig-003-20251209    gcc-14
i386        buildonly-randconfig-003-20251210    clang-20
i386        buildonly-randconfig-004-20251209    gcc-14
i386        buildonly-randconfig-004-20251210    clang-20
i386        buildonly-randconfig-005-20251209    gcc-14
i386        buildonly-randconfig-005-20251210    clang-20
i386        buildonly-randconfig-006-20251209    gcc-14
i386        buildonly-randconfig-006-20251210    clang-20
i386                                defconfig    clang-20
i386                                defconfig    gcc-15.1.0
i386                  randconfig-001-20251209    gcc-14
i386                  randconfig-001-20251210    clang-20
i386                  randconfig-002-20251209    clang-20
i386                  randconfig-002-20251210    clang-20
i386                  randconfig-003-20251209    clang-20
i386                  randconfig-003-20251210    clang-20
i386                  randconfig-004-20251209    gcc-14
i386                  randconfig-004-20251210    clang-20
i386                  randconfig-005-20251209    gcc-14
i386                  randconfig-005-20251210    clang-20
i386                  randconfig-006-20251209    clang-20
i386                  randconfig-006-20251210    clang-20
i386                  randconfig-007-20251209    gcc-14
i386                  randconfig-007-20251210    clang-20
i386                  randconfig-011-20251209    clang-20
i386                  randconfig-011-20251209    gcc-14
i386                  randconfig-011-20251210    gcc-14
i386                  randconfig-012-20251209    clang-20
i386                  randconfig-012-20251209    gcc-14
i386                  randconfig-012-20251210    gcc-14
i386                  randconfig-013-20251209    clang-20
i386                  randconfig-013-20251209    gcc-14
i386                  randconfig-013-20251210    gcc-14
i386                  randconfig-014-20251209    clang-20
i386                  randconfig-014-20251209    gcc-14
i386                  randconfig-014-20251210    gcc-14
i386                  randconfig-015-20251209    clang-20
i386                  randconfig-015-20251209    gcc-14
i386                  randconfig-015-20251210    gcc-14
i386                  randconfig-016-20251209    clang-20
i386                  randconfig-016-20251209    gcc-14
i386                  randconfig-016-20251210    gcc-14
i386                  randconfig-017-20251209    gcc-14
i386                  randconfig-017-20251210    gcc-14
loongarch                        allmodconfig    clang-19
loongarch                        allmodconfig    clang-22
loongarch                         allnoconfig    gcc-15.1.0
loongarch                           defconfig    clang-19
loongarch             randconfig-001-20251209    clang-22
loongarch             randconfig-001-20251210    gcc-10.5.0
loongarch             randconfig-002-20251209    clang-22
loongarch             randconfig-002-20251210    gcc-10.5.0
m68k                             allmodconfig    gcc-15.1.0
m68k                              allnoconfig    gcc-15.1.0
m68k                             allyesconfig    clang-16
m68k                             allyesconfig    gcc-15.1.0
m68k                                defconfig    clang-19
m68k                                defconfig    gcc-15.1.0
m68k                        m5407c3_defconfig    gcc-15.1.0
m68k                          sun3x_defconfig    clang-22
microblaze                        allnoconfig    gcc-15.1.0
microblaze                       allyesconfig    gcc-15.1.0
microblaze                          defconfig    clang-19
microblaze                          defconfig    gcc-15.1.0
mips                             allmodconfig    gcc-15.1.0
mips                              allnoconfig    gcc-15.1.0
mips                             allyesconfig    gcc-15.1.0
mips                  cavium_octeon_defconfig    gcc-15.1.0
mips                       rbtx49xx_defconfig    clang-22
mips                       rbtx49xx_defconfig    gcc-15.1.0
nios2                            allmodconfig    clang-22
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-22
nios2                             allnoconfig    gcc-11.5.0
nios2                               defconfig    clang-19
nios2                               defconfig    gcc-11.5.0
nios2                 randconfig-001-20251209    gcc-8.5.0
nios2                 randconfig-001-20251210    gcc-10.5.0
nios2                 randconfig-002-20251209    gcc-11.5.0
nios2                 randconfig-002-20251210    gcc-10.5.0
openrisc                         allmodconfig    clang-22
openrisc                         allmodconfig    gcc-15.1.0
openrisc                          allnoconfig    clang-22
openrisc                          allnoconfig    gcc-15.1.0
openrisc                            defconfig    gcc-15.1.0
openrisc                 simple_smp_defconfig    clang-22
parisc                           allmodconfig    gcc-15.1.0
parisc                            allnoconfig    clang-22
parisc                            allnoconfig    gcc-15.1.0
parisc                           allyesconfig    clang-19
parisc                           allyesconfig    gcc-15.1.0
parisc                              defconfig    gcc-15.1.0
parisc                randconfig-001-20251209    gcc-15.1.0
parisc                randconfig-001-20251209    gcc-8.5.0
parisc                randconfig-001-20251210    clang-19
parisc                randconfig-002-20251209    gcc-13.4.0
parisc                randconfig-002-20251209    gcc-15.1.0
parisc                randconfig-002-20251210    clang-19
parisc64                            defconfig    clang-19
parisc64                            defconfig    gcc-15.1.0
powerpc                          allmodconfig    gcc-15.1.0
powerpc                           allnoconfig    clang-22
powerpc                           allnoconfig    gcc-15.1.0
powerpc                      chrp32_defconfig    gcc-15.1.0
powerpc                    ge_imp3a_defconfig    gcc-15.1.0
powerpc                   lite5200b_defconfig    gcc-15.1.0
powerpc               randconfig-001-20251209    gcc-14.3.0
powerpc               randconfig-001-20251209    gcc-15.1.0
powerpc               randconfig-001-20251210    clang-19
powerpc               randconfig-002-20251209    clang-22
powerpc               randconfig-002-20251209    gcc-15.1.0
powerpc               randconfig-002-20251210    clang-19
powerpc64             randconfig-001-20251209    gcc-14.3.0
powerpc64             randconfig-001-20251209    gcc-15.1.0
powerpc64             randconfig-001-20251210    clang-19
powerpc64             randconfig-002-20251209    gcc-15.1.0
powerpc64             randconfig-002-20251210    clang-19
riscv                            allmodconfig    clang-22
riscv                             allnoconfig    clang-22
riscv                             allnoconfig    gcc-15.1.0
riscv                            allyesconfig    clang-16
riscv                               defconfig    clang-22
riscv                               defconfig    gcc-15.1.0
riscv                 randconfig-001-20251209    clang-22
riscv                 randconfig-001-20251210    clang-22
riscv                 randconfig-002-20251209    clang-18
riscv                 randconfig-002-20251210    clang-22
s390                             allmodconfig    clang-18
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-22
s390                             allyesconfig    gcc-15.1.0
s390                                defconfig    clang-22
s390                                defconfig    gcc-15.1.0
s390                  randconfig-001-20251209    gcc-12.5.0
s390                  randconfig-001-20251210    clang-22
s390                  randconfig-002-20251209    gcc-12.5.0
s390                  randconfig-002-20251210    clang-22
sh                               allmodconfig    gcc-15.1.0
sh                                allnoconfig    clang-22
sh                                allnoconfig    gcc-15.1.0
sh                               allyesconfig    clang-19
sh                               allyesconfig    gcc-15.1.0
sh                         ap325rxa_defconfig    gcc-15.1.0
sh                                  defconfig    gcc-14
sh                                  defconfig    gcc-15.1.0
sh                               j2_defconfig    gcc-15.1.0
sh                          r7785rp_defconfig    clang-22
sh                    randconfig-001-20251209    gcc-14.3.0
sh                    randconfig-001-20251210    clang-22
sh                    randconfig-002-20251209    gcc-13.4.0
sh                    randconfig-002-20251210    clang-22
sh                           se7206_defconfig    clang-22
sh                           sh2007_defconfig    gcc-15.1.0
sparc                             allnoconfig    clang-22
sparc                             allnoconfig    gcc-15.1.0
sparc                               defconfig    gcc-15.1.0
sparc                 randconfig-001-20251209    gcc-11.5.0
sparc                 randconfig-001-20251210    gcc-15.1.0
sparc                 randconfig-002-20251209    gcc-15.1.0
sparc                 randconfig-002-20251210    gcc-15.1.0
sparc64                          allmodconfig    clang-22
sparc64                             defconfig    clang-20
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20251209    clang-22
sparc64               randconfig-001-20251210    gcc-15.1.0
sparc64               randconfig-002-20251209    clang-20
sparc64               randconfig-002-20251210    gcc-15.1.0
um                               allmodconfig    clang-19
um                                allnoconfig    clang-22
um                               allyesconfig    gcc-14
um                               allyesconfig    gcc-15.1.0
um                                  defconfig    clang-22
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20251209    gcc-14
um                    randconfig-001-20251210    gcc-15.1.0
um                    randconfig-002-20251209    gcc-14
um                    randconfig-002-20251210    gcc-15.1.0
um                           x86_64_defconfig    clang-22
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-20
x86_64                            allnoconfig    clang-20
x86_64                            allnoconfig    clang-22
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20251209    clang-20
x86_64      buildonly-randconfig-001-20251209    gcc-14
x86_64      buildonly-randconfig-001-20251210    clang-20
x86_64      buildonly-randconfig-002-20251209    gcc-14
x86_64      buildonly-randconfig-002-20251210    clang-20
x86_64      buildonly-randconfig-003-20251209    gcc-14
x86_64      buildonly-randconfig-003-20251210    clang-20
x86_64      buildonly-randconfig-004-20251209    clang-20
x86_64      buildonly-randconfig-004-20251209    gcc-14
x86_64      buildonly-randconfig-004-20251210    clang-20
x86_64      buildonly-randconfig-005-20251209    clang-20
x86_64      buildonly-randconfig-005-20251209    gcc-14
x86_64      buildonly-randconfig-005-20251210    clang-20
x86_64      buildonly-randconfig-006-20251209    clang-20
x86_64      buildonly-randconfig-006-20251209    gcc-14
x86_64      buildonly-randconfig-006-20251210    clang-20
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-20
x86_64                randconfig-001-20251209    clang-20
x86_64                randconfig-001-20251210    gcc-14
x86_64                randconfig-002-20251209    clang-20
x86_64                randconfig-002-20251210    gcc-14
x86_64                randconfig-003-20251209    clang-20
x86_64                randconfig-003-20251210    gcc-14
x86_64                randconfig-004-20251209    gcc-14
x86_64                randconfig-004-20251210    gcc-14
x86_64                randconfig-005-20251209    gcc-14
x86_64                randconfig-005-20251210    gcc-14
x86_64                randconfig-006-20251209    gcc-14
x86_64                randconfig-006-20251210    gcc-14
x86_64                randconfig-011-20251209    gcc-14
x86_64                randconfig-011-20251210    clang-20
x86_64                randconfig-012-20251209    clang-20
x86_64                randconfig-012-20251210    clang-20
x86_64                randconfig-013-20251209    gcc-14
x86_64                randconfig-013-20251210    clang-20
x86_64                randconfig-014-20251209    clang-20
x86_64                randconfig-014-20251210    clang-20
x86_64                randconfig-015-20251209    clang-20
x86_64                randconfig-015-20251210    clang-20
x86_64                randconfig-016-20251209    clang-20
x86_64                randconfig-016-20251210    clang-20
x86_64                randconfig-071-20251209    clang-20
x86_64                randconfig-071-20251210    clang-20
x86_64                randconfig-072-20251209    gcc-14
x86_64                randconfig-072-20251210    clang-20
x86_64                randconfig-073-20251209    gcc-14
x86_64                randconfig-073-20251210    clang-20
x86_64                randconfig-074-20251209    gcc-14
x86_64                randconfig-074-20251210    clang-20
x86_64                randconfig-075-20251209    gcc-14
x86_64                randconfig-075-20251210    clang-20
x86_64                randconfig-076-20251209    clang-20
x86_64                randconfig-076-20251210    clang-20
x86_64                               rhel-9.4    clang-20
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-20
x86_64                    rhel-9.4-kselftests    clang-20
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    clang-22
xtensa                            allnoconfig    gcc-15.1.0
xtensa                           allyesconfig    clang-22
xtensa                generic_kc705_defconfig    gcc-15.1.0
xtensa                randconfig-001-20251209    gcc-13.4.0
xtensa                randconfig-001-20251210    gcc-15.1.0
xtensa                randconfig-002-20251209    gcc-10.5.0
xtensa                randconfig-002-20251210    gcc-15.1.0
xtensa                    smp_lx200_defconfig    gcc-15.1.0
xtensa                    xip_kc705_defconfig    gcc-15.1.0

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

^ permalink raw reply

* [PATCH] input: mtk-pmic-keys: Fix potential NULL pointer dereference in probe()
From: Haotian Zhang @ 2025-12-10  3:00 UTC (permalink / raw)
  To: dmitry.torokhov, matthias.bgg, angelogioacchino.delregno
  Cc: louisalexis.eyraud, bisson.gary, julien.massot, linux-input,
	linux-kernel, linux-arm-kernel, linux-mediatek, Haotian Zhang

of_match_device() may return NULL when the device node
does not match any entry in the driver's match table.
The current code dereferences of_id->data unconditionally,
which can lead to a NULL pointer dereference.

Add a NULL check for the return value of of_match_device()
and return -ENODEV upon failure.

Fixes: 3e9f0b3e2b27 ("input: Add MediaTek PMIC keys support")
Signed-off-by: Haotian Zhang <vulab@iscas.ac.cn>
---
 drivers/input/keyboard/mtk-pmic-keys.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
index c78d9f6d97c4..474ef36605dc 100644
--- a/drivers/input/keyboard/mtk-pmic-keys.c
+++ b/drivers/input/keyboard/mtk-pmic-keys.c
@@ -335,6 +335,8 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)
 	struct input_dev *input_dev;
 	const struct of_device_id *of_id =
 		of_match_device(of_mtk_pmic_keys_match_tbl, &pdev->dev);
+	if (!of_id)
+		return -ENODEV;
 
 	keys = devm_kzalloc(&pdev->dev, sizeof(*keys), GFP_KERNEL);
 	if (!keys)
-- 
2.50.1.windows.1


^ permalink raw reply related

* [PATCH] HID: intel-ish-hid: Update ishtp bus match to support device ID table
From: Zhang Lixu @ 2025-12-10  2:53 UTC (permalink / raw)
  To: linux-input, srinivas.pandruvada, jikos, benjamin.tissoires; +Cc: lixu.zhang

The ishtp_cl_bus_match() function previously only checked the first entry
in the driver's device ID table. Update it to iterate over the entire
table, allowing proper matching for drivers with multiple supported
protocol GUIDs.

Signed-off-by: Zhang Lixu <lixu.zhang@intel.com>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
---
 drivers/hid/intel-ish-hid/ishtp/bus.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.c b/drivers/hid/intel-ish-hid/ishtp/bus.c
index c6ce37244e49..c3915f3a060e 100644
--- a/drivers/hid/intel-ish-hid/ishtp/bus.c
+++ b/drivers/hid/intel-ish-hid/ishtp/bus.c
@@ -240,9 +240,17 @@ static int ishtp_cl_bus_match(struct device *dev, const struct device_driver *dr
 {
 	struct ishtp_cl_device *device = to_ishtp_cl_device(dev);
 	struct ishtp_cl_driver *driver = to_ishtp_cl_driver(drv);
+	struct ishtp_fw_client *client = device->fw_client;
+	const struct ishtp_device_id *id;
 
-	return(device->fw_client ? guid_equal(&driver->id[0].guid,
-	       &device->fw_client->props.protocol_name) : 0);
+	if (client) {
+		for (id = driver->id; !guid_is_null(&id->guid); id++) {
+			if (guid_equal(&id->guid, &client->props.protocol_name))
+				return 1;
+		}
+	}
+
+	return 0;
 }
 
 /**

base-commit: c75caf76ed86bbc15a72808f48f8df1608a0886c
-- 
2.43.0


^ permalink raw reply related

* [Bug] roccat_report_event() uses mutex_lock() inside a interrupt handler
From: Armin Wolf @ 2025-12-09 21:38 UTC (permalink / raw)
  To: de
  Cc: Jiri Kosina, Benjamin Tissoires,
	open list:INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN)...

Hello,

i finally had the time to debug an locking issue inside the driver of my Roccat Ryos USB keyboard:

[   24.370282] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:591
[   24.370564] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 0, name: swapper/7
[   24.370573] preempt_count: 101, expected: 0
[   24.370580] RCU nest depth: 0, expected: 0
[   24.370587] 2 locks held by swapper/7/0:
[   24.370593]  #0: ffff9881c0053d48 ((wq_completion)events_bh_highpri){+.-.}-{0:0}, at: process_one_work+0x425/0x6a0
[   24.370624]  #1: ffffbb560036cee0 ((work_completion)(&bh->bh)){+.-.}-{0:0}, at: process_one_work+0x1e5/0x6a0
[   24.370652] Preemption disabled at:
[   24.370656] [<ffffffffbb37f9b6>] __raw_spin_lock_irqsave+0x26/0x60
[   24.370669] CPU: 7 UID: 0 PID: 0 Comm: swapper/7 Tainted: G            E       6.18.0+ #13 PREEMPT(voluntary)
[   24.370673] Tainted: [E]=UNSIGNED_MODULE
[   24.370674] Hardware name: ASUS System Product Name/PRIME B650-PLUS, BIOS 3602 11/13/2025
[   24.370675] Call Trace:
[   24.370677]  <IRQ>
[   24.370680]  dump_stack_lvl+0x8d/0xb0
[   24.370687]  __might_resched+0x1a0/0x2b0
[   24.370696]  __mutex_lock+0x67/0x1020
[   24.370699]  ? __create_object+0x5e/0x90
[   24.370706]  ? srso_alias_return_thunk+0x5/0xfbef5
[   24.370709]  ? roccat_report_event+0x44/0xe0 [hid_roccat]
[   24.370712]  ? srso_alias_return_thunk+0x5/0xfbef5
[   24.370718]  ? roccat_report_event+0x27/0xe0 [hid_roccat]
[   24.370735]  ? roccat_report_event+0x44/0xe0 [hid_roccat]
[   24.370737]  ? srso_alias_return_thunk+0x5/0xfbef5
[   24.370739]  roccat_report_event+0x44/0xe0 [hid_roccat]
[   24.370746]  ryos_raw_event+0x3f/0x50 [hid_roccat_ryos]
[   24.370750]  __hid_input_report+0x129/0x1f0 [hid]
[   24.370766]  hid_input_report+0x11/0x20 [hid]
[   24.370773]  hid_irq_in+0x104/0x1f0 [usbhid]
[   24.370783]  __usb_hcd_giveback_urb+0xa0/0x120 [usbcore]
[   24.370800]  usb_giveback_urb_bh+0xa6/0x130 [usbcore]
[   24.370820]  process_one_work+0x226/0x6a0
[   24.370824]  ? srso_alias_return_thunk+0x5/0xfbef5
[   24.370839]  bh_worker+0x17b/0x1e0
[   24.370849]  tasklet_hi_action+0x17/0x40
[   24.370853]  handle_softirqs+0xe8/0x410
[   24.370866]  __irq_exit_rcu+0xca/0x120
[   24.370868]  irq_exit_rcu+0xa/0x30
[   24.370871]  common_interrupt+0xb8/0xd0
[   24.370875]  </IRQ>
[   24.370876]  <TASK>
[   24.370881]  asm_common_interrupt+0x22/0x40
[   24.370883] RIP: 0010:cpuidle_enter_state+0x12c/0x4f0
[   24.370886] Code: 01 48 0f a3 05 e5 93 0c 01 0f 82 b4 02 00 00 31 ff e8 98 3a 34 ff 45 84 ff 0f 85 02 02 00 00 e8 1a a8 48 ff fb 0f 1f 44 00 00 <45> 85 f6 0f 88 d4 01 00 00 49 63 d6 48 8d 04 52 48 8d 04 82 49 8d
[   24.370887] RSP: 0018:ffffbb56001d7e68 EFLAGS: 00000202
[   24.370889] RAX: 0000000000030185 RBX: ffff9881e1345c00 RCX: 0000000000000000
[   24.370891] RDX: 0000000000000000 RSI: ffffffffbc7884ca RDI: ffffffffbc767f8c
[   24.370892] RBP: 0000000000000003 R08: 0000000000000001 R09: 0000000000000000
[   24.370893] R10: 0000000000000001 R11: 0000000000000000 R12: ffffffffbd029e60
[   24.370893] R13: 00000005ac93dbee R14: 0000000000000003 R15: 0000000000000000
[   24.370916]  ? cpuidle_enter_state+0x126/0x4f0
[   24.370926]  cpuidle_enter+0x29/0x40
[   24.370933]  cpuidle_idle_call+0xff/0x180
[   24.370942]  do_idle+0x8e/0xe0
[   24.370947]  cpu_startup_entry+0x25/0x30
[   24.370950]  start_secondary+0x11c/0x140
[   24.370957]  common_startup_64+0x13e/0x141
[   24.370984]  </TASK>

[   24.371060] =============================
[   24.371063] [ BUG: Invalid wait context ]
[   24.371065] 6.18.0+ #13 Tainted: G        W   E
[   24.371068] -----------------------------
[   24.371071] swapper/7/0 is trying to lock:
[   24.371073] ffff9881d2a52200 (&device->cbuf_lock){....}-{4:4}, at: roccat_report_event+0x44/0xe0 [hid_roccat]
[   24.371083] other info that might help us debug this:
[   24.371085] context-{3:3}
[   24.371088] 2 locks held by swapper/7/0:
[   24.371090]  #0: ffff9881c0053d48 ((wq_completion)events_bh_highpri){+.-.}-{0:0}, at: process_one_work+0x425/0x6a0
[   24.371100]  #1: ffffbb560036cee0 ((work_completion)(&bh->bh)){+.-.}-{0:0}, at: process_one_work+0x1e5/0x6a0
[   24.371110] stack backtrace:
[   24.371113] CPU: 7 UID: 0 PID: 0 Comm: swapper/7 Tainted: G        W   E       6.18.0+ #13 PREEMPT(voluntary)
[   24.371116] Tainted: [W]=WARN, [E]=UNSIGNED_MODULE
[   24.371116] Hardware name: ASUS System Product Name/PRIME B650-PLUS, BIOS 3602 11/13/2025
[   24.371117] Call Trace:
[   24.371118]  <IRQ>
[   24.371120]  dump_stack_lvl+0x73/0xb0
[   24.371123]  __lock_acquire+0x966/0xbb0
[   24.371127]  ? __raw_spin_lock_irqsave+0x26/0x60
[   24.371131]  lock_acquire.part.0+0xa9/0x230
[   24.371135]  ? roccat_report_event+0x44/0xe0 [hid_roccat]
[   24.371139]  ? srso_alias_return_thunk+0x5/0xfbef5
[   24.371141]  ? rcu_is_watching+0xd/0x40
[   24.371144]  ? srso_alias_return_thunk+0x5/0xfbef5
[   24.371145]  ? lock_acquire+0xee/0x110
[   24.371151]  __mutex_lock+0xb3/0x1020
[   24.371153]  ? roccat_report_event+0x44/0xe0 [hid_roccat]
[   24.371155]  ? __create_object+0x5e/0x90
[   24.371158]  ? srso_alias_return_thunk+0x5/0xfbef5
[   24.371160]  ? roccat_report_event+0x44/0xe0 [hid_roccat]
[   24.371162]  ? srso_alias_return_thunk+0x5/0xfbef5
[   24.371165]  ? roccat_report_event+0x27/0xe0 [hid_roccat]
[   24.371172]  ? roccat_report_event+0x44/0xe0 [hid_roccat]
[   24.371174]  ? srso_alias_return_thunk+0x5/0xfbef5
[   24.371176]  roccat_report_event+0x44/0xe0 [hid_roccat]
[   24.371179]  ryos_raw_event+0x3f/0x50 [hid_roccat_ryos]
[   24.371182]  __hid_input_report+0x129/0x1f0 [hid]
[   24.371190]  hid_input_report+0x11/0x20 [hid]
[   24.371194]  hid_irq_in+0x104/0x1f0 [usbhid]
[   24.371199]  __usb_hcd_giveback_urb+0xa0/0x120 [usbcore]
[   24.371210]  usb_giveback_urb_bh+0xa6/0x130 [usbcore]
[   24.371223]  process_one_work+0x226/0x6a0
[   24.371226]  ? srso_alias_return_thunk+0x5/0xfbef5
[   24.371233]  bh_worker+0x17b/0x1e0
[   24.371238]  tasklet_hi_action+0x17/0x40
[   24.371241]  handle_softirqs+0xe8/0x410
[   24.371247]  __irq_exit_rcu+0xca/0x120
[   24.371249]  irq_exit_rcu+0xa/0x30
[   24.371252]  common_interrupt+0xb8/0xd0
[   24.371255]  </IRQ>
[   24.371255]  <TASK>
[   24.371258]  asm_common_interrupt+0x22/0x40
[   24.371260] RIP: 0010:cpuidle_enter_state+0x12c/0x4f0
[   24.371262] Code: 01 48 0f a3 05 e5 93 0c 01 0f 82 b4 02 00 00 31 ff e8 98 3a 34 ff 45 84 ff 0f 85 02 02 00 00 e8 1a a8 48 ff fb 0f 1f 44 00 00 <45> 85 f6 0f 88 d4 01 00 00 49 63 d6 48 8d 04 52 48 8d 04 82 49 8d
[   24.371263] RSP: 0018:ffffbb56001d7e68 EFLAGS: 00000202
[   24.371265] RAX: 0000000000030185 RBX: ffff9881e1345c00 RCX: 0000000000000000
[   24.371266] RDX: 0000000000000000 RSI: ffffffffbc7884ca RDI: ffffffffbc767f8c
[   24.371267] RBP: 0000000000000003 R08: 0000000000000001 R09: 0000000000000000
[   24.371268] R10: 0000000000000001 R11: 0000000000000000 R12: ffffffffbd029e60
[   24.371268] R13: 00000005ac93dbee R14: 0000000000000003 R15: 0000000000000000
[   24.371278]  ? cpuidle_enter_state+0x126/0x4f0
[   24.371283]  cpuidle_enter+0x29/0x40
[   24.371287]  cpuidle_idle_call+0xff/0x180
[   24.371291]  do_idle+0x8e/0xe0
[   24.371294]  cpu_startup_entry+0x25/0x30
[   24.371297]  start_secondary+0x11c/0x140
[   24.371300]  common_startup_64+0x13e/0x141
[   24.371313]  </TASK>

AFAIK roccat_report_event() is being called from a interrupt handler, so calling functions like mutex_lock()
is not permitted here. However since commit cacdb14b1c8d ("HID: roccat: Fix use-after-free in roccat_read()"),
roccat_report_event() calls mutex_lock()_unlock(), causing the above warnings.

I myself have no experience with HID drivers, so maybe someone can give me a hint on how to fix
this issue.

Thanks,
Armin Wolf


^ permalink raw reply

* Re: [PATCH v1 3/3] dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props
From: Rob Herring @ 2025-12-09 19:22 UTC (permalink / raw)
  To: Fabio Baltieri
  Cc: Dmitry Torokhov, Krzysztof Kozlowski, Conor Dooley, Benson Leung,
	Guenter Roeck, Tzung-Bi Shih, Simon Glass, linux-input,
	devicetree, chrome-platform, linux-kernel
In-Reply-To: <20251209154706.529784-4-fabiobaltieri@chromium.org>

On Tue, Dec 09, 2025 at 03:47:06PM +0000, Fabio Baltieri wrote:
> Add binding documentation for the fn-key and fn-keymap properties,
> verify that the two new properties are either both preseent or none.
> 
> Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
> ---
>  .../bindings/input/google,cros-ec-keyb.yaml   | 60 +++++++++++++++----
>  1 file changed, 49 insertions(+), 11 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml b/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml
> index fefaaf46a240..56adf9026010 100644
> --- a/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml
> +++ b/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml
> @@ -44,6 +44,20 @@ properties:
>        where the lower 16 bits are reserved. This property is specified only
>        when the keyboard has a custom design for the top row keys.
>  
> +  fn-key:
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      An u32 containing the coordinate of the Fn key, use the MATRIX_KEY(row,
> +      col, code) macro, code is ignored.
> +
> +  fn-keymap:

If keymap is linux,keymap, then this should perhaps be linux,fn-keymap. 
Depends if we still think linux,keymap is Linux specific?

> +    $ref: /schemas/types.yaml#/definitions/uint32-array
> +    minItems: 1
> +    maxItems: 32
> +    description: |
> +      An array of u32 mapping the row, column and codes for the function keys,
> +      use the MATRIX_KEY macro to define the elements.
> +
>  dependencies:
>    function-row-physmap: [ 'linux,keymap' ]
>    google,needs-ghost-filter: [ 'linux,keymap' ]
> @@ -51,17 +65,28 @@ dependencies:
>  required:
>    - compatible
>  
> -if:
> -  properties:
> -    compatible:
> -      contains:
> -        const: google,cros-ec-keyb
> -then:
> -  $ref: /schemas/input/matrix-keymap.yaml#
> -  required:
> -    - keypad,num-rows
> -    - keypad,num-columns
> -    - linux,keymap
> +allOf:
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: google,cros-ec-keyb
> +    then:
> +      $ref: /schemas/input/matrix-keymap.yaml#
> +      required:
> +        - keypad,num-rows
> +        - keypad,num-columns
> +        - linux,keymap
> +  - if:
> +      anyOf:
> +        - required:
> +          - fn-key
> +        - required:
> +          - fn-keymap
> +    then:
> +      required:
> +        - fn-key
> +        - fn-keymap

This can be more concisely written as:

dependencies:
  fn-key: [fn-keymap]
  fn-keymap: [fn-key]

^ permalink raw reply

* Re: [PATCH v1 3/3] dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props
From: Rob Herring (Arm) @ 2025-12-09 17:24 UTC (permalink / raw)
  To: Fabio Baltieri
  Cc: Tzung-Bi Shih, Dmitry Torokhov, linux-input, Krzysztof Kozlowski,
	Simon Glass, devicetree, chrome-platform, Guenter Roeck,
	Conor Dooley, Benson Leung, linux-kernel
In-Reply-To: <20251209154706.529784-4-fabiobaltieri@chromium.org>


On Tue, 09 Dec 2025 15:47:06 +0000, Fabio Baltieri wrote:
> Add binding documentation for the fn-key and fn-keymap properties,
> verify that the two new properties are either both preseent or none.
> 
> Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
> ---
>  .../bindings/input/google,cros-ec-keyb.yaml   | 60 +++++++++++++++----
>  1 file changed, 49 insertions(+), 11 deletions(-)
> 

My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:
./Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml:83:11: [warning] wrong indentation: expected 12 but found 10 (indentation)
./Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml:85:11: [warning] wrong indentation: expected 12 but found 10 (indentation)

dtschema/dtc warnings/errors:
Error: Documentation/devicetree/bindings/input/google,cros-ec-keyb.example.dts:83.9-89 Properties must precede subnodes
FATAL ERROR: Unable to parse input tree
make[2]: *** [scripts/Makefile.dtbs:141: Documentation/devicetree/bindings/input/google,cros-ec-keyb.example.dtb] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [/builds/robherring/dt-review-ci/linux/Makefile:1559: dt_binding_check] Error 2
make: *** [Makefile:248: __sub-make] Error 2

doc reference errors (make refcheckdocs):

See https://patchwork.kernel.org/project/devicetree/patch/20251209154706.529784-4-fabiobaltieri@chromium.org

The base for the series is generally the latest rc1. A different dependency
should be noted in *this* patch.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit after running the above command yourself. Note
that DT_SCHEMA_FILES can be set to your schema file to speed up checking
your schema. However, it must be unset to test all examples with your schema.


^ permalink raw reply

* [syzbot] [input?] possible deadlock in tasklet_action_common
From: syzbot @ 2025-12-09 16:19 UTC (permalink / raw)
  To: dmitry.torokhov, linux-input, linux-kernel, syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    c2f2b01b74be Merge tag 'i3c/for-6.19' of git://git.kernel...
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=14d46eb4580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=8750900a7c493a0b
dashboard link: https://syzkaller.appspot.com/bug?extid=16c5be44e508252dc97a
compiler:       Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8

Unfortunately, I don't have any reproducer for this issue yet.

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/ec5bc719b709/disk-c2f2b01b.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/e6d5ede51c70/vmlinux-c2f2b01b.xz
kernel image: https://storage.googleapis.com/syzbot-assets/fcdbd10e4015/bzImage-c2f2b01b.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+16c5be44e508252dc97a@syzkaller.appspotmail.com

======================================================
WARNING: possible circular locking dependency detected
syzkaller #0 Not tainted
------------------------------------------------------
syz.0.3170/17035 is trying to acquire lock:
ffff8880b8824358 (tasklet_sync_callback.cb_lock){+...}-{3:3}, at: spin_lock include/linux/spinlock_rt.h:44 [inline]
ffff8880b8824358 (tasklet_sync_callback.cb_lock){+...}-{3:3}, at: tasklet_lock_callback kernel/softirq.c:864 [inline]
ffff8880b8824358 (tasklet_sync_callback.cb_lock){+...}-{3:3}, at: tasklet_action_common+0x130/0x650 kernel/softirq.c:914

but task is already holding lock:
ffff88805f738270 (&dev->event_lock#2){+.+.}-{3:3}, at: spin_lock include/linux/spinlock_rt.h:44 [inline]
ffff88805f738270 (&dev->event_lock#2){+.+.}-{3:3}, at: class_spinlock_irqsave_constructor include/linux/spinlock.h:585 [inline]
ffff88805f738270 (&dev->event_lock#2){+.+.}-{3:3}, at: input_inject_event+0xa5/0x330 drivers/input/input.c:419

which lock already depends on the new lock.


the existing dependency chain (in reverse order) is:

-> #1 (&dev->event_lock#2){+.+.}-{3:3}:
       rt_spin_lock+0x88/0x3e0 kernel/locking/spinlock_rt.c:56
       spin_lock include/linux/spinlock_rt.h:44 [inline]
       class_spinlock_irqsave_constructor include/linux/spinlock.h:585 [inline]
       input_inject_event+0xa5/0x330 drivers/input/input.c:419
       led_trigger_event+0x13b/0x220 drivers/leds/led-triggers.c:420
       kbd_propagate_led_state drivers/tty/vt/keyboard.c:1065 [inline]
       kbd_bh+0x1ec/0x300 drivers/tty/vt/keyboard.c:1244
       tasklet_action_common+0x36b/0x650 kernel/softirq.c:925
       handle_softirqs+0x226/0x6d0 kernel/softirq.c:622
       __do_softirq kernel/softirq.c:656 [inline]
       run_ktimerd+0xcf/0x190 kernel/softirq.c:1138
       smpboot_thread_fn+0x542/0xa60 kernel/smpboot.c:160
       kthread+0x711/0x8a0 kernel/kthread.c:463
       ret_from_fork+0x599/0xb30 arch/x86/kernel/process.c:158
       ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:246

-> #0 (tasklet_sync_callback.cb_lock){+...}-{3:3}:
       check_prev_add kernel/locking/lockdep.c:3165 [inline]
       check_prevs_add kernel/locking/lockdep.c:3284 [inline]
       validate_chain kernel/locking/lockdep.c:3908 [inline]
       __lock_acquire+0x15a6/0x2cf0 kernel/locking/lockdep.c:5237
       lock_acquire+0x117/0x340 kernel/locking/lockdep.c:5868
       rt_spin_lock+0x88/0x3e0 kernel/locking/spinlock_rt.c:56
       spin_lock include/linux/spinlock_rt.h:44 [inline]
       tasklet_lock_callback kernel/softirq.c:864 [inline]
       tasklet_action_common+0x130/0x650 kernel/softirq.c:914
       handle_softirqs+0x226/0x6d0 kernel/softirq.c:622
       __do_softirq kernel/softirq.c:656 [inline]
       __local_bh_enable_ip+0x1a0/0x2e0 kernel/softirq.c:302
       local_bh_enable include/linux/bottom_half.h:33 [inline]
       __alloc_skb+0x224/0x430 net/core/skbuff.c:674
       alloc_skb include/linux/skbuff.h:1383 [inline]
       hidp_send_message+0xb5/0x230 net/bluetooth/hidp/core.c:111
       hidp_send_intr_message net/bluetooth/hidp/core.c:143 [inline]
       hidp_input_event+0x290/0x370 net/bluetooth/hidp/core.c:175
       input_event_dispose+0x80/0x6b0 drivers/input/input.c:322
       input_inject_event+0x1d8/0x330 drivers/input/input.c:424
       kbd_led_trigger_activate+0xbc/0x100 drivers/tty/vt/keyboard.c:1021
       led_trigger_set+0x533/0x950 drivers/leds/led-triggers.c:220
       led_match_default_trigger drivers/leds/led-triggers.c:277 [inline]
       led_trigger_set_default+0x266/0x2a0 drivers/leds/led-triggers.c:300
       led_classdev_register_ext+0x73d/0x960 drivers/leds/led-class.c:578
       led_classdev_register include/linux/leds.h:274 [inline]
       input_leds_connect+0x517/0x790 drivers/input/input-leds.c:145
       input_attach_handler drivers/input/input.c:994 [inline]
       input_register_device+0xd00/0x1170 drivers/input/input.c:2378
       hidp_session_dev_add net/bluetooth/hidp/core.c:861 [inline]
       hidp_session_probe+0x1a8/0x8a0 net/bluetooth/hidp/core.c:1116
       l2cap_register_user+0xf4/0x200 net/bluetooth/l2cap_core.c:1712
       hidp_connection_add+0x158b/0x1a20 net/bluetooth/hidp/core.c:1378
       do_hidp_sock_ioctl net/bluetooth/hidp/sock.c:81 [inline]
       hidp_sock_ioctl+0x3a8/0x5c0 net/bluetooth/hidp/sock.c:128
       sock_do_ioctl+0xdc/0x300 net/socket.c:1254
       sock_ioctl+0x579/0x790 net/socket.c:1375
       vfs_ioctl fs/ioctl.c:51 [inline]
       __do_sys_ioctl fs/ioctl.c:597 [inline]
       __se_sys_ioctl+0xff/0x170 fs/ioctl.c:583
       do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
       do_syscall_64+0xfa/0xf80 arch/x86/entry/syscall_64.c:94
       entry_SYSCALL_64_after_hwframe+0x77/0x7f

other info that might help us debug this:

 Possible unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  lock(&dev->event_lock#2);
                               lock(tasklet_sync_callback.cb_lock);
                               lock(&dev->event_lock#2);
  lock(tasklet_sync_callback.cb_lock);

 *** DEADLOCK ***

10 locks held by syz.0.3170/17035:
 #0: ffff8880582340b0 (&hdev->lock){+.+.}-{4:4}, at: l2cap_register_user+0x67/0x200 net/bluetooth/l2cap_core.c:1699
 #1: ffffffff8ea34f80 (hidp_session_sem){++++}-{4:4}, at: hidp_session_probe+0x99/0x8a0 net/bluetooth/hidp/core.c:1106
 #2: ffffffff8e31c658 (input_mutex){+.+.}-{4:4}, at: class_mutex_intr_constructor include/linux/mutex.h:255 [inline]
 #2: ffffffff8e31c658 (input_mutex){+.+.}-{4:4}, at: input_register_device+0xa76/0x1170 drivers/input/input.c:2374
 #3: ffff888059fee860 (&led_cdev->led_access){+.+.}-{4:4}, at: led_classdev_register_ext+0x43d/0x960 drivers/leds/led-class.c:536
 #4: ffffffff8dd08160 (triggers_list_lock){++++}-{4:4}, at: led_trigger_set_default+0x77/0x2a0 drivers/leds/led-triggers.c:297
 #5: ffff888059fee788 (&led_cdev->trigger_lock){+.+.}-{4:4}, at: led_trigger_set_default+0x87/0x2a0 drivers/leds/led-triggers.c:298
 #6: ffff88805f738270 (&dev->event_lock#2){+.+.}-{3:3}, at: spin_lock include/linux/spinlock_rt.h:44 [inline]
 #6: ffff88805f738270 (&dev->event_lock#2){+.+.}-{3:3}, at: class_spinlock_irqsave_constructor include/linux/spinlock.h:585 [inline]
 #6: ffff88805f738270 (&dev->event_lock#2){+.+.}-{3:3}, at: input_inject_event+0xa5/0x330 drivers/input/input.c:419
 #7: ffffffff8d5ae880 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire include/linux/rcupdate.h:331 [inline]
 #7: ffffffff8d5ae880 (rcu_read_lock){....}-{1:3}, at: rcu_read_lock include/linux/rcupdate.h:867 [inline]
 #7: ffffffff8d5ae880 (rcu_read_lock){....}-{1:3}, at: __rt_spin_lock kernel/locking/spinlock_rt.c:50 [inline]
 #7: ffffffff8d5ae880 (rcu_read_lock){....}-{1:3}, at: rt_spin_lock+0x1c1/0x3e0 kernel/locking/spinlock_rt.c:57
 #8: ffffffff8d5ae880 (rcu_read_lock){....}-{1:3}, at: rcu_lock_acquire include/linux/rcupdate.h:331 [inline]
 #8: ffffffff8d5ae880 (rcu_read_lock){....}-{1:3}, at: rcu_read_lock include/linux/rcupdate.h:867 [inline]
 #8: ffffffff8d5ae880 (rcu_read_lock){....}-{1:3}, at: class_rcu_constructor include/linux/rcupdate.h:1195 [inline]
 #8: ffffffff8d5ae880 (rcu_read_lock){....}-{1:3}, at: input_inject_event+0xb1/0x330 drivers/input/input.c:420
 #9: ffffffff8d5ae880 (rcu_read_lock){....}-{1:3}, at: __local_bh_disable_ip+0xa1/0x530 kernel/softirq.c:163

stack backtrace:
CPU: 0 UID: 0 PID: 17035 Comm: syz.0.3170 Not tainted syzkaller #0 PREEMPT_{RT,(full)} 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025
Call Trace:
 <TASK>
 dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
 print_circular_bug+0x2e2/0x300 kernel/locking/lockdep.c:2043
 check_noncircular+0x12e/0x150 kernel/locking/lockdep.c:2175
 check_prev_add kernel/locking/lockdep.c:3165 [inline]
 check_prevs_add kernel/locking/lockdep.c:3284 [inline]
 validate_chain kernel/locking/lockdep.c:3908 [inline]
 __lock_acquire+0x15a6/0x2cf0 kernel/locking/lockdep.c:5237
 lock_acquire+0x117/0x340 kernel/locking/lockdep.c:5868
 rt_spin_lock+0x88/0x3e0 kernel/locking/spinlock_rt.c:56
 spin_lock include/linux/spinlock_rt.h:44 [inline]
 tasklet_lock_callback kernel/softirq.c:864 [inline]
 tasklet_action_common+0x130/0x650 kernel/softirq.c:914
 handle_softirqs+0x226/0x6d0 kernel/softirq.c:622
 __do_softirq kernel/softirq.c:656 [inline]
 __local_bh_enable_ip+0x1a0/0x2e0 kernel/softirq.c:302
 local_bh_enable include/linux/bottom_half.h:33 [inline]
 __alloc_skb+0x224/0x430 net/core/skbuff.c:674
 alloc_skb include/linux/skbuff.h:1383 [inline]
 hidp_send_message+0xb5/0x230 net/bluetooth/hidp/core.c:111
 hidp_send_intr_message net/bluetooth/hidp/core.c:143 [inline]
 hidp_input_event+0x290/0x370 net/bluetooth/hidp/core.c:175
 input_event_dispose+0x80/0x6b0 drivers/input/input.c:322
 input_inject_event+0x1d8/0x330 drivers/input/input.c:424
 kbd_led_trigger_activate+0xbc/0x100 drivers/tty/vt/keyboard.c:1021
 led_trigger_set+0x533/0x950 drivers/leds/led-triggers.c:220
 led_match_default_trigger drivers/leds/led-triggers.c:277 [inline]
 led_trigger_set_default+0x266/0x2a0 drivers/leds/led-triggers.c:300
 led_classdev_register_ext+0x73d/0x960 drivers/leds/led-class.c:578
 led_classdev_register include/linux/leds.h:274 [inline]
 input_leds_connect+0x517/0x790 drivers/input/input-leds.c:145
 input_attach_handler drivers/input/input.c:994 [inline]
 input_register_device+0xd00/0x1170 drivers/input/input.c:2378
 hidp_session_dev_add net/bluetooth/hidp/core.c:861 [inline]
 hidp_session_probe+0x1a8/0x8a0 net/bluetooth/hidp/core.c:1116
 l2cap_register_user+0xf4/0x200 net/bluetooth/l2cap_core.c:1712
 hidp_connection_add+0x158b/0x1a20 net/bluetooth/hidp/core.c:1378
 do_hidp_sock_ioctl net/bluetooth/hidp/sock.c:81 [inline]
 hidp_sock_ioctl+0x3a8/0x5c0 net/bluetooth/hidp/sock.c:128
 sock_do_ioctl+0xdc/0x300 net/socket.c:1254
 sock_ioctl+0x579/0x790 net/socket.c:1375
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:597 [inline]
 __se_sys_ioctl+0xff/0x170 fs/ioctl.c:583
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xfa/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f6b7032f749
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f6b6e554038 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007f6b70586180 RCX: 00007f6b7032f749
RDX: 0000200000000280 RSI: 00000000400448c8 RDI: 000000000000000a
RBP: 00007f6b703b3f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f6b70586218 R14: 00007f6b70586180 R15: 00007ffdc2f85848
 </TASK>


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

^ permalink raw reply

* [PATCH v1 3/3] dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props
From: Fabio Baltieri @ 2025-12-09 15:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Benson Leung, Guenter Roeck
  Cc: Fabio Baltieri, Tzung-Bi Shih, Simon Glass, linux-input,
	devicetree, chrome-platform, linux-kernel
In-Reply-To: <20251209154706.529784-1-fabiobaltieri@chromium.org>

Add binding documentation for the fn-key and fn-keymap properties,
verify that the two new properties are either both preseent or none.

Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
---
 .../bindings/input/google,cros-ec-keyb.yaml   | 60 +++++++++++++++----
 1 file changed, 49 insertions(+), 11 deletions(-)

diff --git a/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml b/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml
index fefaaf46a240..56adf9026010 100644
--- a/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml
+++ b/Documentation/devicetree/bindings/input/google,cros-ec-keyb.yaml
@@ -44,6 +44,20 @@ properties:
       where the lower 16 bits are reserved. This property is specified only
       when the keyboard has a custom design for the top row keys.
 
+  fn-key:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      An u32 containing the coordinate of the Fn key, use the MATRIX_KEY(row,
+      col, code) macro, code is ignored.
+
+  fn-keymap:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    minItems: 1
+    maxItems: 32
+    description: |
+      An array of u32 mapping the row, column and codes for the function keys,
+      use the MATRIX_KEY macro to define the elements.
+
 dependencies:
   function-row-physmap: [ 'linux,keymap' ]
   google,needs-ghost-filter: [ 'linux,keymap' ]
@@ -51,17 +65,28 @@ dependencies:
 required:
   - compatible
 
-if:
-  properties:
-    compatible:
-      contains:
-        const: google,cros-ec-keyb
-then:
-  $ref: /schemas/input/matrix-keymap.yaml#
-  required:
-    - keypad,num-rows
-    - keypad,num-columns
-    - linux,keymap
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: google,cros-ec-keyb
+    then:
+      $ref: /schemas/input/matrix-keymap.yaml#
+      required:
+        - keypad,num-rows
+        - keypad,num-columns
+        - linux,keymap
+  - if:
+      anyOf:
+        - required:
+          - fn-key
+        - required:
+          - fn-keymap
+    then:
+      required:
+        - fn-key
+        - fn-keymap
 
 unevaluatedProperties: false
 
@@ -132,6 +157,19 @@ examples:
             /* UP      LEFT    */
             0x070b0067 0x070c0069>;
     };
+    fn-key = <MATRIX_KEY(0x04, 0x0a, 0)>;
+    fn-keymap = <
+            MATRIX_KEY(0x00, 0x02, KEY_F1)  /* T1 */
+            MATRIX_KEY(0x03, 0x02, KEY_F2)  /* T2 */
+            MATRIX_KEY(0x02, 0x02, KEY_F3)  /* T3 */
+            MATRIX_KEY(0x01, 0x02, KEY_F4)  /* T4 */
+            MATRIX_KEY(0x04, 0x04, KEY_F5)  /* T5 */
+            MATRIX_KEY(0x02, 0x04, KEY_F6)  /* T6 */
+            MATRIX_KEY(0x01, 0x04, KEY_F7)  /* T7 */
+            MATRIX_KEY(0x02, 0x0b, KEY_F8)  /* T8 */
+            MATRIX_KEY(0x01, 0x09, KEY_F9)  /* T9 */
+            MATRIX_KEY(0x00, 0x04, KEY_F10) /* T10 */
+    >;
   - |
     /* No matrix keyboard, just buttons/switches */
     keyboard-controller {
-- 
2.52.0.223.gf5cc29aaa4-goog


^ permalink raw reply related

* [PATCH v1 2/3] Input: cros_ec_keyb: add function key support
From: Fabio Baltieri @ 2025-12-09 15:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Benson Leung, Guenter Roeck
  Cc: Fabio Baltieri, Tzung-Bi Shih, Simon Glass, linux-input,
	devicetree, chrome-platform, linux-kernel
In-Reply-To: <20251209154706.529784-1-fabiobaltieri@chromium.org>

Add support for handling an Fn button and sending separate keycodes for
a subset of keys in the matrix.

Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
---
 drivers/input/keyboard/cros_ec_keyb.c | 190 ++++++++++++++++++++++++--
 1 file changed, 176 insertions(+), 14 deletions(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 2822c592880b..b0965e5d20de 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -29,6 +29,14 @@
 
 #include <linux/unaligned.h>
 
+/* Maximum number of Fn keys, limited by the key status mask size. */
+#define CROS_EC_FN_KEYMAP_MAX 32
+
+/* Maximum size of the normal key matrix, this is limited by the host command
+ * key_matrix field defined in ec_response_get_next_data_v3
+ */
+#define CROS_EC_KEYBOARD_COLS_MAX 18
+
 /**
  * struct cros_ec_keyb - Structure representing EC keyboard device
  *
@@ -44,6 +52,13 @@
  * @bs_idev: The input device for non-matrix buttons and switches (or NULL).
  * @notifier: interrupt event notifier for transport devices
  * @vdata: vivaldi function row data
+ * @fn_key: coordinate of the function key
+ * @fn_keymap: array of coordinate and codes for the function keys
+ * @fn_keymap_len: number of entries in the fn_keymap array
+ * @fn_key_status: active function keys bitmap
+ * @normal_key_status: active normal keys bitmap
+ * @fn_key_pressed: tracks the function key status
+ * @fn_key_triggered: tracks where any function key fired
  */
 struct cros_ec_keyb {
 	unsigned int rows;
@@ -61,6 +76,14 @@ struct cros_ec_keyb {
 	struct notifier_block notifier;
 
 	struct vivaldi_data vdata;
+
+	uint32_t fn_key;
+	uint32_t *fn_keymap;
+	int fn_keymap_len;
+	uint32_t fn_key_status;
+	uint8_t normal_key_status[CROS_EC_KEYBOARD_COLS_MAX];
+	bool fn_key_pressed;
+	bool fn_key_triggered;
 };
 
 /**
@@ -166,16 +189,108 @@ static bool cros_ec_keyb_has_ghosting(struct cros_ec_keyb *ckdev, uint8_t *buf)
 	return false;
 }
 
+static bool cros_ec_key_is(int row, int col, uint32_t key)
+{
+	if (row == KEY_ROW(key) && col == KEY_COL(key))
+		return true;
+
+	return false;
+}
+
+static void cros_ec_keyb_process_one(struct cros_ec_keyb *ckdev,
+				     int row, int col, bool state)
+{
+	struct input_dev *idev = ckdev->idev;
+	const unsigned short *keycodes = idev->keycode;
+	int pos = MATRIX_SCAN_CODE(row, col, ckdev->row_shift);
+	unsigned int code = keycodes[pos];
+
+	dev_dbg(ckdev->dev, "changed: [r%d c%d]: byte %02x\n", row, col, state);
+
+	if (ckdev->fn_keymap) {
+		if (cros_ec_key_is(row, col, ckdev->fn_key)) {
+			ckdev->fn_key_pressed = state;
+
+			if (state) {
+				ckdev->fn_key_triggered = false;
+			} else if (!ckdev->fn_key_triggered) {
+				/*
+				 * Send the original code if nothing else has
+				 * been pressed together with Fn.
+				 */
+				input_event(idev, EV_MSC, MSC_SCAN, pos);
+				input_report_key(idev, code, true);
+				input_sync(ckdev->idev);
+
+				input_event(idev, EV_MSC, MSC_SCAN, pos);
+				input_report_key(idev, code, false);
+			}
+
+			return;
+		}
+
+		if (!state) {
+			/* Key release, may need to release the Fn code */
+			for (int i = 0; i < ckdev->fn_keymap_len; i++) {
+				if (!cros_ec_key_is(row, col,
+						    ckdev->fn_keymap[i]))
+					continue;
+
+				if ((ckdev->fn_key_status & BIT(i)) == 0)
+					continue;
+
+				code = KEY_VAL(ckdev->fn_keymap[i]);
+				ckdev->fn_key_status &= ~BIT(i);
+
+				input_event(idev, EV_MSC, MSC_SCAN, pos);
+				input_report_key(idev, code, state);
+
+				return;
+			}
+
+			if ((ckdev->normal_key_status[col] & BIT(row)) == 0)
+				/* Discard, key press code was not sent */
+				return;
+		} else if (ckdev->fn_key_pressed) {
+			/* Key press while holding Fn */
+			ckdev->fn_key_triggered = true;
+
+			for (int i = 0; i < ckdev->fn_keymap_len; i++) {
+				if (!cros_ec_key_is(row, col,
+						    ckdev->fn_keymap[i]))
+					continue;
+
+				code = KEY_VAL(ckdev->fn_keymap[i]);
+				ckdev->fn_key_status |= BIT(i);
+
+				input_event(idev, EV_MSC, MSC_SCAN, pos);
+				input_report_key(idev, code, state);
+
+				return;
+			}
+
+			/* Do not emit a code if the key is not mapped */
+			return;
+		}
+	}
+
+	if (state)
+		ckdev->normal_key_status[col] |= BIT(row);
+	else
+		ckdev->normal_key_status[col] &= ~BIT(row);
+
+	input_event(idev, EV_MSC, MSC_SCAN, pos);
+	input_report_key(idev, code, state);
+}
 
 /*
  * Compares the new keyboard state to the old one and produces key
- * press/release events accordingly.  The keyboard state is 13 bytes (one byte
- * per column)
+ * press/release events accordingly.  The keyboard state is one byte
+ * per column.
  */
 static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
 			 uint8_t *kb_state, int len)
 {
-	struct input_dev *idev = ckdev->idev;
 	int col, row;
 	int new_state;
 	int old_state;
@@ -192,20 +307,13 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
 
 	for (col = 0; col < ckdev->cols; col++) {
 		for (row = 0; row < ckdev->rows; row++) {
-			int pos = MATRIX_SCAN_CODE(row, col, ckdev->row_shift);
-			const unsigned short *keycodes = idev->keycode;
-
 			new_state = kb_state[col] & (1 << row);
 			old_state = ckdev->old_kb_state[col] & (1 << row);
-			if (new_state != old_state) {
-				dev_dbg(ckdev->dev,
-					"changed: [r%d c%d]: byte %02x\n",
-					row, col, new_state);
 
-				input_event(idev, EV_MSC, MSC_SCAN, pos);
-				input_report_key(idev, keycodes[pos],
-						 new_state);
-			}
+			if (new_state == old_state)
+				continue;
+
+			cros_ec_keyb_process_one(ckdev, row, col, new_state);
 		}
 		ckdev->old_kb_state[col] = kb_state[col];
 	}
@@ -604,6 +712,12 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
 	if (err)
 		return err;
 
+	if (ckdev->cols > CROS_EC_KEYBOARD_COLS_MAX) {
+		dev_err(dev, "keypad,num-columns too large: %d (max: %d)\n",
+			ckdev->cols, CROS_EC_KEYBOARD_COLS_MAX);
+		return -EINVAL;
+	}
+
 	ckdev->valid_keys = devm_kzalloc(dev, ckdev->cols, GFP_KERNEL);
 	if (!ckdev->valid_keys)
 		return -ENOMEM;
@@ -660,6 +774,47 @@ static int cros_ec_keyb_register_matrix(struct cros_ec_keyb *ckdev)
 	return 0;
 }
 
+static int cros_ec_keyb_register_fn_keys(struct cros_ec_keyb *ckdev)
+{
+	struct device *dev = ckdev->dev;
+	uint32_t fn_key;
+	uint32_t *keymap;
+	int keymap_len;
+	int ret;
+
+	if (!(device_property_present(dev, "fn-key") &&
+	      device_property_present(dev, "fn-keymap")))
+		return 0;
+
+	device_property_read_u32(dev, "fn-key", &fn_key);
+
+	keymap_len = device_property_count_u32(ckdev->dev, "fn-keymap");
+	if (keymap_len > CROS_EC_FN_KEYMAP_MAX) {
+		dev_err(dev, "fn-keymap too large: %d limit=%d",
+			keymap_len, CROS_EC_FN_KEYMAP_MAX);
+		return -EINVAL;
+	}
+
+	keymap = devm_kcalloc(dev, keymap_len, sizeof(*keymap), GFP_KERNEL);
+	if (!keymap)
+		return -ENOMEM;
+
+	ret = device_property_read_u32_array(dev, "fn-keymap", keymap, keymap_len);
+	if (ret) {
+		dev_err(dev, "failed to read fn-keymap property: %d\n", ret);
+		return ret;
+	}
+
+	for (int i = 0; i < keymap_len; i++)
+		__set_bit(KEY_VAL(keymap[i]), ckdev->idev->keybit);
+
+	ckdev->fn_key = fn_key;
+	ckdev->fn_keymap = keymap;
+	ckdev->fn_keymap_len = keymap_len;
+
+	return 0;
+}
+
 static ssize_t function_row_physmap_show(struct device *dev,
 					 struct device_attribute *attr,
 					 char *buf)
@@ -734,6 +889,13 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
 				err);
 			return err;
 		}
+
+		err = cros_ec_keyb_register_fn_keys(ckdev);
+		if (err) {
+			dev_err(dev, "cannot register fn-keys inputs: %d\n",
+				err);
+			return err;
+		}
 	}
 
 	err = cros_ec_keyb_register_bs(ckdev, buttons_switches_only);
-- 
2.52.0.223.gf5cc29aaa4-goog


^ permalink raw reply related

* [PATCH v1 1/3] Input: cros_ec_keyb: clarify key event error message
From: Fabio Baltieri @ 2025-12-09 15:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Benson Leung, Guenter Roeck
  Cc: Fabio Baltieri, Tzung-Bi Shih, Simon Glass, linux-input,
	devicetree, chrome-platform, linux-kernel
In-Reply-To: <20251209154706.529784-1-fabiobaltieri@chromium.org>

Reword one of the key event error messages to clarify its meaning: it's
not necessarily an incomplete message, more of a mismatch length.
Clarify that and log the expected and received length too.

Signed-off-by: Fabio Baltieri <fabiobaltieri@chromium.org>
---
 drivers/input/keyboard/cros_ec_keyb.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index 1c6b0461dc35..2822c592880b 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -269,7 +269,8 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
 
 		if (ckdev->ec->event_size != ckdev->cols) {
 			dev_err(ckdev->dev,
-				"Discarded incomplete key matrix event.\n");
+				"Discarded key matrix event, unexpected length: %d != %d\n",
+				ckdev->ec->event_size, ckdev->cols);
 			return NOTIFY_OK;
 		}
 
-- 
2.52.0.223.gf5cc29aaa4-goog


^ permalink raw reply related

* [PATCH v1 0/3] Input: cros_ec_keyb: add function key support
From: Fabio Baltieri @ 2025-12-09 15:47 UTC (permalink / raw)
  To: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Benson Leung, Guenter Roeck
  Cc: Fabio Baltieri, Tzung-Bi Shih, Simon Glass, linux-input,
	devicetree, chrome-platform, linux-kernel

Hi,

this adds function key support to the cros_ec_keyb driver: the platform
can specify a key to be used as "function key", and that changes the
keycode emitted for other keys as long as the function key remains
pressed.

The Fn key omits its own code if pressed and released with no other
function key pressed in the meantime. Non mapped keys do not emit any
codes, this seems to be the behavior of other devices I have lying
around.

Fabio Baltieri (3):
  Input: cros_ec_keyb: clarify key event error message
  Input: cros_ec_keyb: add function key support
  dt-bindings: google,cros-ec-keyb: add fn-key and f-keymap props

 .../bindings/input/google,cros-ec-keyb.yaml   |  60 +++++-
 drivers/input/keyboard/cros_ec_keyb.c         | 193 ++++++++++++++++--
 2 files changed, 227 insertions(+), 26 deletions(-)

-- 
2.52.0.223.gf5cc29aaa4-goog


^ permalink raw reply

* Re: [PATCH v2 1/2] iio: dac: ds4424: drop unused include IIO consumer header
From: Andy Shevchenko @ 2025-12-09 14:45 UTC (permalink / raw)
  To: Romain Gantois
  Cc: MyungJoo Ham, Chanwoo Choi, Guenter Roeck, Peter Rosin,
	Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
	Lars-Peter Clausen, Michael Hennerich, Mariel Tinaco, Kevin Tsai,
	Linus Walleij, Dmitry Torokhov, Eugen Hristev, Vinod Koul,
	Kishon Vijay Abraham I, Sebastian Reichel, Chen-Yu Tsai,
	Hans de Goede, Support Opensource, Paul Cercueil, Iskren Chernev,
	Krzysztof Kozlowski, Marek Szyprowski, Matheus Castello,
	Saravanan Sekar, Matthias Brugger, AngeloGioacchino Del Regno,
	Casey Connolly, Pali Rohár, Orson Zhai, Baolin Wang,
	Chunyan Zhang, Amit Kucheria, Thara Gopinath, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Claudiu Beznea,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
	Sylwester Nawrocki, Olivier Moysan, Arnaud Pouliquen,
	Maxime Coquelin, Alexandre Torgue, Thomas Petazzoni, linux-kernel,
	linux-hwmon, linux-iio, linux-input, linux-phy, linux-pm,
	linux-mips, linux-mediatek, linux-arm-msm, linux-sound,
	linux-stm32
In-Reply-To: <20251209-iio-inkern-use-namespaced-exports-v2-1-9799a33c4b7f@bootlin.com>

On Tue, Dec 9, 2025 at 10:26 AM Romain Gantois
<romain.gantois@bootlin.com> wrote:
>
> To prepare for the introduction of namespaced exports for the IIO consumer
> API, remove this include directive which isn't actually used by the driver.

Reviewed-by: Andy Shevchenko <andy@kernel.org>

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* joydev/xpad.c: Add the pad "Nova 2 Lite" from GameSir
From: Qbeliw Tanaka @ 2025-12-09 11:38 UTC (permalink / raw)
  To: linux-input

[-- Attachment #1: Type: Text/Plain, Size: 265 bytes --]

In xpad.c, the gamepad "Nova 2 Lite" made by GameSir works as an xbox-360 controller. I attached a patch. (Sorry, diff -u format, and you have to cd drivers/input/joydev .)

You can use this tag:
Reported-by: Qbelio Tanaka <q.tanaka@gmx.com>

Thank you very much.


[-- Attachment #2: a.patch --]
[-- Type: Text/X-Patch, Size: 600 bytes --]

--- xpad.c.orig	2025-12-01 19:46:09.000000000 +0900
+++ xpad.c	2025-12-08 16:59:39.789039265 +0900
@@ -419,6 +419,7 @@
 	{ 0x3285, 0x0662, "Nacon Revolution5 Pro", 0, XTYPE_XBOX360 },
 	{ 0x3285, 0x0663, "Nacon Evol-X", 0, XTYPE_XBOXONE },
 	{ 0x3537, 0x1004, "GameSir T4 Kaleid", 0, XTYPE_XBOX360 },
+	{ 0x3537, 0x100f, "GameSir Nova 2 Lite", 0, XTYPE_XBOX360 },
 	{ 0x3537, 0x1010, "GameSir G7 SE", 0, XTYPE_XBOXONE },
 	{ 0x366c, 0x0005, "ByoWave Proteus Controller", MAP_SHARE_BUTTON, XTYPE_XBOXONE, FLAG_DELAY_INIT },
 	{ 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX },

^ permalink raw reply

* Re: [PATCH v5 1/2] HID: input: Convert battery code to devm_*
From: Benjamin Tissoires @ 2025-12-09 10:32 UTC (permalink / raw)
  To: Lucas Zampieri
  Cc: linux-input, linux-kernel, Jiri Kosina, Sebastian Reichel,
	Bastien Nocera, linux-pm
In-Reply-To: <20251121131556.601130-2-lzampier@redhat.com>

On Nov 21 2025, Lucas Zampieri wrote:
> Convert the HID battery code to use devm_* managed resource APIs.
> 
> This changes the following allocations:
> - kzalloc() -> devm_kzalloc() for power_supply_desc
> - kasprintf() -> devm_kasprintf() for battery name
> - power_supply_register() -> devm_power_supply_register()
> 
> No functional behavior changes.
> 
> Signed-off-by: Lucas Zampieri <lzampier@redhat.com>
> ---
>  drivers/hid/hid-input.c | 49 +++++++++--------------------------------
>  1 file changed, 10 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> index e56e7de53279..5f313c3c35e2 100644
> --- a/drivers/hid/hid-input.c
> +++ b/drivers/hid/hid-input.c
> @@ -530,17 +530,15 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
>  	if (quirks & HID_BATTERY_QUIRK_IGNORE)
>  		return 0;
>  
> -	psy_desc = kzalloc(sizeof(*psy_desc), GFP_KERNEL);
> +	psy_desc = devm_kzalloc(&dev->dev, sizeof(*psy_desc), GFP_KERNEL);
>  	if (!psy_desc)
>  		return -ENOMEM;
>  
> -	psy_desc->name = kasprintf(GFP_KERNEL, "hid-%s-battery",
> -				   strlen(dev->uniq) ?
> -					dev->uniq : dev_name(&dev->dev));
> -	if (!psy_desc->name) {
> -		error = -ENOMEM;
> -		goto err_free_mem;
> -	}
> +	psy_desc->name = devm_kasprintf(&dev->dev, GFP_KERNEL, "hid-%s-battery",
> +					strlen(dev->uniq) ?
> +						dev->uniq : dev_name(&dev->dev));
> +	if (!psy_desc->name)
> +		return -ENOMEM;
>  
>  	psy_desc->type = POWER_SUPPLY_TYPE_BATTERY;
>  	psy_desc->properties = hidinput_battery_props;
> @@ -576,36 +574,15 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
>  	if (quirks & HID_BATTERY_QUIRK_AVOID_QUERY)
>  		dev->battery_avoid_query = true;
>  
> -	dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg);
> +	dev->battery = devm_power_supply_register(&dev->dev, psy_desc, &psy_cfg);
>  	if (IS_ERR(dev->battery)) {
> -		error = PTR_ERR(dev->battery);
> -		hid_warn(dev, "can't register power supply: %d\n", error);
> -		goto err_free_name;
> +		hid_warn(dev, "can't register power supply: %ld\n",
> +			 PTR_ERR(dev->battery));
> +		return PTR_ERR(dev->battery);
>  	}
>  
>  	power_supply_powers(dev->battery, &dev->dev);
>  	return 0;
> -
> -err_free_name:
> -	kfree(psy_desc->name);
> -err_free_mem:
> -	kfree(psy_desc);
> -	dev->battery = NULL;
> -	return error;

As mentioned in my other reply (and this is more of an open question):
what if there is a failure in devm_power_supply_register? Everything
will be allocated and kept until the end of life of the HID device, but
we'll try to recreate the battery for every matching field in the HID
device, meaning we are waiting a lot of space for nothing.

The previous appraoch was cleaning things up, so we were trying a lot,
but at least we were not keeping the memory allocated.

I think we should keep the error path for devm_power_supply_register()
and dealloc (with devm_kfree) the few memories we've done and also clear
dev->battery.  This way we keep the current path and can make use of
devm and get the benefits of removing the hidinput_cleanup_battery()
function.

Cheers,
Benjamin

> -}
> -
> -static void hidinput_cleanup_battery(struct hid_device *dev)
> -{
> -	const struct power_supply_desc *psy_desc;
> -
> -	if (!dev->battery)
> -		return;
> -
> -	psy_desc = dev->battery->desc;
> -	power_supply_unregister(dev->battery);
> -	kfree(psy_desc->name);
> -	kfree(psy_desc);
> -	dev->battery = NULL;
>  }
>  
>  static bool hidinput_update_battery_charge_status(struct hid_device *dev,
> @@ -660,10 +637,6 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
>  	return 0;
>  }
>  
> -static void hidinput_cleanup_battery(struct hid_device *dev)
> -{
> -}
> -
>  static void hidinput_update_battery(struct hid_device *dev, unsigned int usage,
>  				    int value)
>  {
> @@ -2379,8 +2352,6 @@ void hidinput_disconnect(struct hid_device *hid)
>  {
>  	struct hid_input *hidinput, *next;
>  
> -	hidinput_cleanup_battery(hid);
> -
>  	list_for_each_entry_safe(hidinput, next, &hid->inputs, list) {
>  		list_del(&hidinput->list);
>  		if (hidinput->registered)
> -- 
> 2.51.1
> 

^ permalink raw reply

* Re: [PATCH v5 2/2] HID: input: Add support for multiple batteries per device
From: Benjamin Tissoires @ 2025-12-09 10:25 UTC (permalink / raw)
  To: Lucas Zampieri, Lucas Zampieri
  Cc: linux-input, linux-kernel, Jiri Kosina, Sebastian Reichel,
	Bastien Nocera, linux-pm
In-Reply-To: <20251121131556.601130-3-lzampier@redhat.com>

Hi Lucas,

On Nov 21 2025, Lucas Zampieri wrote:
> Introduce struct hid_battery to encapsulate individual battery state and
> enable HID devices to register multiple batteries, each identified by
> its report ID.

That very much looks like we need two patches here as well:
- first introduces the struct hid_battery and converts everybody to use
	it
- second, introduce multiple batteries

This allows to keep the multiple batteries changes separated so we can
validate the hid-apple.c changes by itself for instance.

Looking further at the patch it should be a matter of splitting the
hidinput_setup_battery into a separate patch and in that second patch
add the list support in the struct hid_battery.

> 
> This struct hid_battery replaces the legacy dev->battery_* fields with
> a batteries list.
> Batteries are named using their report ID with the pattern
> hid-{uniq}-battery-{report_id}. External drivers hid-apple and
> hid-magicmouse are updated to use the new battery API via the
> hid_get_first_battery() helper, and hid-input-test is updated for the
> new battery structure.
> 
> This enables proper battery reporting for devices with multiple
> batteries such as split keyboards, gaming headsets with charging docks,
> and wireless earbuds with per-earbud batteries.
> 
> Suggested-by: Benjamin Tissoires <bentiss@kernel.org>
> Signed-off-by: Lucas Zampieri <lzampier@redhat.com>
> ---
>  drivers/hid/hid-apple.c      |  10 ++-
>  drivers/hid/hid-core.c       |   4 +
>  drivers/hid/hid-input-test.c |  39 +++++----
>  drivers/hid/hid-input.c      | 163 +++++++++++++++++++++--------------
>  drivers/hid/hid-magicmouse.c |  10 ++-
>  include/linux/hid.h          |  54 +++++++++---
>  6 files changed, 178 insertions(+), 102 deletions(-)
> 
> diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
> index 61404d7a43ee..fb09b616f8cc 100644
> --- a/drivers/hid/hid-apple.c
> +++ b/drivers/hid/hid-apple.c
> @@ -618,17 +618,19 @@ static int apple_fetch_battery(struct hid_device *hdev)
>  	struct apple_sc *asc = hid_get_drvdata(hdev);
>  	struct hid_report_enum *report_enum;
>  	struct hid_report *report;
> +	struct hid_battery *bat;
> 
> -	if (!(asc->quirks & APPLE_RDESC_BATTERY) || !hdev->battery)
> +	bat = hid_get_first_battery(hdev);

Maybe hid_get_battery(hdev) and add then when multiple batteries are
supported either change the API to hid_get_battery(hdev, 0) either
introduce a new function (you already has hid_find_battery).

> +	if (!(asc->quirks & APPLE_RDESC_BATTERY) || !bat)
>  		return -1;
> 
> -	report_enum = &hdev->report_enum[hdev->battery_report_type];
> -	report = report_enum->report_id_hash[hdev->battery_report_id];
> +	report_enum = &hdev->report_enum[bat->report_type];
> +	report = report_enum->report_id_hash[bat->report_id];
> 
>  	if (!report || report->maxfield < 1)
>  		return -1;
> 
> -	if (hdev->battery_capacity == hdev->battery_max)
> +	if (bat->capacity == bat->max)
>  		return -1;
> 
>  	hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index a5b3a8ca2fcb..76d628547e9a 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -2990,6 +2990,10 @@ struct hid_device *hid_allocate_device(void)
>  	mutex_init(&hdev->ll_open_lock);
>  	kref_init(&hdev->ref);
> 
> +#ifdef CONFIG_HID_BATTERY_STRENGTH
> +	INIT_LIST_HEAD(&hdev->batteries);
> +#endif
> +
>  	ret = hid_bpf_device_init(hdev);
>  	if (ret)
>  		goto out_err;
> diff --git a/drivers/hid/hid-input-test.c b/drivers/hid/hid-input-test.c
> index 6f5c71660d82..c92008dafddf 100644
> --- a/drivers/hid/hid-input-test.c
> +++ b/drivers/hid/hid-input-test.c
> @@ -9,54 +9,59 @@
> 
>  static void hid_test_input_update_battery_charge_status(struct kunit *test)
>  {
> -	struct hid_device *dev;
> +	struct hid_battery *bat;
>  	bool handled;
> 
> -	dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL);
> -	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
> +	bat = kunit_kzalloc(test, sizeof(*bat), GFP_KERNEL);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bat);
> 
> -	handled = hidinput_update_battery_charge_status(dev, HID_DG_HEIGHT, 0);
> +	handled = hidinput_update_battery_charge_status(bat, HID_DG_HEIGHT, 0);
>  	KUNIT_EXPECT_FALSE(test, handled);
> -	KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_UNKNOWN);
> +	KUNIT_EXPECT_EQ(test, bat->charge_status, POWER_SUPPLY_STATUS_UNKNOWN);
> 
> -	handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 0);
> +	handled = hidinput_update_battery_charge_status(bat, HID_BAT_CHARGING, 0);
>  	KUNIT_EXPECT_TRUE(test, handled);
> -	KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_DISCHARGING);
> +	KUNIT_EXPECT_EQ(test, bat->charge_status, POWER_SUPPLY_STATUS_DISCHARGING);
> 
> -	handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 1);
> +	handled = hidinput_update_battery_charge_status(bat, HID_BAT_CHARGING, 1);
>  	KUNIT_EXPECT_TRUE(test, handled);
> -	KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_CHARGING);
> +	KUNIT_EXPECT_EQ(test, bat->charge_status, POWER_SUPPLY_STATUS_CHARGING);
>  }
> 
>  static void hid_test_input_get_battery_property(struct kunit *test)
>  {
>  	struct power_supply *psy;
> +	struct hid_battery *bat;
>  	struct hid_device *dev;
>  	union power_supply_propval val;
>  	int ret;
> 
>  	dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL);
>  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
> -	dev->battery_avoid_query = true;
> +
> +	bat = kunit_kzalloc(test, sizeof(*bat), GFP_KERNEL);
> +	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, bat);
> +	bat->dev = dev;
> +	bat->avoid_query = true;
> 
>  	psy = kunit_kzalloc(test, sizeof(*psy), GFP_KERNEL);
>  	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, psy);
> -	psy->drv_data = dev;
> +	psy->drv_data = bat;
> 
> -	dev->battery_status = HID_BATTERY_UNKNOWN;
> -	dev->battery_charge_status = POWER_SUPPLY_STATUS_CHARGING;
> +	bat->status = HID_BATTERY_UNKNOWN;
> +	bat->charge_status = POWER_SUPPLY_STATUS_CHARGING;
>  	ret = hidinput_get_battery_property(psy, POWER_SUPPLY_PROP_STATUS, &val);
>  	KUNIT_EXPECT_EQ(test, ret, 0);
>  	KUNIT_EXPECT_EQ(test, val.intval, POWER_SUPPLY_STATUS_UNKNOWN);
> 
> -	dev->battery_status = HID_BATTERY_REPORTED;
> -	dev->battery_charge_status = POWER_SUPPLY_STATUS_CHARGING;
> +	bat->status = HID_BATTERY_REPORTED;
> +	bat->charge_status = POWER_SUPPLY_STATUS_CHARGING;
>  	ret = hidinput_get_battery_property(psy, POWER_SUPPLY_PROP_STATUS, &val);
>  	KUNIT_EXPECT_EQ(test, ret, 0);
>  	KUNIT_EXPECT_EQ(test, val.intval, POWER_SUPPLY_STATUS_CHARGING);
> 
> -	dev->battery_status = HID_BATTERY_REPORTED;
> -	dev->battery_charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
> +	bat->status = HID_BATTERY_REPORTED;
> +	bat->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
>  	ret = hidinput_get_battery_property(psy, POWER_SUPPLY_PROP_STATUS, &val);
>  	KUNIT_EXPECT_EQ(test, ret, 0);
>  	KUNIT_EXPECT_EQ(test, val.intval, POWER_SUPPLY_STATUS_DISCHARGING);
> diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
> index 5f313c3c35e2..9eeaba0229d5 100644
> --- a/drivers/hid/hid-input.c
> +++ b/drivers/hid/hid-input.c
> @@ -418,18 +418,18 @@ static unsigned find_battery_quirk(struct hid_device *hdev)
>  	return quirks;
>  }
> 
> -static int hidinput_scale_battery_capacity(struct hid_device *dev,
> +static int hidinput_scale_battery_capacity(struct hid_battery *bat,
>  					   int value)
>  {
> -	if (dev->battery_min < dev->battery_max &&
> -	    value >= dev->battery_min && value <= dev->battery_max)
> -		value = ((value - dev->battery_min) * 100) /
> -			(dev->battery_max - dev->battery_min);
> +	if (bat->min < bat->max &&
> +	    value >= bat->min && value <= bat->max)
> +		value = ((value - bat->min) * 100) /
> +			(bat->max - bat->min);
> 
>  	return value;
>  }
> 
> -static int hidinput_query_battery_capacity(struct hid_device *dev)
> +static int hidinput_query_battery_capacity(struct hid_battery *bat)
>  {
>  	u8 *buf;
>  	int ret;
> @@ -438,14 +438,14 @@ static int hidinput_query_battery_capacity(struct hid_device *dev)
>  	if (!buf)
>  		return -ENOMEM;
> 
> -	ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 4,
> -				 dev->battery_report_type, HID_REQ_GET_REPORT);
> +	ret = hid_hw_raw_request(bat->dev, bat->report_id, buf, 4,
> +				 bat->report_type, HID_REQ_GET_REPORT);
>  	if (ret < 2) {
>  		kfree(buf);
>  		return -ENODATA;
>  	}
> 
> -	ret = hidinput_scale_battery_capacity(dev, buf[1]);
> +	ret = hidinput_scale_battery_capacity(bat, buf[1]);
>  	kfree(buf);
>  	return ret;
>  }
> @@ -454,7 +454,8 @@ static int hidinput_get_battery_property(struct power_supply *psy,
>  					 enum power_supply_property prop,
>  					 union power_supply_propval *val)
>  {
> -	struct hid_device *dev = power_supply_get_drvdata(psy);
> +	struct hid_battery *bat = power_supply_get_drvdata(psy);
> +	struct hid_device *dev = bat->dev;
>  	int value;
>  	int ret = 0;
> 
> @@ -465,13 +466,13 @@ static int hidinput_get_battery_property(struct power_supply *psy,
>  		break;
> 
>  	case POWER_SUPPLY_PROP_CAPACITY:
> -		if (dev->battery_status != HID_BATTERY_REPORTED &&
> -		    !dev->battery_avoid_query) {
> -			value = hidinput_query_battery_capacity(dev);
> +		if (bat->status != HID_BATTERY_REPORTED &&
> +		    !bat->avoid_query) {
> +			value = hidinput_query_battery_capacity(bat);
>  			if (value < 0)
>  				return value;
>  		} else  {
> -			value = dev->battery_capacity;
> +			value = bat->capacity;
>  		}
> 
>  		val->intval = value;
> @@ -482,20 +483,20 @@ static int hidinput_get_battery_property(struct power_supply *psy,
>  		break;
> 
>  	case POWER_SUPPLY_PROP_STATUS:
> -		if (dev->battery_status != HID_BATTERY_REPORTED &&
> -		    !dev->battery_avoid_query) {
> -			value = hidinput_query_battery_capacity(dev);
> +		if (bat->status != HID_BATTERY_REPORTED &&
> +		    !bat->avoid_query) {
> +			value = hidinput_query_battery_capacity(bat);
>  			if (value < 0)
>  				return value;
> 
> -			dev->battery_capacity = value;
> -			dev->battery_status = HID_BATTERY_QUERIED;
> +			bat->capacity = value;
> +			bat->status = HID_BATTERY_QUERIED;
>  		}
> 
> -		if (dev->battery_status == HID_BATTERY_UNKNOWN)
> +		if (bat->status == HID_BATTERY_UNKNOWN)
>  			val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
>  		else
> -			val->intval = dev->battery_charge_status;
> +			val->intval = bat->charge_status;
>  		break;
> 
>  	case POWER_SUPPLY_PROP_SCOPE:
> @@ -510,33 +511,52 @@ static int hidinput_get_battery_property(struct power_supply *psy,
>  	return ret;
>  }
> 
> +static struct hid_battery *hidinput_find_battery(struct hid_device *dev,
> +						 int report_id)
> +{
> +	struct hid_battery *bat;
> +
> +	list_for_each_entry(bat, &dev->batteries, list) {
> +		if (bat->report_id == report_id)
> +			return bat;
> +	}
> +	return NULL;
> +}
> +
>  static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
>  				  struct hid_field *field, bool is_percentage)
>  {
> +	struct hid_battery *bat;
>  	struct power_supply_desc *psy_desc;
> -	struct power_supply_config psy_cfg = { .drv_data = dev, };
> +	struct power_supply_config psy_cfg = { 0 };
>  	unsigned quirks;
>  	s32 min, max;
> -	int error;
> 
> -	if (dev->battery)
> -		return 0;	/* already initialized? */
> +	if (hidinput_find_battery(dev, field->report->id))
> +		return 0;
> 
>  	quirks = find_battery_quirk(dev);
> 
> -	hid_dbg(dev, "device %x:%x:%x %d quirks %d\n",
> -		dev->bus, dev->vendor, dev->product, dev->version, quirks);
> +	hid_dbg(dev, "device %x:%x:%x %d quirks %d report_id %d\n",
> +		dev->bus, dev->vendor, dev->product, dev->version, quirks,
> +		field->report->id);
> 
>  	if (quirks & HID_BATTERY_QUIRK_IGNORE)
>  		return 0;
> 
> +	bat = devm_kzalloc(&dev->dev, sizeof(*bat), GFP_KERNEL);
> +	if (!bat)
> +		return -ENOMEM;

Looking at the current code path (pre 1/2 in this series), we never
check for the return value of hidinput_setup_battery(), so in case
something goes wrong, we are just hammering even more for every battery
field, which is not ideal. I don't think the issue is in this patch, but
I just happened to realize it as I'm reviewing it now.

My chain of thoughts was whether we need a special devm_group for this
so we can partially clean this up in case of failure but I honestly
don't know if this is the good approach either.

I guess the -ENOMEM is not of an issue (because everything will fall
apart as well), but what if the power_supply_register fails?

Cheers,
Benjamin

> +
>  	psy_desc = devm_kzalloc(&dev->dev, sizeof(*psy_desc), GFP_KERNEL);
>  	if (!psy_desc)
>  		return -ENOMEM;
> 
> -	psy_desc->name = devm_kasprintf(&dev->dev, GFP_KERNEL, "hid-%s-battery",
> +	psy_desc->name = devm_kasprintf(&dev->dev, GFP_KERNEL,
> +					"hid-%s-battery-%d",
>  					strlen(dev->uniq) ?
> -						dev->uniq : dev_name(&dev->dev));
> +						dev->uniq : dev_name(&dev->dev),
> +					field->report->id);
>  	if (!psy_desc->name)
>  		return -ENOMEM;
> 
> @@ -557,77 +577,80 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
>  	if (quirks & HID_BATTERY_QUIRK_FEATURE)
>  		report_type = HID_FEATURE_REPORT;
> 
> -	dev->battery_min = min;
> -	dev->battery_max = max;
> -	dev->battery_report_type = report_type;
> -	dev->battery_report_id = field->report->id;
> -	dev->battery_charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
> +	bat->dev = dev;
> +	bat->min = min;
> +	bat->max = max;
> +	bat->report_type = report_type;
> +	bat->report_id = field->report->id;
> +	bat->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
> +	bat->status = HID_BATTERY_UNKNOWN;
> 
>  	/*
>  	 * Stylus is normally not connected to the device and thus we
>  	 * can't query the device and get meaningful battery strength.
>  	 * We have to wait for the device to report it on its own.
>  	 */
> -	dev->battery_avoid_query = report_type == HID_INPUT_REPORT &&
> -				   field->physical == HID_DG_STYLUS;
> +	bat->avoid_query = report_type == HID_INPUT_REPORT &&
> +			   field->physical == HID_DG_STYLUS;
> 
>  	if (quirks & HID_BATTERY_QUIRK_AVOID_QUERY)
> -		dev->battery_avoid_query = true;
> +		bat->avoid_query = true;
> 
> -	dev->battery = devm_power_supply_register(&dev->dev, psy_desc, &psy_cfg);
> -	if (IS_ERR(dev->battery)) {
> +	psy_cfg.drv_data = bat;
> +	bat->ps = devm_power_supply_register(&dev->dev, psy_desc, &psy_cfg);
> +	if (IS_ERR(bat->ps)) {
>  		hid_warn(dev, "can't register power supply: %ld\n",
> -			 PTR_ERR(dev->battery));
> -		return PTR_ERR(dev->battery);
> +			 PTR_ERR(bat->ps));
> +		return PTR_ERR(bat->ps);
>  	}
> 
> -	power_supply_powers(dev->battery, &dev->dev);
> +	power_supply_powers(bat->ps, &dev->dev);
> +
> +	list_add_tail(&bat->list, &dev->batteries);
> +
>  	return 0;
>  }
> 
> -static bool hidinput_update_battery_charge_status(struct hid_device *dev,
> +static bool hidinput_update_battery_charge_status(struct hid_battery *bat,
>  						  unsigned int usage, int value)
>  {
>  	switch (usage) {
>  	case HID_BAT_CHARGING:
> -		dev->battery_charge_status = value ?
> -					     POWER_SUPPLY_STATUS_CHARGING :
> -					     POWER_SUPPLY_STATUS_DISCHARGING;
> +		bat->charge_status = value ?
> +				     POWER_SUPPLY_STATUS_CHARGING :
> +				     POWER_SUPPLY_STATUS_DISCHARGING;
>  		return true;
>  	}
> 
>  	return false;
>  }
> 
> -static void hidinput_update_battery(struct hid_device *dev, unsigned int usage,
> -				    int value)
> +static void hidinput_update_battery(struct hid_battery *bat,
> +				    unsigned int usage, int value)
>  {
>  	int capacity;
> 
> -	if (!dev->battery)
> -		return;
> -
> -	if (hidinput_update_battery_charge_status(dev, usage, value)) {
> -		power_supply_changed(dev->battery);
> +	if (hidinput_update_battery_charge_status(bat, usage, value)) {
> +		power_supply_changed(bat->ps);
>  		return;
>  	}
> 
>  	if ((usage & HID_USAGE_PAGE) == HID_UP_DIGITIZER && value == 0)
>  		return;
> 
> -	if (value < dev->battery_min || value > dev->battery_max)
> +	if (value < bat->min || value > bat->max)
>  		return;
> 
> -	capacity = hidinput_scale_battery_capacity(dev, value);
> +	capacity = hidinput_scale_battery_capacity(bat, value);
> 
> -	if (dev->battery_status != HID_BATTERY_REPORTED ||
> -	    capacity != dev->battery_capacity ||
> -	    ktime_after(ktime_get_coarse(), dev->battery_ratelimit_time)) {
> -		dev->battery_capacity = capacity;
> -		dev->battery_status = HID_BATTERY_REPORTED;
> -		dev->battery_ratelimit_time =
> +	if (bat->status != HID_BATTERY_REPORTED ||
> +	    capacity != bat->capacity ||
> +	    ktime_after(ktime_get_coarse(), bat->ratelimit_time)) {
> +		bat->capacity = capacity;
> +		bat->status = HID_BATTERY_REPORTED;
> +		bat->ratelimit_time =
>  			ktime_add_ms(ktime_get_coarse(), 30 * 1000);
> -		power_supply_changed(dev->battery);
> +		power_supply_changed(bat->ps);
>  	}
>  }
>  #else  /* !CONFIG_HID_BATTERY_STRENGTH */
> @@ -637,8 +660,14 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
>  	return 0;
>  }
> 
> -static void hidinput_update_battery(struct hid_device *dev, unsigned int usage,
> -				    int value)
> +static struct hid_battery *hidinput_find_battery(struct hid_device *dev,
> +						 int report_id)
> +{
> +	return NULL;
> +}
> +
> +static void hidinput_update_battery(struct hid_battery *bat,
> +				    unsigned int usage, int value)
>  {
>  }
>  #endif	/* CONFIG_HID_BATTERY_STRENGTH */
> @@ -1506,7 +1535,11 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
>  		return;
> 
>  	if (usage->type == EV_PWR) {
> -		hidinput_update_battery(hid, usage->hid, value);
> +		struct hid_battery *bat = hidinput_find_battery(hid,
> +								 report->id);
> +
> +		if (bat)
> +			hidinput_update_battery(bat, usage->hid, value);
>  		return;
>  	}
> 
> diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
> index 7d4a25c6de0e..b495f7a4bc6c 100644
> --- a/drivers/hid/hid-magicmouse.c
> +++ b/drivers/hid/hid-magicmouse.c
> @@ -812,19 +812,21 @@ static int magicmouse_fetch_battery(struct hid_device *hdev)
>  #ifdef CONFIG_HID_BATTERY_STRENGTH
>  	struct hid_report_enum *report_enum;
>  	struct hid_report *report;
> +	struct hid_battery *bat;
> 
> -	if (!hdev->battery ||
> +	bat = hid_get_first_battery(hdev);
> +	if (!bat ||
>  	    (!is_usb_magicmouse2(hdev->vendor, hdev->product) &&
>  	     !is_usb_magictrackpad2(hdev->vendor, hdev->product)))
>  		return -1;
> 
> -	report_enum = &hdev->report_enum[hdev->battery_report_type];
> -	report = report_enum->report_id_hash[hdev->battery_report_id];
> +	report_enum = &hdev->report_enum[bat->report_type];
> +	report = report_enum->report_id_hash[bat->report_id];
> 
>  	if (!report || report->maxfield < 1)
>  		return -1;
> 
> -	if (hdev->battery_capacity == hdev->battery_max)
> +	if (bat->capacity == bat->max)
>  		return -1;
> 
>  	hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
> diff --git a/include/linux/hid.h b/include/linux/hid.h
> index a4ddb94e3ee5..3e33ef74c3c1 100644
> --- a/include/linux/hid.h
> +++ b/include/linux/hid.h
> @@ -634,6 +634,36 @@ enum hid_battery_status {
>  	HID_BATTERY_REPORTED,		/* Device sent unsolicited battery strength report */
>  };
> 
> +/**
> + * struct hid_battery - represents a single battery power supply
> + * @dev: pointer to the parent hid_device
> + * @ps: the power supply instance
> + * @min: minimum battery value from HID descriptor
> + * @max: maximum battery value from HID descriptor
> + * @report_type: HID report type (input/feature)
> + * @report_id: HID report ID for this battery
> + * @charge_status: current charging status
> + * @status: battery reporting status
> + * @capacity: current battery capacity (0-100)
> + * @avoid_query: if true, avoid querying battery (e.g., for stylus)
> + * @ratelimit_time: rate limiting for battery reports
> + * @list: list node for linking into hid_device's battery list
> + */
> +struct hid_battery {
> +	struct hid_device *dev;
> +	struct power_supply *ps;
> +	__s32 min;
> +	__s32 max;
> +	__s32 report_type;
> +	__s32 report_id;
> +	__s32 charge_status;
> +	enum hid_battery_status status;
> +	__s32 capacity;
> +	bool avoid_query;
> +	ktime_t ratelimit_time;
> +	struct list_head list;
> +};
> +
>  struct hid_driver;
>  struct hid_ll_driver;
> 
> @@ -670,19 +700,10 @@ struct hid_device {
>  #ifdef CONFIG_HID_BATTERY_STRENGTH
>  	/*
>  	 * Power supply information for HID devices which report
> -	 * battery strength. power_supply was successfully registered if
> -	 * battery is non-NULL.
> +	 * battery strength. Each battery is tracked separately in the
> +	 * batteries list.
>  	 */
> -	struct power_supply *battery;
> -	__s32 battery_capacity;
> -	__s32 battery_min;
> -	__s32 battery_max;
> -	__s32 battery_report_type;
> -	__s32 battery_report_id;
> -	__s32 battery_charge_status;
> -	enum hid_battery_status battery_status;
> -	bool battery_avoid_query;
> -	ktime_t battery_ratelimit_time;
> +	struct list_head batteries;
>  #endif
> 
>  	unsigned long status;						/* see STAT flags above */
> @@ -743,6 +764,15 @@ static inline void hid_set_drvdata(struct hid_device *hdev, void *data)
>  	dev_set_drvdata(&hdev->dev, data);
>  }
> 
> +#ifdef CONFIG_HID_BATTERY_STRENGTH
> +static inline struct hid_battery *hid_get_first_battery(struct hid_device *hdev)
> +{
> +	if (list_empty(&hdev->batteries))
> +		return NULL;
> +	return list_first_entry(&hdev->batteries, struct hid_battery, list);
> +}
> +#endif
> +
>  #define HID_GLOBAL_STACK_SIZE 4
>  #define HID_COLLECTION_STACK_SIZE 4
> 
> --
> 2.51.1
> 

^ permalink raw reply

* Re: [PATCH v10 00/11] HID: asus: Fix ASUS ROG Laptop's Keyboard backlight handling
From: Antheas Kapenekakis @ 2025-12-09  9:49 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: Kelsios, platform-driver-x86, linux-input, LKML, Jiri Kosina,
	Benjamin Tissoires, Corentin Chary, Luke D . Jones, Hans de Goede,
	Denis Benato
In-Reply-To: <1adcffd1-2381-654d-b9b5-966306758509@linux.intel.com>

On Tue, 9 Dec 2025 at 10:17, Ilpo Järvinen
<ilpo.jarvinen@linux.intel.com> wrote:
>
> On Sat, 6 Dec 2025, Antheas Kapenekakis wrote:
>
> > On Sat, 6 Dec 2025 at 00:03, Antheas Kapenekakis <lkml@antheas.dev> wrote:
> > >
> > > On Fri, 5 Dec 2025 at 23:13, Kelsios <K3lsios@proton.me> wrote:
> > > >
> > > > Hello,
> > > >
> > > > I would like to report a regression affecting keyboard backlight brightness control on my ASUS ROG Zephyrus G16 (model GU605CW).
> > > >
> > > > Using kernel 6.17.9-arch1-1.1-g14 with the latest HID ASUS patchset v10, keyboard *color* control works correctly, but *brightness* control no longer responds at all. The issue is reproducible on every boot. This problem is not present when using patchset v8, where both color and brightness work as expected.
> > > >
> > > > Important detail: the issue occurs even **without** asusctl installed, so it must be within the kernel HID/WMI handling and is unrelated to userspace tools.
> > > >
> > > > Output of dmesg is available here [1], please let me know if any additional information is required.
> > > >
> > > > Thank you for your time and work on supporting these ASUS laptops.
> > > >
> > > > Best regards,
> > > > Kelsios
> > > >
> > > > [1] https://pastebin.com/ZFC13Scf
> > >
> > > [ 1.035986] asus 0003:0B05:19B6.0001: Asus failed to receive handshake ack: -32
> > >
> > > Oh yeah, asus_kbd_init no longer works with spurious inits so it broke
> > > devices marked with QUIRK_ROG_NKEY_LEGACY
> > >
> > > There are three ways to approach this. One is to ignore the error...
> > > second is to drop the quirk... third is to check for the usages for ID1, ID2...
> > >
> > > I would tend towards dropping the ID2 init and ignoring the error for
> > > ID1... Unless an EPIPE would cause the device to close
> >
> > Benjamin correctly caught the deviation
>
> BTW, we want to record this knowledge also into the changelog so that the
> next person who'd want to make the check stricter does not need to guess
> whether it was based on a real observed problem or mere guessing there
> could be a problem.

If we keep the spurious inits, the stricter check will catch them and
throw errors. This is problematic.

Kelsios, you have a device that allegedly would not work without those
inits. Perhaps you could try removing the legacy quirk from your
device and see if everything is ok?

If it is, then we have a tested device and a case for removing the
legacy quirk altogether

Antheas

> --
>  i.
>
>


^ permalink raw reply

* Re: [PATCH v10 00/11] HID: asus: Fix ASUS ROG Laptop's Keyboard backlight handling
From: Ilpo Järvinen @ 2025-12-09  9:17 UTC (permalink / raw)
  To: Antheas Kapenekakis
  Cc: Kelsios, platform-driver-x86, linux-input, LKML, Jiri Kosina,
	Benjamin Tissoires, Corentin Chary, Luke D . Jones, Hans de Goede,
	Denis Benato
In-Reply-To: <CAGwozwEud1-6GT=JHoG64f3NUXJ1-wFmWpotNK4s6b=m+1styw@mail.gmail.com>

On Sat, 6 Dec 2025, Antheas Kapenekakis wrote:

> On Sat, 6 Dec 2025 at 00:03, Antheas Kapenekakis <lkml@antheas.dev> wrote:
> >
> > On Fri, 5 Dec 2025 at 23:13, Kelsios <K3lsios@proton.me> wrote:
> > >
> > > Hello,
> > >
> > > I would like to report a regression affecting keyboard backlight brightness control on my ASUS ROG Zephyrus G16 (model GU605CW).
> > >
> > > Using kernel 6.17.9-arch1-1.1-g14 with the latest HID ASUS patchset v10, keyboard *color* control works correctly, but *brightness* control no longer responds at all. The issue is reproducible on every boot. This problem is not present when using patchset v8, where both color and brightness work as expected.
> > >
> > > Important detail: the issue occurs even **without** asusctl installed, so it must be within the kernel HID/WMI handling and is unrelated to userspace tools.
> > >
> > > Output of dmesg is available here [1], please let me know if any additional information is required.
> > >
> > > Thank you for your time and work on supporting these ASUS laptops.
> > >
> > > Best regards,
> > > Kelsios
> > >
> > > [1] https://pastebin.com/ZFC13Scf
> >
> > [ 1.035986] asus 0003:0B05:19B6.0001: Asus failed to receive handshake ack: -32
> >
> > Oh yeah, asus_kbd_init no longer works with spurious inits so it broke
> > devices marked with QUIRK_ROG_NKEY_LEGACY
> >
> > There are three ways to approach this. One is to ignore the error...
> > second is to drop the quirk... third is to check for the usages for ID1, ID2...
> >
> > I would tend towards dropping the ID2 init and ignoring the error for
> > ID1... Unless an EPIPE would cause the device to close
> 
> Benjamin correctly caught the deviation

BTW, we want to record this knowledge also into the changelog so that the 
next person who'd want to make the check stricter does not need to guess 
whether it was based on a real observed problem or mere guessing there 
could be a problem.

-- 
 i.


^ permalink raw reply

* Re: [PATCH v10 05/11] HID: asus: move vendor initialization to probe
From: Ilpo Järvinen @ 2025-12-09  9:14 UTC (permalink / raw)
  To: Antheas Kapenekakis
  Cc: platform-driver-x86, linux-input, LKML, Jiri Kosina,
	Benjamin Tissoires, Corentin Chary, Luke D . Jones, Hans de Goede,
	Denis Benato
In-Reply-To: <CAGwozwEN-Rzjk2nZ9mbROE2vbiQ4LUiTn5OB6mKSfArRwDgL7Q@mail.gmail.com>

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

On Tue, 9 Dec 2025, Antheas Kapenekakis wrote:
> On Mon, 8 Dec 2025 at 18:11, Ilpo Järvinen
> <ilpo.jarvinen@linux.intel.com> wrote:
> >
> > On Sat, 22 Nov 2025, Antheas Kapenekakis wrote:
> >
> > > ROG NKEY devices have multiple HID endpoints, around 3-4. One of those
> > > endpoints has a usage page of 0xff31, and is the one that emits keyboard
> > > shortcuts and controls RGB/backlight. Currently, this driver places
> > > the usage page check under asus_input_mapping and then inits backlight
> > > in asus_input_configured which is unnecessarily complicated and prevents
> > > probe from performing customizations on the vendor endpoint.
> > >
> > > Simplify the logic by introducing an is_vendor variable into probe that
> > > checks for usage page 0xff31. Then, use this variable to move backlight
> > > initialization into probe instead of asus_input_configured, and remove
> > > the backlight check from asus_input_mapping.
> >
> > In the changelogs, please add () after any name that refers to a C
> > function so the reader immediately knows you're talking about a function.
> 
> Sure. What should be my timeline for fixing this?
> 
> I assume we missed the merge window. If not, I can tweak the series
> and send it later today

This is 6.20 material so no big hurry.

--
 i.

> > > Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
> > > ---
> > >  drivers/hid/hid-asus.c | 35 ++++++++++++++++++-----------------
> > >  1 file changed, 18 insertions(+), 17 deletions(-)
> > >
> > > diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
> > > index 2a412e10f916..faac971794c0 100644
> > > --- a/drivers/hid/hid-asus.c
> > > +++ b/drivers/hid/hid-asus.c
> > > @@ -48,6 +48,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
> > >  #define T100CHI_MOUSE_REPORT_ID 0x06
> > >  #define FEATURE_REPORT_ID 0x0d
> > >  #define INPUT_REPORT_ID 0x5d
> > > +#define HID_USAGE_PAGE_VENDOR 0xff310000
> > >  #define FEATURE_KBD_REPORT_ID 0x5a
> > >  #define FEATURE_KBD_REPORT_SIZE 64
> > >  #define FEATURE_KBD_LED_REPORT_ID1 0x5d
> > > @@ -127,7 +128,6 @@ struct asus_drvdata {
> > >       struct input_dev *tp_kbd_input;
> > >       struct asus_kbd_leds *kbd_backlight;
> > >       const struct asus_touchpad_info *tp;
> > > -     bool enable_backlight;
> > >       struct power_supply *battery;
> > >       struct power_supply_desc battery_desc;
> > >       int battery_capacity;
> > > @@ -318,7 +318,7 @@ static int asus_e1239t_event(struct asus_drvdata *drvdat, u8 *data, int size)
> > >  static int asus_event(struct hid_device *hdev, struct hid_field *field,
> > >                     struct hid_usage *usage, __s32 value)
> > >  {
> > > -     if ((usage->hid & HID_USAGE_PAGE) == 0xff310000 &&
> > > +     if ((usage->hid & HID_USAGE_PAGE) == HID_USAGE_PAGE_VENDOR &&
> > >           (usage->hid & HID_USAGE) != 0x00 &&
> > >           (usage->hid & HID_USAGE) != 0xff && !usage->type) {
> > >               hid_warn(hdev, "Unmapped Asus vendor usagepage code 0x%02x\n",
> > > @@ -941,11 +941,6 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
> > >
> > >       drvdata->input = input;
> > >
> > > -     if (drvdata->enable_backlight &&
> > > -         !asus_kbd_wmi_led_control_present(hdev) &&
> > > -         asus_kbd_register_leds(hdev))
> > > -             hid_warn(hdev, "Failed to initialize backlight.\n");
> > > -
> > >       return 0;
> > >  }
> > >
> > > @@ -1018,15 +1013,6 @@ static int asus_input_mapping(struct hid_device *hdev,
> > >                       return -1;
> > >               }
> > >
> > > -             /*
> > > -              * Check and enable backlight only on devices with UsagePage ==
> > > -              * 0xff31 to avoid initializing the keyboard firmware multiple
> > > -              * times on devices with multiple HID descriptors but same
> > > -              * PID/VID.
> > > -              */
> > > -             if (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT)
> > > -                     drvdata->enable_backlight = true;
> > > -
> > >               set_bit(EV_REP, hi->input->evbit);
> > >               return 1;
> > >       }
> > > @@ -1143,8 +1129,11 @@ static int __maybe_unused asus_reset_resume(struct hid_device *hdev)
> > >
> > >  static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
> > >  {
> > > -     int ret;
> > > +     struct hid_report_enum *rep_enum;
> > >       struct asus_drvdata *drvdata;
> > > +     struct hid_report *rep;
> > > +     bool is_vendor = false;
> > > +     int ret;
> > >
> > >       drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
> > >       if (drvdata == NULL) {
> > > @@ -1228,12 +1217,24 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
> > >               return ret;
> > >       }
> > >
> > > +     /* Check for vendor for RGB init and handle generic devices properly. */
> > > +     rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
> > > +     list_for_each_entry(rep, &rep_enum->report_list, list) {
> > > +             if ((rep->application & HID_USAGE_PAGE) == HID_USAGE_PAGE_VENDOR)
> > > +                     is_vendor = true;
> > > +     }
> > > +
> > >       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> > >       if (ret) {
> > >               hid_err(hdev, "Asus hw start failed: %d\n", ret);
> > >               return ret;
> > >       }
> > >
> > > +     if (is_vendor && (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT) &&
> > > +         !asus_kbd_wmi_led_control_present(hdev) &&
> > > +         asus_kbd_register_leds(hdev))
> > > +             hid_warn(hdev, "Failed to initialize backlight.\n");
> > > +
> > >       /*
> > >        * Check that input registration succeeded. Checking that
> > >        * HID_CLAIMED_INPUT is set prevents a UAF when all input devices
> > >
> >
> > --
> >  i.
> >
> >
> 

^ permalink raw reply

* Re: [PATCH v10 05/11] HID: asus: move vendor initialization to probe
From: Antheas Kapenekakis @ 2025-12-09  9:12 UTC (permalink / raw)
  To: Ilpo Järvinen
  Cc: platform-driver-x86, linux-input, LKML, Jiri Kosina,
	Benjamin Tissoires, Corentin Chary, Luke D . Jones, Hans de Goede,
	Denis Benato
In-Reply-To: <8e3817f1-73e8-6f61-3eca-e45aa4d46af3@linux.intel.com>

On Mon, 8 Dec 2025 at 18:11, Ilpo Järvinen
<ilpo.jarvinen@linux.intel.com> wrote:
>
> On Sat, 22 Nov 2025, Antheas Kapenekakis wrote:
>
> > ROG NKEY devices have multiple HID endpoints, around 3-4. One of those
> > endpoints has a usage page of 0xff31, and is the one that emits keyboard
> > shortcuts and controls RGB/backlight. Currently, this driver places
> > the usage page check under asus_input_mapping and then inits backlight
> > in asus_input_configured which is unnecessarily complicated and prevents
> > probe from performing customizations on the vendor endpoint.
> >
> > Simplify the logic by introducing an is_vendor variable into probe that
> > checks for usage page 0xff31. Then, use this variable to move backlight
> > initialization into probe instead of asus_input_configured, and remove
> > the backlight check from asus_input_mapping.
>
> In the changelogs, please add () after any name that refers to a C
> function so the reader immediately knows you're talking about a function.

Sure. What should be my timeline for fixing this?

I assume we missed the merge window. If not, I can tweak the series
and send it later today

Antheas

> > Signed-off-by: Antheas Kapenekakis <lkml@antheas.dev>
> > ---
> >  drivers/hid/hid-asus.c | 35 ++++++++++++++++++-----------------
> >  1 file changed, 18 insertions(+), 17 deletions(-)
> >
> > diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c
> > index 2a412e10f916..faac971794c0 100644
> > --- a/drivers/hid/hid-asus.c
> > +++ b/drivers/hid/hid-asus.c
> > @@ -48,6 +48,7 @@ MODULE_DESCRIPTION("Asus HID Keyboard and TouchPad");
> >  #define T100CHI_MOUSE_REPORT_ID 0x06
> >  #define FEATURE_REPORT_ID 0x0d
> >  #define INPUT_REPORT_ID 0x5d
> > +#define HID_USAGE_PAGE_VENDOR 0xff310000
> >  #define FEATURE_KBD_REPORT_ID 0x5a
> >  #define FEATURE_KBD_REPORT_SIZE 64
> >  #define FEATURE_KBD_LED_REPORT_ID1 0x5d
> > @@ -127,7 +128,6 @@ struct asus_drvdata {
> >       struct input_dev *tp_kbd_input;
> >       struct asus_kbd_leds *kbd_backlight;
> >       const struct asus_touchpad_info *tp;
> > -     bool enable_backlight;
> >       struct power_supply *battery;
> >       struct power_supply_desc battery_desc;
> >       int battery_capacity;
> > @@ -318,7 +318,7 @@ static int asus_e1239t_event(struct asus_drvdata *drvdat, u8 *data, int size)
> >  static int asus_event(struct hid_device *hdev, struct hid_field *field,
> >                     struct hid_usage *usage, __s32 value)
> >  {
> > -     if ((usage->hid & HID_USAGE_PAGE) == 0xff310000 &&
> > +     if ((usage->hid & HID_USAGE_PAGE) == HID_USAGE_PAGE_VENDOR &&
> >           (usage->hid & HID_USAGE) != 0x00 &&
> >           (usage->hid & HID_USAGE) != 0xff && !usage->type) {
> >               hid_warn(hdev, "Unmapped Asus vendor usagepage code 0x%02x\n",
> > @@ -941,11 +941,6 @@ static int asus_input_configured(struct hid_device *hdev, struct hid_input *hi)
> >
> >       drvdata->input = input;
> >
> > -     if (drvdata->enable_backlight &&
> > -         !asus_kbd_wmi_led_control_present(hdev) &&
> > -         asus_kbd_register_leds(hdev))
> > -             hid_warn(hdev, "Failed to initialize backlight.\n");
> > -
> >       return 0;
> >  }
> >
> > @@ -1018,15 +1013,6 @@ static int asus_input_mapping(struct hid_device *hdev,
> >                       return -1;
> >               }
> >
> > -             /*
> > -              * Check and enable backlight only on devices with UsagePage ==
> > -              * 0xff31 to avoid initializing the keyboard firmware multiple
> > -              * times on devices with multiple HID descriptors but same
> > -              * PID/VID.
> > -              */
> > -             if (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT)
> > -                     drvdata->enable_backlight = true;
> > -
> >               set_bit(EV_REP, hi->input->evbit);
> >               return 1;
> >       }
> > @@ -1143,8 +1129,11 @@ static int __maybe_unused asus_reset_resume(struct hid_device *hdev)
> >
> >  static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
> >  {
> > -     int ret;
> > +     struct hid_report_enum *rep_enum;
> >       struct asus_drvdata *drvdata;
> > +     struct hid_report *rep;
> > +     bool is_vendor = false;
> > +     int ret;
> >
> >       drvdata = devm_kzalloc(&hdev->dev, sizeof(*drvdata), GFP_KERNEL);
> >       if (drvdata == NULL) {
> > @@ -1228,12 +1217,24 @@ static int asus_probe(struct hid_device *hdev, const struct hid_device_id *id)
> >               return ret;
> >       }
> >
> > +     /* Check for vendor for RGB init and handle generic devices properly. */
> > +     rep_enum = &hdev->report_enum[HID_INPUT_REPORT];
> > +     list_for_each_entry(rep, &rep_enum->report_list, list) {
> > +             if ((rep->application & HID_USAGE_PAGE) == HID_USAGE_PAGE_VENDOR)
> > +                     is_vendor = true;
> > +     }
> > +
> >       ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
> >       if (ret) {
> >               hid_err(hdev, "Asus hw start failed: %d\n", ret);
> >               return ret;
> >       }
> >
> > +     if (is_vendor && (drvdata->quirks & QUIRK_USE_KBD_BACKLIGHT) &&
> > +         !asus_kbd_wmi_led_control_present(hdev) &&
> > +         asus_kbd_register_leds(hdev))
> > +             hid_warn(hdev, "Failed to initialize backlight.\n");
> > +
> >       /*
> >        * Check that input registration succeeded. Checking that
> >        * HID_CLAIMED_INPUT is set prevents a UAF when all input devices
> >
>
> --
>  i.
>
>


^ permalink raw reply

* [PATCH v2 2/2] iio: inkern: Use namespaced exports
From: Romain Gantois @ 2025-12-09  8:25 UTC (permalink / raw)
  To: MyungJoo Ham, Chanwoo Choi, Guenter Roeck, Peter Rosin,
	Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
	Lars-Peter Clausen, Michael Hennerich, Mariel Tinaco, Kevin Tsai,
	Linus Walleij, Dmitry Torokhov, Eugen Hristev, Vinod Koul,
	Kishon Vijay Abraham I, Sebastian Reichel, Chen-Yu Tsai,
	Hans de Goede, Support Opensource, Paul Cercueil, Iskren Chernev,
	Krzysztof Kozlowski, Marek Szyprowski, Matheus Castello,
	Saravanan Sekar, Matthias Brugger, AngeloGioacchino Del Regno,
	Casey Connolly, Pali Rohár, Orson Zhai, Baolin Wang,
	Chunyan Zhang, Amit Kucheria, Thara Gopinath, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Claudiu Beznea,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
	Sylwester Nawrocki, Olivier Moysan, Arnaud Pouliquen,
	Maxime Coquelin, Alexandre Torgue
  Cc: Thomas Petazzoni, linux-kernel, linux-hwmon, linux-iio,
	linux-input, linux-phy, linux-pm, linux-mips, linux-mediatek,
	linux-arm-msm, linux-sound, linux-stm32, Romain Gantois,
	Sebastian Reichel, Andy Shevchenko
In-Reply-To: <20251209-iio-inkern-use-namespaced-exports-v2-0-9799a33c4b7f@bootlin.com>

Use namespaced exports for IIO consumer API functions.

This will make it easier to manage the IIO export surface. Consumer drivers
will only be provided access to a specific set of functions, thereby
restricting usage of internal IIO functions by other parts of the kernel.

This change cannot be split into several parts without breaking
bisectability, thus all of the affected drivers are modified at once.

Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com> # for power-supply
Acked-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Romain Gantois <romain.gantois@bootlin.com>
---
 drivers/extcon/extcon-adc-jack.c                |  1 +
 drivers/hwmon/iio_hwmon.c                       |  1 +
 drivers/hwmon/ntc_thermistor.c                  |  1 +
 drivers/iio/adc/envelope-detector.c             |  1 +
 drivers/iio/afe/iio-rescale.c                   |  1 +
 drivers/iio/buffer/industrialio-buffer-cb.c     |  1 +
 drivers/iio/buffer/industrialio-hw-consumer.c   |  1 +
 drivers/iio/dac/ad8460.c                        |  1 +
 drivers/iio/dac/dpot-dac.c                      |  1 +
 drivers/iio/inkern.c                            | 54 ++++++++++++-------------
 drivers/iio/light/cm3605.c                      |  1 +
 drivers/iio/light/gp2ap002.c                    |  1 +
 drivers/iio/multiplexer/iio-mux.c               |  1 +
 drivers/iio/potentiostat/lmp91000.c             |  1 +
 drivers/input/joystick/adc-joystick.c           |  1 +
 drivers/input/keyboard/adc-keys.c               |  1 +
 drivers/input/touchscreen/colibri-vf50-ts.c     |  1 +
 drivers/input/touchscreen/resistive-adc-touch.c |  1 +
 drivers/phy/motorola/phy-cpcap-usb.c            |  1 +
 drivers/power/supply/ab8500_btemp.c             |  1 +
 drivers/power/supply/ab8500_charger.c           |  1 +
 drivers/power/supply/ab8500_fg.c                |  1 +
 drivers/power/supply/axp20x_ac_power.c          |  1 +
 drivers/power/supply/axp20x_battery.c           |  1 +
 drivers/power/supply/axp20x_usb_power.c         |  1 +
 drivers/power/supply/axp288_fuel_gauge.c        |  1 +
 drivers/power/supply/cpcap-battery.c            |  1 +
 drivers/power/supply/cpcap-charger.c            |  1 +
 drivers/power/supply/da9150-charger.c           |  1 +
 drivers/power/supply/generic-adc-battery.c      |  1 +
 drivers/power/supply/ingenic-battery.c          |  1 +
 drivers/power/supply/intel_dc_ti_battery.c      |  1 +
 drivers/power/supply/lego_ev3_battery.c         |  1 +
 drivers/power/supply/lp8788-charger.c           |  1 +
 drivers/power/supply/max17040_battery.c         |  1 +
 drivers/power/supply/mp2629_charger.c           |  1 +
 drivers/power/supply/mt6370-charger.c           |  1 +
 drivers/power/supply/qcom_smbx.c                |  1 +
 drivers/power/supply/rn5t618_power.c            |  1 +
 drivers/power/supply/rx51_battery.c             |  1 +
 drivers/power/supply/sc27xx_fuel_gauge.c        |  1 +
 drivers/power/supply/twl4030_charger.c          |  1 +
 drivers/power/supply/twl4030_madc_battery.c     |  1 +
 drivers/power/supply/twl6030_charger.c          |  1 +
 drivers/thermal/qcom/qcom-spmi-adc-tm5.c        |  1 +
 drivers/thermal/qcom/qcom-spmi-temp-alarm.c     |  1 +
 drivers/thermal/renesas/rzg3s_thermal.c         |  1 +
 drivers/thermal/thermal-generic-adc.c           |  1 +
 sound/soc/codecs/audio-iio-aux.c                |  1 +
 sound/soc/samsung/aries_wm8994.c                |  1 +
 sound/soc/samsung/midas_wm1811.c                |  1 +
 sound/soc/stm/stm32_adfsdm.c                    |  1 +
 52 files changed, 78 insertions(+), 27 deletions(-)

diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
index 7e3c9f38297b..e735f43dcdeb 100644
--- a/drivers/extcon/extcon-adc-jack.c
+++ b/drivers/extcon/extcon-adc-jack.c
@@ -210,3 +210,4 @@ module_platform_driver(adc_jack_driver);
 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
 MODULE_DESCRIPTION("ADC Jack extcon driver");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/hwmon/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c
index e376d4cde5ad..4c7843fbcc50 100644
--- a/drivers/hwmon/iio_hwmon.c
+++ b/drivers/hwmon/iio_hwmon.c
@@ -222,3 +222,4 @@ module_platform_driver(iio_hwmon_driver);
 MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
 MODULE_DESCRIPTION("IIO to hwmon driver");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c
index d21f7266c411..417807fad80b 100644
--- a/drivers/hwmon/ntc_thermistor.c
+++ b/drivers/hwmon/ntc_thermistor.c
@@ -706,3 +706,4 @@ MODULE_DESCRIPTION("NTC Thermistor Driver");
 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:ntc-thermistor");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/iio/adc/envelope-detector.c b/drivers/iio/adc/envelope-detector.c
index 5b16fe737659..fea20e7e6cd9 100644
--- a/drivers/iio/adc/envelope-detector.c
+++ b/drivers/iio/adc/envelope-detector.c
@@ -406,3 +406,4 @@ module_platform_driver(envelope_detector_driver);
 MODULE_DESCRIPTION("Envelope detector using a DAC and a comparator");
 MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
index ecaf59278c6f..d7f55109af3e 100644
--- a/drivers/iio/afe/iio-rescale.c
+++ b/drivers/iio/afe/iio-rescale.c
@@ -609,3 +609,4 @@ module_platform_driver(rescale_driver);
 MODULE_DESCRIPTION("IIO rescale driver");
 MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/iio/buffer/industrialio-buffer-cb.c b/drivers/iio/buffer/industrialio-buffer-cb.c
index 3e27385069ed..608ea9afc15a 100644
--- a/drivers/iio/buffer/industrialio-buffer-cb.c
+++ b/drivers/iio/buffer/industrialio-buffer-cb.c
@@ -153,3 +153,4 @@ EXPORT_SYMBOL_GPL(iio_channel_cb_get_iio_dev);
 MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
 MODULE_DESCRIPTION("Industrial I/O callback buffer");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/iio/buffer/industrialio-hw-consumer.c b/drivers/iio/buffer/industrialio-hw-consumer.c
index 526b2a8d725d..d7ff086ed783 100644
--- a/drivers/iio/buffer/industrialio-hw-consumer.c
+++ b/drivers/iio/buffer/industrialio-hw-consumer.c
@@ -211,3 +211,4 @@ EXPORT_SYMBOL_GPL(iio_hw_consumer_disable);
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 MODULE_DESCRIPTION("Hardware consumer buffer the IIO framework");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/iio/dac/ad8460.c b/drivers/iio/dac/ad8460.c
index 6e45686902dd..ad654819ca22 100644
--- a/drivers/iio/dac/ad8460.c
+++ b/drivers/iio/dac/ad8460.c
@@ -955,3 +955,4 @@ MODULE_AUTHOR("Mariel Tinaco <mariel.tinaco@analog.com");
 MODULE_DESCRIPTION("AD8460 DAC driver");
 MODULE_LICENSE("GPL");
 MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/iio/dac/dpot-dac.c b/drivers/iio/dac/dpot-dac.c
index d1b8441051ae..49dbdb7df955 100644
--- a/drivers/iio/dac/dpot-dac.c
+++ b/drivers/iio/dac/dpot-dac.c
@@ -254,3 +254,4 @@ module_platform_driver(dpot_dac_driver);
 MODULE_DESCRIPTION("DAC emulation driver using a digital potentiometer");
 MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 1e5eb5a41271..c75c3a8d233f 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -281,7 +281,7 @@ struct iio_channel *fwnode_iio_channel_get_by_name(struct fwnode_handle *fwnode,
 
 	return ERR_PTR(-ENODEV);
 }
-EXPORT_SYMBOL_GPL(fwnode_iio_channel_get_by_name);
+EXPORT_SYMBOL_NS_GPL(fwnode_iio_channel_get_by_name, "IIO_CONSUMER");
 
 static struct iio_channel *fwnode_iio_channel_get_all(struct device *dev)
 {
@@ -386,7 +386,7 @@ struct iio_channel *iio_channel_get(struct device *dev,
 
 	return iio_channel_get_sys(name, channel_name);
 }
-EXPORT_SYMBOL_GPL(iio_channel_get);
+EXPORT_SYMBOL_NS_GPL(iio_channel_get, "IIO_CONSUMER");
 
 void iio_channel_release(struct iio_channel *channel)
 {
@@ -395,7 +395,7 @@ void iio_channel_release(struct iio_channel *channel)
 	iio_device_put(channel->indio_dev);
 	kfree(channel);
 }
-EXPORT_SYMBOL_GPL(iio_channel_release);
+EXPORT_SYMBOL_NS_GPL(iio_channel_release, "IIO_CONSUMER");
 
 static void devm_iio_channel_free(void *iio_channel)
 {
@@ -418,7 +418,7 @@ struct iio_channel *devm_iio_channel_get(struct device *dev,
 
 	return channel;
 }
-EXPORT_SYMBOL_GPL(devm_iio_channel_get);
+EXPORT_SYMBOL_NS_GPL(devm_iio_channel_get, "IIO_CONSUMER");
 
 struct iio_channel *devm_fwnode_iio_channel_get_by_name(struct device *dev,
 							struct fwnode_handle *fwnode,
@@ -437,7 +437,7 @@ struct iio_channel *devm_fwnode_iio_channel_get_by_name(struct device *dev,
 
 	return channel;
 }
-EXPORT_SYMBOL_GPL(devm_fwnode_iio_channel_get_by_name);
+EXPORT_SYMBOL_NS_GPL(devm_fwnode_iio_channel_get_by_name, "IIO_CONSUMER");
 
 struct iio_channel *iio_channel_get_all(struct device *dev)
 {
@@ -506,7 +506,7 @@ struct iio_channel *iio_channel_get_all(struct device *dev)
 		iio_device_put(chans[i].indio_dev);
 	return ERR_PTR(ret);
 }
-EXPORT_SYMBOL_GPL(iio_channel_get_all);
+EXPORT_SYMBOL_NS_GPL(iio_channel_get_all, "IIO_CONSUMER");
 
 void iio_channel_release_all(struct iio_channel *channels)
 {
@@ -518,7 +518,7 @@ void iio_channel_release_all(struct iio_channel *channels)
 	}
 	kfree(channels);
 }
-EXPORT_SYMBOL_GPL(iio_channel_release_all);
+EXPORT_SYMBOL_NS_GPL(iio_channel_release_all, "IIO_CONSUMER");
 
 static void devm_iio_channel_free_all(void *iio_channels)
 {
@@ -541,7 +541,7 @@ struct iio_channel *devm_iio_channel_get_all(struct device *dev)
 
 	return channels;
 }
-EXPORT_SYMBOL_GPL(devm_iio_channel_get_all);
+EXPORT_SYMBOL_NS_GPL(devm_iio_channel_get_all, "IIO_CONSUMER");
 
 static int iio_channel_read(struct iio_channel *chan, int *val, int *val2,
 			    enum iio_chan_info_enum info)
@@ -585,7 +585,7 @@ int iio_read_channel_raw(struct iio_channel *chan, int *val)
 
 	return iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_RAW);
 }
-EXPORT_SYMBOL_GPL(iio_read_channel_raw);
+EXPORT_SYMBOL_NS_GPL(iio_read_channel_raw, "IIO_CONSUMER");
 
 int iio_read_channel_average_raw(struct iio_channel *chan, int *val)
 {
@@ -597,7 +597,7 @@ int iio_read_channel_average_raw(struct iio_channel *chan, int *val)
 
 	return iio_channel_read(chan, val, NULL, IIO_CHAN_INFO_AVERAGE_RAW);
 }
-EXPORT_SYMBOL_GPL(iio_read_channel_average_raw);
+EXPORT_SYMBOL_NS_GPL(iio_read_channel_average_raw, "IIO_CONSUMER");
 
 int iio_multiply_value(int *result, s64 multiplier,
 		       unsigned int type, int val, int val2)
@@ -701,7 +701,7 @@ int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
 	return iio_convert_raw_to_processed_unlocked(chan, raw, processed,
 						     scale);
 }
-EXPORT_SYMBOL_GPL(iio_convert_raw_to_processed);
+EXPORT_SYMBOL_NS_GPL(iio_convert_raw_to_processed, "IIO_CONSUMER");
 
 int iio_read_channel_attribute(struct iio_channel *chan, int *val, int *val2,
 			       enum iio_chan_info_enum attribute)
@@ -714,13 +714,13 @@ int iio_read_channel_attribute(struct iio_channel *chan, int *val, int *val2,
 
 	return iio_channel_read(chan, val, val2, attribute);
 }
-EXPORT_SYMBOL_GPL(iio_read_channel_attribute);
+EXPORT_SYMBOL_NS_GPL(iio_read_channel_attribute, "IIO_CONSUMER");
 
 int iio_read_channel_offset(struct iio_channel *chan, int *val, int *val2)
 {
 	return iio_read_channel_attribute(chan, val, val2, IIO_CHAN_INFO_OFFSET);
 }
-EXPORT_SYMBOL_GPL(iio_read_channel_offset);
+EXPORT_SYMBOL_NS_GPL(iio_read_channel_offset, "IIO_CONSUMER");
 
 int iio_read_channel_processed_scale(struct iio_channel *chan, int *val,
 				     unsigned int scale)
@@ -748,20 +748,20 @@ int iio_read_channel_processed_scale(struct iio_channel *chan, int *val,
 							     scale);
 	}
 }
-EXPORT_SYMBOL_GPL(iio_read_channel_processed_scale);
+EXPORT_SYMBOL_NS_GPL(iio_read_channel_processed_scale, "IIO_CONSUMER");
 
 int iio_read_channel_processed(struct iio_channel *chan, int *val)
 {
 	/* This is just a special case with scale factor 1 */
 	return iio_read_channel_processed_scale(chan, val, 1);
 }
-EXPORT_SYMBOL_GPL(iio_read_channel_processed);
+EXPORT_SYMBOL_NS_GPL(iio_read_channel_processed, "IIO_CONSUMER");
 
 int iio_read_channel_scale(struct iio_channel *chan, int *val, int *val2)
 {
 	return iio_read_channel_attribute(chan, val, val2, IIO_CHAN_INFO_SCALE);
 }
-EXPORT_SYMBOL_GPL(iio_read_channel_scale);
+EXPORT_SYMBOL_NS_GPL(iio_read_channel_scale, "IIO_CONSUMER");
 
 static int iio_channel_read_avail(struct iio_channel *chan,
 				  const int **vals, int *type, int *length,
@@ -790,7 +790,7 @@ int iio_read_avail_channel_attribute(struct iio_channel *chan,
 
 	return iio_channel_read_avail(chan, vals, type, length, attribute);
 }
-EXPORT_SYMBOL_GPL(iio_read_avail_channel_attribute);
+EXPORT_SYMBOL_NS_GPL(iio_read_avail_channel_attribute, "IIO_CONSUMER");
 
 int iio_read_avail_channel_raw(struct iio_channel *chan,
 			       const int **vals, int *length)
@@ -807,7 +807,7 @@ int iio_read_avail_channel_raw(struct iio_channel *chan,
 
 	return ret;
 }
-EXPORT_SYMBOL_GPL(iio_read_avail_channel_raw);
+EXPORT_SYMBOL_NS_GPL(iio_read_avail_channel_raw, "IIO_CONSUMER");
 
 static int iio_channel_read_max(struct iio_channel *chan,
 				int *val, int *val2, int *type,
@@ -863,7 +863,7 @@ int iio_read_max_channel_raw(struct iio_channel *chan, int *val)
 
 	return iio_channel_read_max(chan, val, NULL, &type, IIO_CHAN_INFO_RAW);
 }
-EXPORT_SYMBOL_GPL(iio_read_max_channel_raw);
+EXPORT_SYMBOL_NS_GPL(iio_read_max_channel_raw, "IIO_CONSUMER");
 
 static int iio_channel_read_min(struct iio_channel *chan,
 				int *val, int *val2, int *type,
@@ -919,7 +919,7 @@ int iio_read_min_channel_raw(struct iio_channel *chan, int *val)
 
 	return iio_channel_read_min(chan, val, NULL, &type, IIO_CHAN_INFO_RAW);
 }
-EXPORT_SYMBOL_GPL(iio_read_min_channel_raw);
+EXPORT_SYMBOL_NS_GPL(iio_read_min_channel_raw, "IIO_CONSUMER");
 
 int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type)
 {
@@ -933,7 +933,7 @@ int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type)
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(iio_get_channel_type);
+EXPORT_SYMBOL_NS_GPL(iio_get_channel_type, "IIO_CONSUMER");
 
 static int iio_channel_write(struct iio_channel *chan, int val, int val2,
 			     enum iio_chan_info_enum info)
@@ -957,13 +957,13 @@ int iio_write_channel_attribute(struct iio_channel *chan, int val, int val2,
 
 	return iio_channel_write(chan, val, val2, attribute);
 }
-EXPORT_SYMBOL_GPL(iio_write_channel_attribute);
+EXPORT_SYMBOL_NS_GPL(iio_write_channel_attribute, "IIO_CONSUMER");
 
 int iio_write_channel_raw(struct iio_channel *chan, int val)
 {
 	return iio_write_channel_attribute(chan, val, 0, IIO_CHAN_INFO_RAW);
 }
-EXPORT_SYMBOL_GPL(iio_write_channel_raw);
+EXPORT_SYMBOL_NS_GPL(iio_write_channel_raw, "IIO_CONSUMER");
 
 unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan)
 {
@@ -978,7 +978,7 @@ unsigned int iio_get_channel_ext_info_count(struct iio_channel *chan)
 
 	return i;
 }
-EXPORT_SYMBOL_GPL(iio_get_channel_ext_info_count);
+EXPORT_SYMBOL_NS_GPL(iio_get_channel_ext_info_count, "IIO_CONSUMER");
 
 static const struct iio_chan_spec_ext_info *
 iio_lookup_ext_info(const struct iio_channel *chan, const char *attr)
@@ -1013,7 +1013,7 @@ ssize_t iio_read_channel_ext_info(struct iio_channel *chan,
 	return ext_info->read(chan->indio_dev, ext_info->private,
 			      chan->channel, buf);
 }
-EXPORT_SYMBOL_GPL(iio_read_channel_ext_info);
+EXPORT_SYMBOL_NS_GPL(iio_read_channel_ext_info, "IIO_CONSUMER");
 
 ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
 				   const char *buf, size_t len)
@@ -1027,7 +1027,7 @@ ssize_t iio_write_channel_ext_info(struct iio_channel *chan, const char *attr,
 	return ext_info->write(chan->indio_dev, ext_info->private,
 			       chan->channel, buf, len);
 }
-EXPORT_SYMBOL_GPL(iio_write_channel_ext_info);
+EXPORT_SYMBOL_NS_GPL(iio_write_channel_ext_info, "IIO_CONSUMER");
 
 ssize_t iio_read_channel_label(struct iio_channel *chan, char *buf)
 {
@@ -1038,4 +1038,4 @@ ssize_t iio_read_channel_label(struct iio_channel *chan, char *buf)
 
 	return do_iio_read_channel_label(chan->indio_dev, chan->channel, buf);
 }
-EXPORT_SYMBOL_GPL(iio_read_channel_label);
+EXPORT_SYMBOL_NS_GPL(iio_read_channel_label, "IIO_CONSUMER");
diff --git a/drivers/iio/light/cm3605.c b/drivers/iio/light/cm3605.c
index 0c17378e27d1..1bd11292d005 100644
--- a/drivers/iio/light/cm3605.c
+++ b/drivers/iio/light/cm3605.c
@@ -325,3 +325,4 @@ module_platform_driver(cm3605_driver);
 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
 MODULE_DESCRIPTION("CM3605 ambient light and proximity sensor driver");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c
index a0d8a58f2704..04b1f6eade0e 100644
--- a/drivers/iio/light/gp2ap002.c
+++ b/drivers/iio/light/gp2ap002.c
@@ -717,3 +717,4 @@ module_i2c_driver(gp2ap002_driver);
 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
 MODULE_DESCRIPTION("GP2AP002 ambient light and proximity sensor driver");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/iio/multiplexer/iio-mux.c b/drivers/iio/multiplexer/iio-mux.c
index b742ca9a99d1..e193913f5af7 100644
--- a/drivers/iio/multiplexer/iio-mux.c
+++ b/drivers/iio/multiplexer/iio-mux.c
@@ -464,3 +464,4 @@ module_platform_driver(mux_driver);
 MODULE_DESCRIPTION("IIO multiplexer driver");
 MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c
index eccc2a34358f..7d993f2acda4 100644
--- a/drivers/iio/potentiostat/lmp91000.c
+++ b/drivers/iio/potentiostat/lmp91000.c
@@ -423,3 +423,4 @@ module_i2c_driver(lmp91000_driver);
 MODULE_AUTHOR("Matt Ranostay <matt.ranostay@konsulko.com>");
 MODULE_DESCRIPTION("LMP91000 digital potentiostat");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/input/joystick/adc-joystick.c b/drivers/input/joystick/adc-joystick.c
index ff44f9978b71..4fa42f88bcfa 100644
--- a/drivers/input/joystick/adc-joystick.c
+++ b/drivers/input/joystick/adc-joystick.c
@@ -329,3 +329,4 @@ module_platform_driver(adc_joystick_driver);
 MODULE_DESCRIPTION("Input driver for joysticks connected over ADC");
 MODULE_AUTHOR("Artur Rojek <contact@artur-rojek.eu>");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/input/keyboard/adc-keys.c b/drivers/input/keyboard/adc-keys.c
index f1753207429d..d687459a0c80 100644
--- a/drivers/input/keyboard/adc-keys.c
+++ b/drivers/input/keyboard/adc-keys.c
@@ -202,3 +202,4 @@ module_platform_driver(adc_keys_driver);
 MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
 MODULE_DESCRIPTION("Input driver for resistor ladder connected on ADC");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/input/touchscreen/colibri-vf50-ts.c b/drivers/input/touchscreen/colibri-vf50-ts.c
index 98d5b2ba63fb..89c4d7b2b89e 100644
--- a/drivers/input/touchscreen/colibri-vf50-ts.c
+++ b/drivers/input/touchscreen/colibri-vf50-ts.c
@@ -372,3 +372,4 @@ module_platform_driver(vf50_touch_driver);
 MODULE_AUTHOR("Sanchayan Maity");
 MODULE_DESCRIPTION("Colibri VF50 Touchscreen driver");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/input/touchscreen/resistive-adc-touch.c b/drivers/input/touchscreen/resistive-adc-touch.c
index 7e761ec73273..2fefd652864c 100644
--- a/drivers/input/touchscreen/resistive-adc-touch.c
+++ b/drivers/input/touchscreen/resistive-adc-touch.c
@@ -301,3 +301,4 @@ module_platform_driver(grts_driver);
 MODULE_AUTHOR("Eugen Hristev <eugen.hristev@microchip.com>");
 MODULE_DESCRIPTION("Generic ADC Resistive Touch Driver");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/phy/motorola/phy-cpcap-usb.c b/drivers/phy/motorola/phy-cpcap-usb.c
index 7cb020dd3423..9591672b0511 100644
--- a/drivers/phy/motorola/phy-cpcap-usb.c
+++ b/drivers/phy/motorola/phy-cpcap-usb.c
@@ -717,3 +717,4 @@ MODULE_ALIAS("platform:cpcap_usb");
 MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
 MODULE_DESCRIPTION("CPCAP usb phy driver");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c
index e5202a7b6209..36b0c52a4b8b 100644
--- a/drivers/power/supply/ab8500_btemp.c
+++ b/drivers/power/supply/ab8500_btemp.c
@@ -829,3 +829,4 @@ MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy");
 MODULE_ALIAS("platform:ab8500-btemp");
 MODULE_DESCRIPTION("AB8500 battery temperature driver");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c
index 5f4537766e5b..6e49d1b28254 100644
--- a/drivers/power/supply/ab8500_charger.c
+++ b/drivers/power/supply/ab8500_charger.c
@@ -3751,3 +3751,4 @@ MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Johan Palsson, Karl Komierowski, Arun R Murthy");
 MODULE_ALIAS("platform:ab8500-charger");
 MODULE_DESCRIPTION("AB8500 charger management driver");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
index 9dd99722667a..5fa559f796aa 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -3252,3 +3252,4 @@ MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Johan Palsson, Karl Komierowski");
 MODULE_ALIAS("platform:ab8500-fg");
 MODULE_DESCRIPTION("AB8500 Fuel Gauge driver");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/axp20x_ac_power.c b/drivers/power/supply/axp20x_ac_power.c
index 5f6ea416fa30..e9049d6229df 100644
--- a/drivers/power/supply/axp20x_ac_power.c
+++ b/drivers/power/supply/axp20x_ac_power.c
@@ -421,3 +421,4 @@ module_platform_driver(axp20x_ac_power_driver);
 MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
 MODULE_DESCRIPTION("AXP20X and AXP22X PMICs' AC power supply driver");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c
index 50ca8e110085..ee8701a6e907 100644
--- a/drivers/power/supply/axp20x_battery.c
+++ b/drivers/power/supply/axp20x_battery.c
@@ -1155,3 +1155,4 @@ module_platform_driver(axp20x_batt_driver);
 MODULE_DESCRIPTION("Battery power supply driver for AXP20X and AXP22X PMICs");
 MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c
index e75d1e377ac1..599adcf84968 100644
--- a/drivers/power/supply/axp20x_usb_power.c
+++ b/drivers/power/supply/axp20x_usb_power.c
@@ -1080,3 +1080,4 @@ module_platform_driver(axp20x_usb_power_driver);
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_DESCRIPTION("AXP20x PMIC USB power supply status driver");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
index a3d71fc72064..c6897dd808fc 100644
--- a/drivers/power/supply/axp288_fuel_gauge.c
+++ b/drivers/power/supply/axp288_fuel_gauge.c
@@ -817,3 +817,4 @@ MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>");
 MODULE_AUTHOR("Todd Brandt <todd.e.brandt@linux.intel.com>");
 MODULE_DESCRIPTION("Xpower AXP288 Fuel Gauge Driver");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c
index 8106d1edcbc2..542c3c70e3cb 100644
--- a/drivers/power/supply/cpcap-battery.c
+++ b/drivers/power/supply/cpcap-battery.c
@@ -1176,3 +1176,4 @@ module_platform_driver(cpcap_battery_driver);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
 MODULE_DESCRIPTION("CPCAP PMIC Battery Driver");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/cpcap-charger.c b/drivers/power/supply/cpcap-charger.c
index d0c3008db534..89bc0fc3c9f8 100644
--- a/drivers/power/supply/cpcap-charger.c
+++ b/drivers/power/supply/cpcap-charger.c
@@ -977,3 +977,4 @@ MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
 MODULE_DESCRIPTION("CPCAP Battery Charger Interface driver");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:cpcap-charger");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/da9150-charger.c b/drivers/power/supply/da9150-charger.c
index 27f36ef5b88d..58449df6068c 100644
--- a/drivers/power/supply/da9150-charger.c
+++ b/drivers/power/supply/da9150-charger.c
@@ -644,3 +644,4 @@ module_platform_driver(da9150_charger_driver);
 MODULE_DESCRIPTION("Charger Driver for DA9150");
 MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/generic-adc-battery.c b/drivers/power/supply/generic-adc-battery.c
index f5f2566b3a32..d18c8ee40405 100644
--- a/drivers/power/supply/generic-adc-battery.c
+++ b/drivers/power/supply/generic-adc-battery.c
@@ -298,3 +298,4 @@ module_platform_driver(gab_driver);
 MODULE_AUTHOR("anish kumar <yesanishhere@gmail.com>");
 MODULE_DESCRIPTION("generic battery driver using IIO");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/ingenic-battery.c b/drivers/power/supply/ingenic-battery.c
index b111c7ce2be3..5be269f17bff 100644
--- a/drivers/power/supply/ingenic-battery.c
+++ b/drivers/power/supply/ingenic-battery.c
@@ -190,3 +190,4 @@ module_platform_driver(ingenic_battery_driver);
 MODULE_DESCRIPTION("Battery driver for Ingenic JZ47xx SoCs");
 MODULE_AUTHOR("Artur Rojek <contact@artur-rojek.eu>");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/intel_dc_ti_battery.c b/drivers/power/supply/intel_dc_ti_battery.c
index 56b0c92e9d28..1a16ded563bc 100644
--- a/drivers/power/supply/intel_dc_ti_battery.c
+++ b/drivers/power/supply/intel_dc_ti_battery.c
@@ -387,3 +387,4 @@ MODULE_ALIAS("platform:" DEV_NAME);
 MODULE_AUTHOR("Hans de Goede <hansg@kernel.org>");
 MODULE_DESCRIPTION("Intel Dollar Cove (TI) battery driver");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/lego_ev3_battery.c b/drivers/power/supply/lego_ev3_battery.c
index 28454de05761..414816662b06 100644
--- a/drivers/power/supply/lego_ev3_battery.c
+++ b/drivers/power/supply/lego_ev3_battery.c
@@ -231,3 +231,4 @@ module_platform_driver(lego_ev3_battery_driver);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Lechner <david@lechnology.com>");
 MODULE_DESCRIPTION("LEGO MINDSTORMS EV3 Battery Driver");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/lp8788-charger.c b/drivers/power/supply/lp8788-charger.c
index f0a680c155c4..8c6ec98362d0 100644
--- a/drivers/power/supply/lp8788-charger.c
+++ b/drivers/power/supply/lp8788-charger.c
@@ -727,3 +727,4 @@ MODULE_DESCRIPTION("TI LP8788 Charger Driver");
 MODULE_AUTHOR("Milo Kim");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:lp8788-charger");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/max17040_battery.c b/drivers/power/supply/max17040_battery.c
index c1640bc6accd..1fe658bfecc1 100644
--- a/drivers/power/supply/max17040_battery.c
+++ b/drivers/power/supply/max17040_battery.c
@@ -635,3 +635,4 @@ module_i2c_driver(max17040_i2c_driver);
 MODULE_AUTHOR("Minkyu Kang <mk7.kang@samsung.com>");
 MODULE_DESCRIPTION("MAX17040 Fuel Gauge");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/mp2629_charger.c b/drivers/power/supply/mp2629_charger.c
index d281c1059629..ed49f9a04c8c 100644
--- a/drivers/power/supply/mp2629_charger.c
+++ b/drivers/power/supply/mp2629_charger.c
@@ -660,3 +660,4 @@ module_platform_driver(mp2629_charger_driver);
 MODULE_AUTHOR("Saravanan Sekar <sravanhome@gmail.com>");
 MODULE_DESCRIPTION("MP2629 Charger driver");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/mt6370-charger.c b/drivers/power/supply/mt6370-charger.c
index e6db961d5818..2d02fdf37d70 100644
--- a/drivers/power/supply/mt6370-charger.c
+++ b/drivers/power/supply/mt6370-charger.c
@@ -941,3 +941,4 @@ module_platform_driver(mt6370_chg_driver);
 MODULE_AUTHOR("ChiaEn Wu <chiaen_wu@richtek.com>");
 MODULE_DESCRIPTION("MediaTek MT6370 Charger Driver");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/qcom_smbx.c b/drivers/power/supply/qcom_smbx.c
index b1cb925581ec..63b88754155c 100644
--- a/drivers/power/supply/qcom_smbx.c
+++ b/drivers/power/supply/qcom_smbx.c
@@ -1050,3 +1050,4 @@ module_platform_driver(qcom_spmi_smb);
 MODULE_AUTHOR("Casey Connolly <casey.connolly@linaro.org>");
 MODULE_DESCRIPTION("Qualcomm SMB2 Charger Driver");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/rn5t618_power.c b/drivers/power/supply/rn5t618_power.c
index 40dec55a9f73..a3f30e390c11 100644
--- a/drivers/power/supply/rn5t618_power.c
+++ b/drivers/power/supply/rn5t618_power.c
@@ -821,3 +821,4 @@ module_platform_driver(rn5t618_power_driver);
 MODULE_ALIAS("platform:rn5t618-power");
 MODULE_DESCRIPTION("Power supply driver for RICOH RN5T618");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/rx51_battery.c b/drivers/power/supply/rx51_battery.c
index b0220ec2d926..57266921dc8e 100644
--- a/drivers/power/supply/rx51_battery.c
+++ b/drivers/power/supply/rx51_battery.c
@@ -246,3 +246,4 @@ MODULE_ALIAS("platform:rx51-battery");
 MODULE_AUTHOR("Pali Rohár <pali@kernel.org>");
 MODULE_DESCRIPTION("Nokia RX-51 battery driver");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c
index a7ed9de8a289..1719ec4173e6 100644
--- a/drivers/power/supply/sc27xx_fuel_gauge.c
+++ b/drivers/power/supply/sc27xx_fuel_gauge.c
@@ -1350,3 +1350,4 @@ module_platform_driver(sc27xx_fgu_driver);
 
 MODULE_DESCRIPTION("Spreadtrum SC27XX PMICs Fual Gauge Unit Driver");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/twl4030_charger.c b/drivers/power/supply/twl4030_charger.c
index 04216b2bfb6c..151f7b24e9b9 100644
--- a/drivers/power/supply/twl4030_charger.c
+++ b/drivers/power/supply/twl4030_charger.c
@@ -1144,3 +1144,4 @@ MODULE_AUTHOR("Gražvydas Ignotas");
 MODULE_DESCRIPTION("TWL4030 Battery Charger Interface driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:twl4030_bci");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/twl4030_madc_battery.c b/drivers/power/supply/twl4030_madc_battery.c
index 3935162e350b..9b3785d1643c 100644
--- a/drivers/power/supply/twl4030_madc_battery.c
+++ b/drivers/power/supply/twl4030_madc_battery.c
@@ -237,3 +237,4 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Lukas Märdian <lukas@goldelico.com>");
 MODULE_DESCRIPTION("twl4030_madc battery driver");
 MODULE_ALIAS("platform:twl4030_madc_battery");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/power/supply/twl6030_charger.c b/drivers/power/supply/twl6030_charger.c
index b4ec26ff257c..82911a811f4e 100644
--- a/drivers/power/supply/twl6030_charger.c
+++ b/drivers/power/supply/twl6030_charger.c
@@ -579,3 +579,4 @@ module_platform_driver(twl6030_charger_driver);
 
 MODULE_DESCRIPTION("TWL6030 Battery Charger Interface driver");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
index d7f2e6ca92c2..bb6222c8cc5f 100644
--- a/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
+++ b/drivers/thermal/qcom/qcom-spmi-adc-tm5.c
@@ -1069,3 +1069,4 @@ module_platform_driver(adc_tm5_driver);
 
 MODULE_DESCRIPTION("SPMI PMIC Thermal Monitor ADC driver");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
index f39ca0ddd17b..fb003ca96454 100644
--- a/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
+++ b/drivers/thermal/qcom/qcom-spmi-temp-alarm.c
@@ -904,3 +904,4 @@ module_platform_driver(qpnp_tm_driver);
 MODULE_ALIAS("platform:spmi-temp-alarm");
 MODULE_DESCRIPTION("QPNP PMIC Temperature Alarm driver");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/thermal/renesas/rzg3s_thermal.c b/drivers/thermal/renesas/rzg3s_thermal.c
index e25e36c99a88..7ced8f76a0ec 100644
--- a/drivers/thermal/renesas/rzg3s_thermal.c
+++ b/drivers/thermal/renesas/rzg3s_thermal.c
@@ -270,3 +270,4 @@ module_platform_driver(rzg3s_thermal_driver);
 MODULE_DESCRIPTION("Renesas RZ/G3S Thermal Sensor Unit Driver");
 MODULE_AUTHOR("Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c
index 7c844589b153..cfdb8e674dd2 100644
--- a/drivers/thermal/thermal-generic-adc.c
+++ b/drivers/thermal/thermal-generic-adc.c
@@ -228,3 +228,4 @@ module_platform_driver(gadc_thermal_driver);
 MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
 MODULE_DESCRIPTION("Generic ADC thermal driver using IIO framework with DT");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/sound/soc/codecs/audio-iio-aux.c b/sound/soc/codecs/audio-iio-aux.c
index 588e48044c13..864a5a676495 100644
--- a/sound/soc/codecs/audio-iio-aux.c
+++ b/sound/soc/codecs/audio-iio-aux.c
@@ -312,3 +312,4 @@ module_platform_driver(audio_iio_aux_driver);
 MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
 MODULE_DESCRIPTION("IIO ALSA SoC aux driver");
 MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/sound/soc/samsung/aries_wm8994.c b/sound/soc/samsung/aries_wm8994.c
index 3723329b266d..b6f0f3c0d393 100644
--- a/sound/soc/samsung/aries_wm8994.c
+++ b/sound/soc/samsung/aries_wm8994.c
@@ -700,3 +700,4 @@ module_platform_driver(aries_audio_driver);
 MODULE_DESCRIPTION("ALSA SoC ARIES WM8994");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:aries-audio-wm8994");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/sound/soc/samsung/midas_wm1811.c b/sound/soc/samsung/midas_wm1811.c
index 239e958b88d3..12c4962f901d 100644
--- a/sound/soc/samsung/midas_wm1811.c
+++ b/sound/soc/samsung/midas_wm1811.c
@@ -773,3 +773,4 @@ module_platform_driver(midas_driver);
 MODULE_AUTHOR("Simon Shields <simon@lineageos.org>");
 MODULE_DESCRIPTION("ASoC support for Midas");
 MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_CONSUMER");
diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c
index c914d1c46850..dabcd2759187 100644
--- a/sound/soc/stm/stm32_adfsdm.c
+++ b/sound/soc/stm/stm32_adfsdm.c
@@ -407,3 +407,4 @@ MODULE_DESCRIPTION("stm32 DFSDM DAI driver");
 MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:" STM32_ADFSDM_DRV_NAME);
+MODULE_IMPORT_NS("IIO_CONSUMER");

-- 
2.51.2


^ permalink raw reply related

* [PATCH v2 1/2] iio: dac: ds4424: drop unused include IIO consumer header
From: Romain Gantois @ 2025-12-09  8:25 UTC (permalink / raw)
  To: MyungJoo Ham, Chanwoo Choi, Guenter Roeck, Peter Rosin,
	Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
	Lars-Peter Clausen, Michael Hennerich, Mariel Tinaco, Kevin Tsai,
	Linus Walleij, Dmitry Torokhov, Eugen Hristev, Vinod Koul,
	Kishon Vijay Abraham I, Sebastian Reichel, Chen-Yu Tsai,
	Hans de Goede, Support Opensource, Paul Cercueil, Iskren Chernev,
	Krzysztof Kozlowski, Marek Szyprowski, Matheus Castello,
	Saravanan Sekar, Matthias Brugger, AngeloGioacchino Del Regno,
	Casey Connolly, Pali Rohár, Orson Zhai, Baolin Wang,
	Chunyan Zhang, Amit Kucheria, Thara Gopinath, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Claudiu Beznea,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
	Sylwester Nawrocki, Olivier Moysan, Arnaud Pouliquen,
	Maxime Coquelin, Alexandre Torgue
  Cc: Thomas Petazzoni, linux-kernel, linux-hwmon, linux-iio,
	linux-input, linux-phy, linux-pm, linux-mips, linux-mediatek,
	linux-arm-msm, linux-sound, linux-stm32, Romain Gantois
In-Reply-To: <20251209-iio-inkern-use-namespaced-exports-v2-0-9799a33c4b7f@bootlin.com>

To prepare for the introduction of namespaced exports for the IIO consumer
API, remove this include directive which isn't actually used by the driver.

Signed-off-by: Romain Gantois <romain.gantois@bootlin.com>
---
 drivers/iio/dac/ds4424.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/iio/dac/ds4424.c b/drivers/iio/dac/ds4424.c
index a8198ba4f98a..6dda8918975a 100644
--- a/drivers/iio/dac/ds4424.c
+++ b/drivers/iio/dac/ds4424.c
@@ -14,7 +14,6 @@
 #include <linux/iio/iio.h>
 #include <linux/iio/driver.h>
 #include <linux/iio/machine.h>
-#include <linux/iio/consumer.h>
 
 #define DS4422_MAX_DAC_CHANNELS		2
 #define DS4424_MAX_DAC_CHANNELS		4

-- 
2.51.2


^ permalink raw reply related

* [PATCH v2 0/2] iio: inkern: Use namespaced exports
From: Romain Gantois @ 2025-12-09  8:25 UTC (permalink / raw)
  To: MyungJoo Ham, Chanwoo Choi, Guenter Roeck, Peter Rosin,
	Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
	Lars-Peter Clausen, Michael Hennerich, Mariel Tinaco, Kevin Tsai,
	Linus Walleij, Dmitry Torokhov, Eugen Hristev, Vinod Koul,
	Kishon Vijay Abraham I, Sebastian Reichel, Chen-Yu Tsai,
	Hans de Goede, Support Opensource, Paul Cercueil, Iskren Chernev,
	Krzysztof Kozlowski, Marek Szyprowski, Matheus Castello,
	Saravanan Sekar, Matthias Brugger, AngeloGioacchino Del Regno,
	Casey Connolly, Pali Rohár, Orson Zhai, Baolin Wang,
	Chunyan Zhang, Amit Kucheria, Thara Gopinath, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Claudiu Beznea,
	Liam Girdwood, Mark Brown, Jaroslav Kysela, Takashi Iwai,
	Sylwester Nawrocki, Olivier Moysan, Arnaud Pouliquen,
	Maxime Coquelin, Alexandre Torgue
  Cc: Thomas Petazzoni, linux-kernel, linux-hwmon, linux-iio,
	linux-input, linux-phy, linux-pm, linux-mips, linux-mediatek,
	linux-arm-msm, linux-sound, linux-stm32, Romain Gantois,
	Sebastian Reichel, Andy Shevchenko

Hello everyone,

This is version two of my series which introduces namespaced exports for
the IIO consumer API.

Best Regards,

Romain

Signed-off-by: Romain Gantois <romain.gantois@bootlin.com>
---
Changes in v2:
- Separated out ds4424 changes.
- Improved commit descriptions.
- Link to v1: https://lore.kernel.org/r/20251201-iio-inkern-use-namespaced-exports-v1-1-da1935f70243@bootlin.com

---
Romain Gantois (2):
      iio: dac: ds4424: drop unused include IIO consumer header
      iio: inkern: Use namespaced exports

 drivers/extcon/extcon-adc-jack.c                |  1 +
 drivers/hwmon/iio_hwmon.c                       |  1 +
 drivers/hwmon/ntc_thermistor.c                  |  1 +
 drivers/iio/adc/envelope-detector.c             |  1 +
 drivers/iio/afe/iio-rescale.c                   |  1 +
 drivers/iio/buffer/industrialio-buffer-cb.c     |  1 +
 drivers/iio/buffer/industrialio-hw-consumer.c   |  1 +
 drivers/iio/dac/ad8460.c                        |  1 +
 drivers/iio/dac/dpot-dac.c                      |  1 +
 drivers/iio/dac/ds4424.c                        |  1 -
 drivers/iio/inkern.c                            | 54 ++++++++++++-------------
 drivers/iio/light/cm3605.c                      |  1 +
 drivers/iio/light/gp2ap002.c                    |  1 +
 drivers/iio/multiplexer/iio-mux.c               |  1 +
 drivers/iio/potentiostat/lmp91000.c             |  1 +
 drivers/input/joystick/adc-joystick.c           |  1 +
 drivers/input/keyboard/adc-keys.c               |  1 +
 drivers/input/touchscreen/colibri-vf50-ts.c     |  1 +
 drivers/input/touchscreen/resistive-adc-touch.c |  1 +
 drivers/phy/motorola/phy-cpcap-usb.c            |  1 +
 drivers/power/supply/ab8500_btemp.c             |  1 +
 drivers/power/supply/ab8500_charger.c           |  1 +
 drivers/power/supply/ab8500_fg.c                |  1 +
 drivers/power/supply/axp20x_ac_power.c          |  1 +
 drivers/power/supply/axp20x_battery.c           |  1 +
 drivers/power/supply/axp20x_usb_power.c         |  1 +
 drivers/power/supply/axp288_fuel_gauge.c        |  1 +
 drivers/power/supply/cpcap-battery.c            |  1 +
 drivers/power/supply/cpcap-charger.c            |  1 +
 drivers/power/supply/da9150-charger.c           |  1 +
 drivers/power/supply/generic-adc-battery.c      |  1 +
 drivers/power/supply/ingenic-battery.c          |  1 +
 drivers/power/supply/intel_dc_ti_battery.c      |  1 +
 drivers/power/supply/lego_ev3_battery.c         |  1 +
 drivers/power/supply/lp8788-charger.c           |  1 +
 drivers/power/supply/max17040_battery.c         |  1 +
 drivers/power/supply/mp2629_charger.c           |  1 +
 drivers/power/supply/mt6370-charger.c           |  1 +
 drivers/power/supply/qcom_smbx.c                |  1 +
 drivers/power/supply/rn5t618_power.c            |  1 +
 drivers/power/supply/rx51_battery.c             |  1 +
 drivers/power/supply/sc27xx_fuel_gauge.c        |  1 +
 drivers/power/supply/twl4030_charger.c          |  1 +
 drivers/power/supply/twl4030_madc_battery.c     |  1 +
 drivers/power/supply/twl6030_charger.c          |  1 +
 drivers/thermal/qcom/qcom-spmi-adc-tm5.c        |  1 +
 drivers/thermal/qcom/qcom-spmi-temp-alarm.c     |  1 +
 drivers/thermal/renesas/rzg3s_thermal.c         |  1 +
 drivers/thermal/thermal-generic-adc.c           |  1 +
 sound/soc/codecs/audio-iio-aux.c                |  1 +
 sound/soc/samsung/aries_wm8994.c                |  1 +
 sound/soc/samsung/midas_wm1811.c                |  1 +
 sound/soc/stm/stm32_adfsdm.c                    |  1 +
 53 files changed, 78 insertions(+), 28 deletions(-)
---
base-commit: 99fece7ab29c9654d7945312b275b527757ac4b3
change-id: 20251127-iio-inkern-use-namespaced-exports-41fc09223b5e

Best regards,
-- 
Romain Gantois <romain.gantois@bootlin.com>


^ permalink raw reply

* [PATCH v2 4/4] HID: Intel-thc-hid: Intel-quicki2c: Add output report support
From: Even Xu @ 2025-12-09  7:52 UTC (permalink / raw)
  To: jikos, bentiss
  Cc: srinivas.pandruvada, linux-input, linux-kernel, Even Xu,
	Rui Zhang
In-Reply-To: <20251209075215.1535371-1-even.xu@intel.com>

Add support for HID output reports in the intel-quicki2c driver by
implementing the output_report callback in the HID low-level driver
interface.

This enables proper communication with HID devices that require
output report functionality, such as setting device configuration or
updating device firmware.

Tested-by: Rui Zhang <rui1.zhang@intel.com>
Signed-off-by: Even Xu <even.xu@intel.com>
---
 .../intel-quicki2c/quicki2c-hid.c             |  8 ++++++++
 .../intel-quicki2c/quicki2c-protocol.c        | 19 +++++++++++++++++++
 .../intel-quicki2c/quicki2c-protocol.h        |  1 +
 3 files changed, 28 insertions(+)

diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-hid.c b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-hid.c
index 5c3ec95bb3fd..580a760b3ffc 100644
--- a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-hid.c
+++ b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-hid.c
@@ -83,6 +83,13 @@ static int quicki2c_hid_power(struct hid_device *hid, int lvl)
 	return 0;
 }
 
+static int quicki2c_hid_output_report(struct hid_device *hid, u8 *buf, size_t count)
+{
+	struct quicki2c_device *qcdev = hid->driver_data;
+
+	return quicki2c_output_report(qcdev, buf, count);
+}
+
 static struct hid_ll_driver quicki2c_hid_ll_driver = {
 	.parse = quicki2c_hid_parse,
 	.start = quicki2c_hid_start,
@@ -91,6 +98,7 @@ static struct hid_ll_driver quicki2c_hid_ll_driver = {
 	.close = quicki2c_hid_close,
 	.power = quicki2c_hid_power,
 	.raw_request = quicki2c_hid_raw_request,
+	.output_report = quicki2c_hid_output_report,
 };
 
 /**
diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c
index a287d9ee09c3..41271301215a 100644
--- a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c
+++ b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.c
@@ -195,6 +195,25 @@ int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type,
 	return buf_len;
 }
 
+int quicki2c_output_report(struct quicki2c_device *qcdev, void *buf, size_t buf_len)
+{
+	ssize_t len;
+	int ret;
+
+	len = quicki2c_init_write_buf(qcdev, 0, 0, false, buf, buf_len,
+				      qcdev->report_buf, qcdev->report_len);
+	if (len < 0)
+		return -EINVAL;
+
+	ret = thc_dma_write(qcdev->thc_hw, qcdev->report_buf, len);
+	if (ret) {
+		dev_err(qcdev->dev, "Output Report failed, ret %d\n", ret);
+		return ret;
+	}
+
+	return buf_len;
+}
+
 #define HIDI2C_RESET_TIMEOUT		5
 
 int quicki2c_reset(struct quicki2c_device *qcdev)
diff --git a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.h b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.h
index db70e08c8b1c..6642cefb8a67 100644
--- a/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.h
+++ b/drivers/hid/intel-thc-hid/intel-quicki2c/quicki2c-protocol.h
@@ -13,6 +13,7 @@ int quicki2c_get_report(struct quicki2c_device *qcdev, u8 report_type,
 			unsigned int reportnum, void *buf, size_t buf_len);
 int quicki2c_set_report(struct quicki2c_device *qcdev, u8 report_type,
 			unsigned int reportnum, void *buf, size_t buf_len);
+int quicki2c_output_report(struct quicki2c_device *qcdev, void *buf, size_t buf_len);
 int quicki2c_get_device_descriptor(struct quicki2c_device *qcdev);
 int quicki2c_get_report_descriptor(struct quicki2c_device *qcdev);
 int quicki2c_reset(struct quicki2c_device *qcdev);
-- 
2.40.1


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).