From quic_msavaliy at quicinc.com  Mon Dec  2 22:49:59 2024
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Tue, 3 Dec 2024 12:19:59 +0530
Subject: [PATCH] i3c: dw: Fix use-after-free in dw_i3c_master driver due
 to race condition
In-Reply-To: <bfc49c9527be5b513e7ceafeba314ca40a5be4bc.1732703537.git.xiaopei01@kylinos.cn>
References: <bfc49c9527be5b513e7ceafeba314ca40a5be4bc.1732703537.git.xiaopei01@kylinos.cn>
Message-ID: <2cc88393-d051-4626-87b7-1ea6c532ae61@quicinc.com>



On 11/28/2024 7:29 AM, Pei Xiao wrote:
> In dw_i3c_common_probe, &master->hj_work is bound with
> dw_i3c_hj_work. And dw_i3c_master_irq_handler can call
> dw_i3c_master_irq_handle_ibis function to start the work.
> 
> If we remove the module which will call dw_i3c_common_remove to
> make cleanup, it will free master->base through i3c_master_unregister
> while the work mentioned above will be used. The sequence of operations
> that may lead to a UAF bug is as follows:
> 
> CPU0                                      CPU1
> 
>                                       | dw_i3c_hj_work
> dw_i3c_common_remove                 |
> i3c_master_unregister(&master->base) |
> device_unregister(&master->dev)      |
> device_release                       |
> //free master->base                  |
>                                       | i3c_master_do_daa(&master->base)
>                                       | //use master->base
> 
> Fix it by ensuring that the work is canceled before proceeding with
> the cleanup in dw_i3c_common_remove.
> 
> Fixes: 1dd728f5d4d4 ("i3c: master: Add driver for Synopsys DesignWare IP")
> Signed-off-by: Pei Xiao <xiaopei01 at kylinos.cn>
> ---
>   drivers/i3c/master/dw-i3c-master.c | 1 +
>   1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
> index 8d694672c110..dbcd3984f257 100644
> --- a/drivers/i3c/master/dw-i3c-master.c
> +++ b/drivers/i3c/master/dw-i3c-master.c
> @@ -1624,6 +1624,7 @@ EXPORT_SYMBOL_GPL(dw_i3c_common_probe);
>   
>   void dw_i3c_common_remove(struct dw_i3c_master *master)
>   {
> +	cancel_work_sync(&master->hj_work);
You still need to capture return and ensure that the pending work is 
really completed or no more pending.
>   	i3c_master_unregister(&master->base);
>   
>   	pm_runtime_disable(master->dev);



From xiaopei01 at kylinos.cn  Mon Dec  2 23:05:56 2024
From: xiaopei01 at kylinos.cn (Pei Xiao)
Date: Tue, 3 Dec 2024 15:05:56 +0800
Subject: [PATCH] i3c: dw: Fix use-after-free in dw_i3c_master driver due
 to race condition
In-Reply-To: <2cc88393-d051-4626-87b7-1ea6c532ae61@quicinc.com>
References: <bfc49c9527be5b513e7ceafeba314ca40a5be4bc.1732703537.git.xiaopei01@kylinos.cn>
 <2cc88393-d051-4626-87b7-1ea6c532ae61@quicinc.com>
Message-ID: <15edf6df-3b13-4c72-a9c8-7c87d8578c4d@kylinos.cn>

Hi,
   I don't thinks so.Here is a description of cancel_work_sync.
   *work is guaranteed to be not pending or executing on any CPU*.


cancel_work_sync ? cancel a work and wait for it to finish
Synopsis
bool cancel_work_sync (	struct work_struct * work);

Arguments

work

     the work to cancel

Description

Cancel work and wait for its execution to finish. This function can be 
used even if the work re-queues itself or migrates to another workqueue. 
On return from this function, work is guaranteed to be not pending or 
executing on any CPU.

cancel_work_sync(delayed_work->work) must not be used for 
delayed_work's. Use cancel_delayed_work_sync instead.

The caller must ensure that the workqueue on which work was last queued 
can't be destroyed before this function returns.
Return

true if work was pending, false otherwise.

Thanks!
Pei.
? 2024/12/3 14:49, Mukesh Kumar Savaliya ??:
> 
> 
> On 11/28/2024 7:29 AM, Pei Xiao wrote:
>> In dw_i3c_common_probe, &master->hj_work is bound with
>> dw_i3c_hj_work. And dw_i3c_master_irq_handler can call
>> dw_i3c_master_irq_handle_ibis function to start the work.
>>
>> If we remove the module which will call dw_i3c_common_remove to
>> make cleanup, it will free master->base through i3c_master_unregister
>> while the work mentioned above will be used. The sequence of operations
>> that may lead to a UAF bug is as follows:
>>
>> CPU0????????????????????????????????????? CPU1
>>
>> ????????????????????????????????????? | dw_i3c_hj_work
>> dw_i3c_common_remove???????????????? |
>> i3c_master_unregister(&master->base) |
>> device_unregister(&master->dev)????? |
>> device_release?????????????????????? |
>> //free master->base????????????????? |
>> ????????????????????????????????????? | i3c_master_do_daa(&master->base)
>> ????????????????????????????????????? | //use master->base
>>
>> Fix it by ensuring that the work is canceled before proceeding with
>> the cleanup in dw_i3c_common_remove.
>>
>> Fixes: 1dd728f5d4d4 ("i3c: master: Add driver for Synopsys DesignWare 
>> IP")
>> Signed-off-by: Pei Xiao <xiaopei01 at kylinos.cn>
>> ---
>> ? drivers/i3c/master/dw-i3c-master.c | 1 +
>> ? 1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/i3c/master/dw-i3c-master.c 
>> b/drivers/i3c/master/dw-i3c-master.c
>> index 8d694672c110..dbcd3984f257 100644
>> --- a/drivers/i3c/master/dw-i3c-master.c
>> +++ b/drivers/i3c/master/dw-i3c-master.c
>> @@ -1624,6 +1624,7 @@ EXPORT_SYMBOL_GPL(dw_i3c_common_probe);
>> ? void dw_i3c_common_remove(struct dw_i3c_master *master)
>> ? {
>> +??? cancel_work_sync(&master->hj_work);
> You still need to capture return and ensure that the pending work is 
> really completed or no more pending.
>> ????? i3c_master_unregister(&master->base);
>> ????? pm_runtime_disable(master->dev);
> 
> 


From quic_msavaliy at quicinc.com  Mon Dec  2 23:12:20 2024
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Tue, 3 Dec 2024 12:42:20 +0530
Subject: [PATCH] i3c: dw: Fix use-after-free in dw_i3c_master driver due
 to race condition
In-Reply-To: <15edf6df-3b13-4c72-a9c8-7c87d8578c4d@kylinos.cn>
References: <bfc49c9527be5b513e7ceafeba314ca40a5be4bc.1732703537.git.xiaopei01@kylinos.cn>
 <2cc88393-d051-4626-87b7-1ea6c532ae61@quicinc.com>
 <15edf6df-3b13-4c72-a9c8-7c87d8578c4d@kylinos.cn>
Message-ID: <1d5e7370-3913-416c-80f9-0e8ce459d761@quicinc.com>

Hi Pei, Please Don't top post the comment.

On 12/3/2024 12:35 PM, Pei Xiao wrote:
> Hi,
>  ? I don't thinks so.Here is a description of cancel_work_sync.
>  ? *work is guaranteed to be not pending or executing on any CPU*.
> 
> 
> cancel_work_sync ? cancel a work and wait for it to finish
> Synopsis
> bool cancel_work_sync (??? struct work_struct * work);
> 
> Arguments
> 
> work
> 
>  ??? the work to cancel
> 
> Description
> 
> Cancel work and wait for its execution to finish. This function can be 
> used even if the work re-queues itself or migrates to another workqueue. 
> On return from this function, work is guaranteed to be not pending or 
> executing on any CPU.
> 
> cancel_work_sync(delayed_work->work) must not be used for 
> delayed_work's. Use cancel_delayed_work_sync instead.
> 
> The caller must ensure that the workqueue on which work was last queued 
> can't be destroyed before this function returns.
> Return
> 
> true if work was pending, false otherwise.
> 
> Thanks!
> Pei.
> ? 2024/12/3 14:49, Mukesh Kumar Savaliya ??:
>>
>>
>> On 11/28/2024 7:29 AM, Pei Xiao wrote:
>>> In dw_i3c_common_probe, &master->hj_work is bound with
>>> dw_i3c_hj_work. And dw_i3c_master_irq_handler can call
>>> dw_i3c_master_irq_handle_ibis function to start the work.
>>>
>>> If we remove the module which will call dw_i3c_common_remove to
>>> make cleanup, it will free master->base through i3c_master_unregister
>>> while the work mentioned above will be used. The sequence of operations
>>> that may lead to a UAF bug is as follows:
>>>
>>> CPU0????????????????????????????????????? CPU1
>>>
>>> ????????????????????????????????????? | dw_i3c_hj_work
>>> dw_i3c_common_remove???????????????? |
>>> i3c_master_unregister(&master->base) |
>>> device_unregister(&master->dev)????? |
>>> device_release?????????????????????? |
>>> //free master->base????????????????? |
>>> ????????????????????????????????????? | i3c_master_do_daa(&master->base)
>>> ????????????????????????????????????? | //use master->base
>>>
>>> Fix it by ensuring that the work is canceled before proceeding with
>>> the cleanup in dw_i3c_common_remove.
>>>
>>> Fixes: 1dd728f5d4d4 ("i3c: master: Add driver for Synopsys DesignWare 
>>> IP")
>>> Signed-off-by: Pei Xiao <xiaopei01 at kylinos.cn>
>>> ---
>>> ? drivers/i3c/master/dw-i3c-master.c | 1 +
>>> ? 1 file changed, 1 insertion(+)
>>>
>>> diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/ 
>>> dw-i3c-master.c
>>> index 8d694672c110..dbcd3984f257 100644
>>> --- a/drivers/i3c/master/dw-i3c-master.c
>>> +++ b/drivers/i3c/master/dw-i3c-master.c
>>> @@ -1624,6 +1624,7 @@ EXPORT_SYMBOL_GPL(dw_i3c_common_probe);
>>> ? void dw_i3c_common_remove(struct dw_i3c_master *master)
>>> ? {
>>> +??? cancel_work_sync(&master->hj_work);
>> You still need to capture return and ensure that the pending work is 
>> really completed or no more pending.
Return : true if work was pending, false otherwise
Would like to capture the return and notify/print ?
>>> ????? i3c_master_unregister(&master->base);
>>> ????? pm_runtime_disable(master->dev);
>>
>>



From xiaopei01 at kylinos.cn  Mon Dec  2 23:23:28 2024
From: xiaopei01 at kylinos.cn (Pei Xiao)
Date: Tue, 3 Dec 2024 15:23:28 +0800
Subject: [PATCH] i3c: dw: Fix use-after-free in dw_i3c_master driver due
 to race condition
In-Reply-To: <1d5e7370-3913-416c-80f9-0e8ce459d761@quicinc.com>
References: <bfc49c9527be5b513e7ceafeba314ca40a5be4bc.1732703537.git.xiaopei01@kylinos.cn>
 <2cc88393-d051-4626-87b7-1ea6c532ae61@quicinc.com>
 <15edf6df-3b13-4c72-a9c8-7c87d8578c4d@kylinos.cn>
 <1d5e7370-3913-416c-80f9-0e8ce459d761@quicinc.com>
Message-ID: <8c20ba3f-d214-428c-a827-7642d85bec87@kylinos.cn>



? 2024/12/3 15:12, Mukesh Kumar Savaliya ??:
> Hi Pei, Please Don't top post the comment.
so sorry for that!
> 
> On 12/3/2024 12:35 PM, Pei Xiao wrote:
>> Hi,
>> ?? I don't thinks so.Here is a description of cancel_work_sync.
>> ?? *work is guaranteed to be not pending or executing on any CPU*.
>>
>>
>> cancel_work_sync ? cancel a work and wait for it to finish
>> Synopsis
>> bool cancel_work_sync (??? struct work_struct * work);
>>
>> Arguments
>>
>> work
>>
>> ???? the work to cancel
>>
>> Description
>>
>> Cancel work and wait for its execution to finish. This function can be 
>> used even if the work re-queues itself or migrates to another 
>> workqueue. On return from this function, work is guaranteed to be not 
>> pending or executing on any CPU.
>>
>> cancel_work_sync(delayed_work->work) must not be used for 
>> delayed_work's. Use cancel_delayed_work_sync instead.
>>
>> The caller must ensure that the workqueue on which work was last 
>> queued can't be destroyed before this function returns.
>> Return
>>
>> true if work was pending, false otherwise.
>>
>> Thanks!
>> Pei.
>> ? 2024/12/3 14:49, Mukesh Kumar Savaliya ??:
>>>
>>>
>>> On 11/28/2024 7:29 AM, Pei Xiao wrote:
>>>> In dw_i3c_common_probe, &master->hj_work is bound with
>>>> dw_i3c_hj_work. And dw_i3c_master_irq_handler can call
>>>> dw_i3c_master_irq_handle_ibis function to start the work.
>>>>
>>>> If we remove the module which will call dw_i3c_common_remove to
>>>> make cleanup, it will free master->base through i3c_master_unregister
>>>> while the work mentioned above will be used. The sequence of operations
>>>> that may lead to a UAF bug is as follows:
>>>>
>>>> CPU0????????????????????????????????????? CPU1
>>>>
>>>> ????????????????????????????????????? | dw_i3c_hj_work
>>>> dw_i3c_common_remove???????????????? |
>>>> i3c_master_unregister(&master->base) |
>>>> device_unregister(&master->dev)????? |
>>>> device_release?????????????????????? |
>>>> //free master->base????????????????? |
>>>> ????????????????????????????????????? | 
>>>> i3c_master_do_daa(&master->base)
>>>> ????????????????????????????????????? | //use master->base
>>>>
>>>> Fix it by ensuring that the work is canceled before proceeding with
>>>> the cleanup in dw_i3c_common_remove.
>>>>
>>>> Fixes: 1dd728f5d4d4 ("i3c: master: Add driver for Synopsys 
>>>> DesignWare IP")
>>>> Signed-off-by: Pei Xiao <xiaopei01 at kylinos.cn>
>>>> ---
>>>> ? drivers/i3c/master/dw-i3c-master.c | 1 +
>>>> ? 1 file changed, 1 insertion(+)
>>>>
>>>> diff --git a/drivers/i3c/master/dw-i3c-master.c 
>>>> b/drivers/i3c/master/ dw-i3c-master.c
>>>> index 8d694672c110..dbcd3984f257 100644
>>>> --- a/drivers/i3c/master/dw-i3c-master.c
>>>> +++ b/drivers/i3c/master/dw-i3c-master.c
>>>> @@ -1624,6 +1624,7 @@ EXPORT_SYMBOL_GPL(dw_i3c_common_probe);
>>>> ? void dw_i3c_common_remove(struct dw_i3c_master *master)
>>>> ? {
>>>> +??? cancel_work_sync(&master->hj_work);
>>> You still need to capture return and ensure that the pending work is 
>>> really completed or no more pending.
> Return : true if work was pending, false otherwise
> Would like to capture the return and notify/print ?
when I grep "cancel_work_sync" -nr driver/,almost no use of this return 
value in driver.

Thanks!
Pei.

>>>> ????? i3c_master_unregister(&master->base);
>>>> ????? pm_runtime_disable(master->dev);
>>>
>>>
> 
> 


From quic_msavaliy at quicinc.com  Mon Dec  2 23:44:46 2024
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Tue, 3 Dec 2024 13:14:46 +0530
Subject: [PATCH] i3c: dw: Fix use-after-free in dw_i3c_master driver due
 to race condition
In-Reply-To: <8c20ba3f-d214-428c-a827-7642d85bec87@kylinos.cn>
References: <bfc49c9527be5b513e7ceafeba314ca40a5be4bc.1732703537.git.xiaopei01@kylinos.cn>
 <2cc88393-d051-4626-87b7-1ea6c532ae61@quicinc.com>
 <15edf6df-3b13-4c72-a9c8-7c87d8578c4d@kylinos.cn>
 <1d5e7370-3913-416c-80f9-0e8ce459d761@quicinc.com>
 <8c20ba3f-d214-428c-a827-7642d85bec87@kylinos.cn>
Message-ID: <4cecd65a-02c4-4a67-b209-0ec90ae02cb1@quicinc.com>

Thanks Pei !

On 12/3/2024 12:53 PM, Pei Xiao wrote:
> 
> 
> ? 2024/12/3 15:12, Mukesh Kumar Savaliya ??:
>> Hi Pei, Please Don't top post the comment.
> so sorry for that!
>>
>> On 12/3/2024 12:35 PM, Pei Xiao wrote:
>>> Hi,
>>> ?? I don't thinks so.Here is a description of cancel_work_sync.
>>> ?? *work is guaranteed to be not pending or executing on any CPU*.
>>>
>>>
>>> cancel_work_sync ? cancel a work and wait for it to finish
>>> Synopsis
>>> bool cancel_work_sync (??? struct work_struct * work);
>>>
>>> Arguments
>>>
>>> work
>>>
>>> ???? the work to cancel
>>>
>>> Description
>>>
>>> Cancel work and wait for its execution to finish. This function can 
>>> be used even if the work re-queues itself or migrates to another 
>>> workqueue. On return from this function, work is guaranteed to be not 
>>> pending or executing on any CPU.
>>>
>>> cancel_work_sync(delayed_work->work) must not be used for 
>>> delayed_work's. Use cancel_delayed_work_sync instead.
>>>
>>> The caller must ensure that the workqueue on which work was last 
>>> queued can't be destroyed before this function returns.
>>> Return
>>>
>>> true if work was pending, false otherwise.
>>>
>>> Thanks!
>>> Pei.
>>> ? 2024/12/3 14:49, Mukesh Kumar Savaliya ??:
>>>>
>>>>
>>>> On 11/28/2024 7:29 AM, Pei Xiao wrote:
>>>>> In dw_i3c_common_probe, &master->hj_work is bound with
>>>>> dw_i3c_hj_work. And dw_i3c_master_irq_handler can call
>>>>> dw_i3c_master_irq_handle_ibis function to start the work.
>>>>>
>>>>> If we remove the module which will call dw_i3c_common_remove to
>>>>> make cleanup, it will free master->base through i3c_master_unregister
>>>>> while the work mentioned above will be used. The sequence of 
>>>>> operations
>>>>> that may lead to a UAF bug is as follows:
>>>>>
>>>>> CPU0????????????????????????????????????? CPU1
>>>>>
>>>>> ????????????????????????????????????? | dw_i3c_hj_work
>>>>> dw_i3c_common_remove???????????????? |
>>>>> i3c_master_unregister(&master->base) |
>>>>> device_unregister(&master->dev)????? |
>>>>> device_release?????????????????????? |
>>>>> //free master->base????????????????? |
>>>>> ????????????????????????????????????? | i3c_master_do_daa(&master- 
>>>>> >base)
>>>>> ????????????????????????????????????? | //use master->base
>>>>>
>>>>> Fix it by ensuring that the work is canceled before proceeding with
>>>>> the cleanup in dw_i3c_common_remove.
>>>>>
>>>>> Fixes: 1dd728f5d4d4 ("i3c: master: Add driver for Synopsys 
>>>>> DesignWare IP")
Acked-by: Mukesh Kumar Savaliya <quic_msavaliy at quicinc.com>
>>>>> Signed-off-by: Pei Xiao <xiaopei01 at kylinos.cn>
>>>>> ---
>>>>> ? drivers/i3c/master/dw-i3c-master.c | 1 +
>>>>> ? 1 file changed, 1 insertion(+)
>>>>>
>>>>> diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/ 
>>>>> master/ dw-i3c-master.c
>>>>> index 8d694672c110..dbcd3984f257 100644
>>>>> --- a/drivers/i3c/master/dw-i3c-master.c
>>>>> +++ b/drivers/i3c/master/dw-i3c-master.c
>>>>> @@ -1624,6 +1624,7 @@ EXPORT_SYMBOL_GPL(dw_i3c_common_probe);
>>>>> ? void dw_i3c_common_remove(struct dw_i3c_master *master)
>>>>> ? {
>>>>> +??? cancel_work_sync(&master->hj_work);
>>>> You still need to capture return and ensure that the pending work is 
>>>> really completed or no more pending.
>> Return : true if work was pending, false otherwise
>> Would like to capture the return and notify/print ?
> when I grep "cancel_work_sync" -nr driver/,almost no use of this return 
> value in driver.
> 
Sure, looks fine to me.
> Thanks!
> Pei.
> 
>>>>> ????? i3c_master_unregister(&master->base);
>>>>> ????? pm_runtime_disable(master->dev);
>>>>
>>>>
>>
>>



From sashal at kernel.org  Wed Dec  4 07:59:51 2024
From: sashal at kernel.org (Sasha Levin)
Date: Wed,  4 Dec 2024 10:59:51 -0500
Subject: [PATCH AUTOSEL 6.12 03/15] i3c: mipi-i3c-hci: Mask ring interrupts before ring stop request
In-Reply-To: <20241204160010.2216008-1-sashal@kernel.org>
References: <20241204160010.2216008-1-sashal@kernel.org>
Message-ID: <20241204160010.2216008-3-sashal@kernel.org>

From: Jarkko Nikula <jarkko.nikula at linux.intel.com>

[ Upstream commit 6ca2738174e4ee44edb2ab2d86ce74f015a0cc32 ]

Bus cleanup path in DMA mode may trigger a RING_OP_STAT interrupt when
the ring is being stopped. Depending on timing between ring stop request
completion, interrupt handler removal and code execution this may lead
to a NULL pointer dereference in hci_dma_irq_handler() if it gets to run
after the io_data pointer is set to NULL in hci_dma_cleanup().

Prevent this my masking the ring interrupts before ring stop request.

Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
Link: https://lore.kernel.org/r/20240920144432.62370-2-jarkko.nikula at linux.intel.com
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/i3c/master/mipi-i3c-hci/dma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
index a918e96b21fdd..13adc58400942 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
@@ -159,10 +159,10 @@ static void hci_dma_cleanup(struct i3c_hci *hci)
 	for (i = 0; i < rings->total; i++) {
 		rh = &rings->headers[i];
 
+		rh_reg_write(INTR_SIGNAL_ENABLE, 0);
 		rh_reg_write(RING_CONTROL, 0);
 		rh_reg_write(CR_SETUP, 0);
 		rh_reg_write(IBI_SETUP, 0);
-		rh_reg_write(INTR_SIGNAL_ENABLE, 0);
 
 		if (rh->xfer)
 			dma_free_coherent(&hci->master.dev,
-- 
2.43.0



From sashal at kernel.org  Wed Dec  4 08:00:00 2024
From: sashal at kernel.org (Sasha Levin)
Date: Wed,  4 Dec 2024 11:00:00 -0500
Subject: [PATCH AUTOSEL 6.12 12/15] i3c: Use i3cdev->desc->info instead of calling i3c_device_get_info() to avoid deadlock
In-Reply-To: <20241204160010.2216008-1-sashal@kernel.org>
References: <20241204160010.2216008-1-sashal@kernel.org>
Message-ID: <20241204160010.2216008-12-sashal@kernel.org>

From: Defa Li <defa.li at mediatek.com>

[ Upstream commit 6cf7b65f7029914dc0cd7db86fac9ee5159008c6 ]

A deadlock may happen since the i3c_master_register() acquires
&i3cbus->lock twice. See the log below.
Use i3cdev->desc->info instead of calling i3c_device_info() to
avoid acquiring the lock twice.

v2:
  - Modified the title and commit message

============================================
WARNING: possible recursive locking detected
6.11.0-mainline
--------------------------------------------
init/1 is trying to acquire lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_bus_normaluse_lock

but task is already holding lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

other info that might help us debug this:
 Possible unsafe locking scenario:

       CPU0
       ----
  lock(&i3cbus->lock);
  lock(&i3cbus->lock);

 *** DEADLOCK ***

 May be due to missing lock nesting notation

2 locks held by init/1:
 #0: fcffff809b6798f8 (&dev->mutex){....}-{3:3}, at: __driver_attach
 #1: f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

stack backtrace:
CPU: 6 UID: 0 PID: 1 Comm: init
Call trace:
 dump_backtrace+0xfc/0x17c
 show_stack+0x18/0x28
 dump_stack_lvl+0x40/0xc0
 dump_stack+0x18/0x24
 print_deadlock_bug+0x388/0x390
 __lock_acquire+0x18bc/0x32ec
 lock_acquire+0x134/0x2b0
 down_read+0x50/0x19c
 i3c_bus_normaluse_lock+0x14/0x24
 i3c_device_get_info+0x24/0x58
 i3c_device_uevent+0x34/0xa4
 dev_uevent+0x310/0x384
 kobject_uevent_env+0x244/0x414
 kobject_uevent+0x14/0x20
 device_add+0x278/0x460
 device_register+0x20/0x34
 i3c_master_register_new_i3c_devs+0x78/0x154
 i3c_master_register+0x6a0/0x6d4
 mtk_i3c_master_probe+0x3b8/0x4d8
 platform_probe+0xa0/0xe0
 really_probe+0x114/0x454
 __driver_probe_device+0xa0/0x15c
 driver_probe_device+0x3c/0x1ac
 __driver_attach+0xc4/0x1f0
 bus_for_each_dev+0x104/0x160
 driver_attach+0x24/0x34
 bus_add_driver+0x14c/0x294
 driver_register+0x68/0x104
 __platform_driver_register+0x20/0x30
 init_module+0x20/0xfe4
 do_one_initcall+0x184/0x464
 do_init_module+0x58/0x1ec
 load_module+0xefc/0x10c8
 __arm64_sys_finit_module+0x238/0x33c
 invoke_syscall+0x58/0x10c
 el0_svc_common+0xa8/0xdc
 do_el0_svc+0x1c/0x28
 el0_svc+0x50/0xac
 el0t_64_sync_handler+0x70/0xbc
 el0t_64_sync+0x1a8/0x1ac

Signed-off-by: Defa Li <defa.li at mediatek.com>
Link: https://lore.kernel.org/r/20241107132549.25439-1-defa.li at mediatek.com
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/i3c/master.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 6f3eb710a75d6..bb8a8bf0c4c7c 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -282,7 +282,8 @@ static int i3c_device_uevent(const struct device *dev, struct kobj_uevent_env *e
 	struct i3c_device_info devinfo;
 	u16 manuf, part, ext;
 
-	i3c_device_get_info(i3cdev, &devinfo);
+	if (i3cdev->desc)
+		devinfo = i3cdev->desc->info;
 	manuf = I3C_PID_MANUF_ID(devinfo.pid);
 	part = I3C_PID_PART_ID(devinfo.pid);
 	ext = I3C_PID_EXTRA_INFO(devinfo.pid);
-- 
2.43.0



From sashal at kernel.org  Wed Dec  4 08:00:28 2024
From: sashal at kernel.org (Sasha Levin)
Date: Wed,  4 Dec 2024 11:00:28 -0500
Subject: [PATCH AUTOSEL 6.11 03/13] i3c: mipi-i3c-hci: Mask ring interrupts before ring stop request
In-Reply-To: <20241204160044.2216380-1-sashal@kernel.org>
References: <20241204160044.2216380-1-sashal@kernel.org>
Message-ID: <20241204160044.2216380-3-sashal@kernel.org>

From: Jarkko Nikula <jarkko.nikula at linux.intel.com>

[ Upstream commit 6ca2738174e4ee44edb2ab2d86ce74f015a0cc32 ]

Bus cleanup path in DMA mode may trigger a RING_OP_STAT interrupt when
the ring is being stopped. Depending on timing between ring stop request
completion, interrupt handler removal and code execution this may lead
to a NULL pointer dereference in hci_dma_irq_handler() if it gets to run
after the io_data pointer is set to NULL in hci_dma_cleanup().

Prevent this my masking the ring interrupts before ring stop request.

Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
Link: https://lore.kernel.org/r/20240920144432.62370-2-jarkko.nikula at linux.intel.com
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/i3c/master/mipi-i3c-hci/dma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
index a918e96b21fdd..13adc58400942 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
@@ -159,10 +159,10 @@ static void hci_dma_cleanup(struct i3c_hci *hci)
 	for (i = 0; i < rings->total; i++) {
 		rh = &rings->headers[i];
 
+		rh_reg_write(INTR_SIGNAL_ENABLE, 0);
 		rh_reg_write(RING_CONTROL, 0);
 		rh_reg_write(CR_SETUP, 0);
 		rh_reg_write(IBI_SETUP, 0);
-		rh_reg_write(INTR_SIGNAL_ENABLE, 0);
 
 		if (rh->xfer)
 			dma_free_coherent(&hci->master.dev,
-- 
2.43.0



From sashal at kernel.org  Wed Dec  4 08:00:36 2024
From: sashal at kernel.org (Sasha Levin)
Date: Wed,  4 Dec 2024 11:00:36 -0500
Subject: [PATCH AUTOSEL 6.11 11/13] i3c: Use i3cdev->desc->info instead of calling i3c_device_get_info() to avoid deadlock
In-Reply-To: <20241204160044.2216380-1-sashal@kernel.org>
References: <20241204160044.2216380-1-sashal@kernel.org>
Message-ID: <20241204160044.2216380-11-sashal@kernel.org>

From: Defa Li <defa.li at mediatek.com>

[ Upstream commit 6cf7b65f7029914dc0cd7db86fac9ee5159008c6 ]

A deadlock may happen since the i3c_master_register() acquires
&i3cbus->lock twice. See the log below.
Use i3cdev->desc->info instead of calling i3c_device_info() to
avoid acquiring the lock twice.

v2:
  - Modified the title and commit message

============================================
WARNING: possible recursive locking detected
6.11.0-mainline
--------------------------------------------
init/1 is trying to acquire lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_bus_normaluse_lock

but task is already holding lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

other info that might help us debug this:
 Possible unsafe locking scenario:

       CPU0
       ----
  lock(&i3cbus->lock);
  lock(&i3cbus->lock);

 *** DEADLOCK ***

 May be due to missing lock nesting notation

2 locks held by init/1:
 #0: fcffff809b6798f8 (&dev->mutex){....}-{3:3}, at: __driver_attach
 #1: f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

stack backtrace:
CPU: 6 UID: 0 PID: 1 Comm: init
Call trace:
 dump_backtrace+0xfc/0x17c
 show_stack+0x18/0x28
 dump_stack_lvl+0x40/0xc0
 dump_stack+0x18/0x24
 print_deadlock_bug+0x388/0x390
 __lock_acquire+0x18bc/0x32ec
 lock_acquire+0x134/0x2b0
 down_read+0x50/0x19c
 i3c_bus_normaluse_lock+0x14/0x24
 i3c_device_get_info+0x24/0x58
 i3c_device_uevent+0x34/0xa4
 dev_uevent+0x310/0x384
 kobject_uevent_env+0x244/0x414
 kobject_uevent+0x14/0x20
 device_add+0x278/0x460
 device_register+0x20/0x34
 i3c_master_register_new_i3c_devs+0x78/0x154
 i3c_master_register+0x6a0/0x6d4
 mtk_i3c_master_probe+0x3b8/0x4d8
 platform_probe+0xa0/0xe0
 really_probe+0x114/0x454
 __driver_probe_device+0xa0/0x15c
 driver_probe_device+0x3c/0x1ac
 __driver_attach+0xc4/0x1f0
 bus_for_each_dev+0x104/0x160
 driver_attach+0x24/0x34
 bus_add_driver+0x14c/0x294
 driver_register+0x68/0x104
 __platform_driver_register+0x20/0x30
 init_module+0x20/0xfe4
 do_one_initcall+0x184/0x464
 do_init_module+0x58/0x1ec
 load_module+0xefc/0x10c8
 __arm64_sys_finit_module+0x238/0x33c
 invoke_syscall+0x58/0x10c
 el0_svc_common+0xa8/0xdc
 do_el0_svc+0x1c/0x28
 el0_svc+0x50/0xac
 el0t_64_sync_handler+0x70/0xbc
 el0t_64_sync+0x1a8/0x1ac

Signed-off-by: Defa Li <defa.li at mediatek.com>
Link: https://lore.kernel.org/r/20241107132549.25439-1-defa.li at mediatek.com
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/i3c/master.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 7028f03c2c42e..5e3b63f78d2d2 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -282,7 +282,8 @@ static int i3c_device_uevent(const struct device *dev, struct kobj_uevent_env *e
 	struct i3c_device_info devinfo;
 	u16 manuf, part, ext;
 
-	i3c_device_get_info(i3cdev, &devinfo);
+	if (i3cdev->desc)
+		devinfo = i3cdev->desc->info;
 	manuf = I3C_PID_MANUF_ID(devinfo.pid);
 	part = I3C_PID_PART_ID(devinfo.pid);
 	ext = I3C_PID_EXTRA_INFO(devinfo.pid);
-- 
2.43.0



From sashal at kernel.org  Wed Dec  4 08:01:00 2024
From: sashal at kernel.org (Sasha Levin)
Date: Wed,  4 Dec 2024 11:01:00 -0500
Subject: [PATCH AUTOSEL 6.6 03/12] i3c: mipi-i3c-hci: Mask ring interrupts before ring stop request
In-Reply-To: <20241204160115.2216718-1-sashal@kernel.org>
References: <20241204160115.2216718-1-sashal@kernel.org>
Message-ID: <20241204160115.2216718-3-sashal@kernel.org>

From: Jarkko Nikula <jarkko.nikula at linux.intel.com>

[ Upstream commit 6ca2738174e4ee44edb2ab2d86ce74f015a0cc32 ]

Bus cleanup path in DMA mode may trigger a RING_OP_STAT interrupt when
the ring is being stopped. Depending on timing between ring stop request
completion, interrupt handler removal and code execution this may lead
to a NULL pointer dereference in hci_dma_irq_handler() if it gets to run
after the io_data pointer is set to NULL in hci_dma_cleanup().

Prevent this my masking the ring interrupts before ring stop request.

Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
Link: https://lore.kernel.org/r/20240920144432.62370-2-jarkko.nikula at linux.intel.com
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/i3c/master/mipi-i3c-hci/dma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
index edc3a69bfe31f..bcc0c7d4131f2 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
@@ -174,10 +174,10 @@ static void hci_dma_cleanup(struct i3c_hci *hci)
 	for (i = 0; i < rings->total; i++) {
 		rh = &rings->headers[i];
 
+		rh_reg_write(INTR_SIGNAL_ENABLE, 0);
 		rh_reg_write(RING_CONTROL, 0);
 		rh_reg_write(CR_SETUP, 0);
 		rh_reg_write(IBI_SETUP, 0);
-		rh_reg_write(INTR_SIGNAL_ENABLE, 0);
 
 		if (rh->xfer)
 			dma_free_coherent(&hci->master.dev,
-- 
2.43.0



From sashal at kernel.org  Wed Dec  4 08:01:07 2024
From: sashal at kernel.org (Sasha Levin)
Date: Wed,  4 Dec 2024 11:01:07 -0500
Subject: [PATCH AUTOSEL 6.6 10/12] i3c: Use i3cdev->desc->info instead of calling i3c_device_get_info() to avoid deadlock
In-Reply-To: <20241204160115.2216718-1-sashal@kernel.org>
References: <20241204160115.2216718-1-sashal@kernel.org>
Message-ID: <20241204160115.2216718-10-sashal@kernel.org>

From: Defa Li <defa.li at mediatek.com>

[ Upstream commit 6cf7b65f7029914dc0cd7db86fac9ee5159008c6 ]

A deadlock may happen since the i3c_master_register() acquires
&i3cbus->lock twice. See the log below.
Use i3cdev->desc->info instead of calling i3c_device_info() to
avoid acquiring the lock twice.

v2:
  - Modified the title and commit message

============================================
WARNING: possible recursive locking detected
6.11.0-mainline
--------------------------------------------
init/1 is trying to acquire lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_bus_normaluse_lock

but task is already holding lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

other info that might help us debug this:
 Possible unsafe locking scenario:

       CPU0
       ----
  lock(&i3cbus->lock);
  lock(&i3cbus->lock);

 *** DEADLOCK ***

 May be due to missing lock nesting notation

2 locks held by init/1:
 #0: fcffff809b6798f8 (&dev->mutex){....}-{3:3}, at: __driver_attach
 #1: f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

stack backtrace:
CPU: 6 UID: 0 PID: 1 Comm: init
Call trace:
 dump_backtrace+0xfc/0x17c
 show_stack+0x18/0x28
 dump_stack_lvl+0x40/0xc0
 dump_stack+0x18/0x24
 print_deadlock_bug+0x388/0x390
 __lock_acquire+0x18bc/0x32ec
 lock_acquire+0x134/0x2b0
 down_read+0x50/0x19c
 i3c_bus_normaluse_lock+0x14/0x24
 i3c_device_get_info+0x24/0x58
 i3c_device_uevent+0x34/0xa4
 dev_uevent+0x310/0x384
 kobject_uevent_env+0x244/0x414
 kobject_uevent+0x14/0x20
 device_add+0x278/0x460
 device_register+0x20/0x34
 i3c_master_register_new_i3c_devs+0x78/0x154
 i3c_master_register+0x6a0/0x6d4
 mtk_i3c_master_probe+0x3b8/0x4d8
 platform_probe+0xa0/0xe0
 really_probe+0x114/0x454
 __driver_probe_device+0xa0/0x15c
 driver_probe_device+0x3c/0x1ac
 __driver_attach+0xc4/0x1f0
 bus_for_each_dev+0x104/0x160
 driver_attach+0x24/0x34
 bus_add_driver+0x14c/0x294
 driver_register+0x68/0x104
 __platform_driver_register+0x20/0x30
 init_module+0x20/0xfe4
 do_one_initcall+0x184/0x464
 do_init_module+0x58/0x1ec
 load_module+0xefc/0x10c8
 __arm64_sys_finit_module+0x238/0x33c
 invoke_syscall+0x58/0x10c
 el0_svc_common+0xa8/0xdc
 do_el0_svc+0x1c/0x28
 el0_svc+0x50/0xac
 el0t_64_sync_handler+0x70/0xbc
 el0t_64_sync+0x1a8/0x1ac

Signed-off-by: Defa Li <defa.li at mediatek.com>
Link: https://lore.kernel.org/r/20241107132549.25439-1-defa.li at mediatek.com
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/i3c/master.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 0e9ff5500a777..d66ff7a98c71d 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -280,7 +280,8 @@ static int i3c_device_uevent(const struct device *dev, struct kobj_uevent_env *e
 	struct i3c_device_info devinfo;
 	u16 manuf, part, ext;
 
-	i3c_device_get_info(i3cdev, &devinfo);
+	if (i3cdev->desc)
+		devinfo = i3cdev->desc->info;
 	manuf = I3C_PID_MANUF_ID(devinfo.pid);
 	part = I3C_PID_PART_ID(devinfo.pid);
 	ext = I3C_PID_EXTRA_INFO(devinfo.pid);
-- 
2.43.0



From sashal at kernel.org  Wed Dec  4 08:01:34 2024
From: sashal at kernel.org (Sasha Levin)
Date: Wed,  4 Dec 2024 11:01:34 -0500
Subject: [PATCH AUTOSEL 6.1 2/6] i3c: mipi-i3c-hci: Mask ring interrupts before ring stop request
In-Reply-To: <20241204160142.2217017-1-sashal@kernel.org>
References: <20241204160142.2217017-1-sashal@kernel.org>
Message-ID: <20241204160142.2217017-2-sashal@kernel.org>

From: Jarkko Nikula <jarkko.nikula at linux.intel.com>

[ Upstream commit 6ca2738174e4ee44edb2ab2d86ce74f015a0cc32 ]

Bus cleanup path in DMA mode may trigger a RING_OP_STAT interrupt when
the ring is being stopped. Depending on timing between ring stop request
completion, interrupt handler removal and code execution this may lead
to a NULL pointer dereference in hci_dma_irq_handler() if it gets to run
after the io_data pointer is set to NULL in hci_dma_cleanup().

Prevent this my masking the ring interrupts before ring stop request.

Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
Link: https://lore.kernel.org/r/20240920144432.62370-2-jarkko.nikula at linux.intel.com
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/i3c/master/mipi-i3c-hci/dma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
index edc3a69bfe31f..bcc0c7d4131f2 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
@@ -174,10 +174,10 @@ static void hci_dma_cleanup(struct i3c_hci *hci)
 	for (i = 0; i < rings->total; i++) {
 		rh = &rings->headers[i];
 
+		rh_reg_write(INTR_SIGNAL_ENABLE, 0);
 		rh_reg_write(RING_CONTROL, 0);
 		rh_reg_write(CR_SETUP, 0);
 		rh_reg_write(IBI_SETUP, 0);
-		rh_reg_write(INTR_SIGNAL_ENABLE, 0);
 
 		if (rh->xfer)
 			dma_free_coherent(&hci->master.dev,
-- 
2.43.0



From sashal at kernel.org  Wed Dec  4 08:01:38 2024
From: sashal at kernel.org (Sasha Levin)
Date: Wed,  4 Dec 2024 11:01:38 -0500
Subject: [PATCH AUTOSEL 6.1 6/6] i3c: Use i3cdev->desc->info instead of calling i3c_device_get_info() to avoid deadlock
In-Reply-To: <20241204160142.2217017-1-sashal@kernel.org>
References: <20241204160142.2217017-1-sashal@kernel.org>
Message-ID: <20241204160142.2217017-6-sashal@kernel.org>

From: Defa Li <defa.li at mediatek.com>

[ Upstream commit 6cf7b65f7029914dc0cd7db86fac9ee5159008c6 ]

A deadlock may happen since the i3c_master_register() acquires
&i3cbus->lock twice. See the log below.
Use i3cdev->desc->info instead of calling i3c_device_info() to
avoid acquiring the lock twice.

v2:
  - Modified the title and commit message

============================================
WARNING: possible recursive locking detected
6.11.0-mainline
--------------------------------------------
init/1 is trying to acquire lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_bus_normaluse_lock

but task is already holding lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

other info that might help us debug this:
 Possible unsafe locking scenario:

       CPU0
       ----
  lock(&i3cbus->lock);
  lock(&i3cbus->lock);

 *** DEADLOCK ***

 May be due to missing lock nesting notation

2 locks held by init/1:
 #0: fcffff809b6798f8 (&dev->mutex){....}-{3:3}, at: __driver_attach
 #1: f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

stack backtrace:
CPU: 6 UID: 0 PID: 1 Comm: init
Call trace:
 dump_backtrace+0xfc/0x17c
 show_stack+0x18/0x28
 dump_stack_lvl+0x40/0xc0
 dump_stack+0x18/0x24
 print_deadlock_bug+0x388/0x390
 __lock_acquire+0x18bc/0x32ec
 lock_acquire+0x134/0x2b0
 down_read+0x50/0x19c
 i3c_bus_normaluse_lock+0x14/0x24
 i3c_device_get_info+0x24/0x58
 i3c_device_uevent+0x34/0xa4
 dev_uevent+0x310/0x384
 kobject_uevent_env+0x244/0x414
 kobject_uevent+0x14/0x20
 device_add+0x278/0x460
 device_register+0x20/0x34
 i3c_master_register_new_i3c_devs+0x78/0x154
 i3c_master_register+0x6a0/0x6d4
 mtk_i3c_master_probe+0x3b8/0x4d8
 platform_probe+0xa0/0xe0
 really_probe+0x114/0x454
 __driver_probe_device+0xa0/0x15c
 driver_probe_device+0x3c/0x1ac
 __driver_attach+0xc4/0x1f0
 bus_for_each_dev+0x104/0x160
 driver_attach+0x24/0x34
 bus_add_driver+0x14c/0x294
 driver_register+0x68/0x104
 __platform_driver_register+0x20/0x30
 init_module+0x20/0xfe4
 do_one_initcall+0x184/0x464
 do_init_module+0x58/0x1ec
 load_module+0xefc/0x10c8
 __arm64_sys_finit_module+0x238/0x33c
 invoke_syscall+0x58/0x10c
 el0_svc_common+0xa8/0xdc
 do_el0_svc+0x1c/0x28
 el0_svc+0x50/0xac
 el0t_64_sync_handler+0x70/0xbc
 el0t_64_sync+0x1a8/0x1ac

Signed-off-by: Defa Li <defa.li at mediatek.com>
Link: https://lore.kernel.org/r/20241107132549.25439-1-defa.li at mediatek.com
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/i3c/master.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index ab0b5691b03e0..ac97bf9c55c39 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -279,7 +279,8 @@ static int i3c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 	struct i3c_device_info devinfo;
 	u16 manuf, part, ext;
 
-	i3c_device_get_info(i3cdev, &devinfo);
+	if (i3cdev->desc)
+		devinfo = i3cdev->desc->info;
 	manuf = I3C_PID_MANUF_ID(devinfo.pid);
 	part = I3C_PID_PART_ID(devinfo.pid);
 	ext = I3C_PID_EXTRA_INFO(devinfo.pid);
-- 
2.43.0



From sashal at kernel.org  Wed Dec  4 08:01:52 2024
From: sashal at kernel.org (Sasha Levin)
Date: Wed,  4 Dec 2024 11:01:52 -0500
Subject: [PATCH AUTOSEL 5.15 2/6] i3c: mipi-i3c-hci: Mask ring interrupts before ring stop request
In-Reply-To: <20241204160200.2217169-1-sashal@kernel.org>
References: <20241204160200.2217169-1-sashal@kernel.org>
Message-ID: <20241204160200.2217169-2-sashal@kernel.org>

From: Jarkko Nikula <jarkko.nikula at linux.intel.com>

[ Upstream commit 6ca2738174e4ee44edb2ab2d86ce74f015a0cc32 ]

Bus cleanup path in DMA mode may trigger a RING_OP_STAT interrupt when
the ring is being stopped. Depending on timing between ring stop request
completion, interrupt handler removal and code execution this may lead
to a NULL pointer dereference in hci_dma_irq_handler() if it gets to run
after the io_data pointer is set to NULL in hci_dma_cleanup().

Prevent this my masking the ring interrupts before ring stop request.

Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
Link: https://lore.kernel.org/r/20240920144432.62370-2-jarkko.nikula at linux.intel.com
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/i3c/master/mipi-i3c-hci/dma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
index b9b6be1864384..61a5abac50dc0 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
@@ -174,10 +174,10 @@ static void hci_dma_cleanup(struct i3c_hci *hci)
 	for (i = 0; i < rings->total; i++) {
 		rh = &rings->headers[i];
 
+		rh_reg_write(INTR_SIGNAL_ENABLE, 0);
 		rh_reg_write(RING_CONTROL, 0);
 		rh_reg_write(CR_SETUP, 0);
 		rh_reg_write(IBI_SETUP, 0);
-		rh_reg_write(INTR_SIGNAL_ENABLE, 0);
 
 		if (rh->xfer)
 			dma_free_coherent(&hci->master.dev,
-- 
2.43.0



From sashal at kernel.org  Wed Dec  4 08:01:56 2024
From: sashal at kernel.org (Sasha Levin)
Date: Wed,  4 Dec 2024 11:01:56 -0500
Subject: [PATCH AUTOSEL 5.15 6/6] i3c: Use i3cdev->desc->info instead of calling i3c_device_get_info() to avoid deadlock
In-Reply-To: <20241204160200.2217169-1-sashal@kernel.org>
References: <20241204160200.2217169-1-sashal@kernel.org>
Message-ID: <20241204160200.2217169-6-sashal@kernel.org>

From: Defa Li <defa.li at mediatek.com>

[ Upstream commit 6cf7b65f7029914dc0cd7db86fac9ee5159008c6 ]

A deadlock may happen since the i3c_master_register() acquires
&i3cbus->lock twice. See the log below.
Use i3cdev->desc->info instead of calling i3c_device_info() to
avoid acquiring the lock twice.

v2:
  - Modified the title and commit message

============================================
WARNING: possible recursive locking detected
6.11.0-mainline
--------------------------------------------
init/1 is trying to acquire lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_bus_normaluse_lock

but task is already holding lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

other info that might help us debug this:
 Possible unsafe locking scenario:

       CPU0
       ----
  lock(&i3cbus->lock);
  lock(&i3cbus->lock);

 *** DEADLOCK ***

 May be due to missing lock nesting notation

2 locks held by init/1:
 #0: fcffff809b6798f8 (&dev->mutex){....}-{3:3}, at: __driver_attach
 #1: f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

stack backtrace:
CPU: 6 UID: 0 PID: 1 Comm: init
Call trace:
 dump_backtrace+0xfc/0x17c
 show_stack+0x18/0x28
 dump_stack_lvl+0x40/0xc0
 dump_stack+0x18/0x24
 print_deadlock_bug+0x388/0x390
 __lock_acquire+0x18bc/0x32ec
 lock_acquire+0x134/0x2b0
 down_read+0x50/0x19c
 i3c_bus_normaluse_lock+0x14/0x24
 i3c_device_get_info+0x24/0x58
 i3c_device_uevent+0x34/0xa4
 dev_uevent+0x310/0x384
 kobject_uevent_env+0x244/0x414
 kobject_uevent+0x14/0x20
 device_add+0x278/0x460
 device_register+0x20/0x34
 i3c_master_register_new_i3c_devs+0x78/0x154
 i3c_master_register+0x6a0/0x6d4
 mtk_i3c_master_probe+0x3b8/0x4d8
 platform_probe+0xa0/0xe0
 really_probe+0x114/0x454
 __driver_probe_device+0xa0/0x15c
 driver_probe_device+0x3c/0x1ac
 __driver_attach+0xc4/0x1f0
 bus_for_each_dev+0x104/0x160
 driver_attach+0x24/0x34
 bus_add_driver+0x14c/0x294
 driver_register+0x68/0x104
 __platform_driver_register+0x20/0x30
 init_module+0x20/0xfe4
 do_one_initcall+0x184/0x464
 do_init_module+0x58/0x1ec
 load_module+0xefc/0x10c8
 __arm64_sys_finit_module+0x238/0x33c
 invoke_syscall+0x58/0x10c
 el0_svc_common+0xa8/0xdc
 do_el0_svc+0x1c/0x28
 el0_svc+0x50/0xac
 el0t_64_sync_handler+0x70/0xbc
 el0t_64_sync+0x1a8/0x1ac

Signed-off-by: Defa Li <defa.li at mediatek.com>
Link: https://lore.kernel.org/r/20241107132549.25439-1-defa.li at mediatek.com
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/i3c/master.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index b6abbb0acbbd3..c4663501a971c 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -279,7 +279,8 @@ static int i3c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 	struct i3c_device_info devinfo;
 	u16 manuf, part, ext;
 
-	i3c_device_get_info(i3cdev, &devinfo);
+	if (i3cdev->desc)
+		devinfo = i3cdev->desc->info;
 	manuf = I3C_PID_MANUF_ID(devinfo.pid);
 	part = I3C_PID_PART_ID(devinfo.pid);
 	ext = I3C_PID_EXTRA_INFO(devinfo.pid);
-- 
2.43.0



From sashal at kernel.org  Wed Dec  4 08:02:14 2024
From: sashal at kernel.org (Sasha Levin)
Date: Wed,  4 Dec 2024 11:02:14 -0500
Subject: [PATCH AUTOSEL 5.10 4/4] i3c: Use i3cdev->desc->info instead of calling i3c_device_get_info() to avoid deadlock
In-Reply-To: <20241204160216.2217323-1-sashal@kernel.org>
References: <20241204160216.2217323-1-sashal@kernel.org>
Message-ID: <20241204160216.2217323-4-sashal@kernel.org>

From: Defa Li <defa.li at mediatek.com>

[ Upstream commit 6cf7b65f7029914dc0cd7db86fac9ee5159008c6 ]

A deadlock may happen since the i3c_master_register() acquires
&i3cbus->lock twice. See the log below.
Use i3cdev->desc->info instead of calling i3c_device_info() to
avoid acquiring the lock twice.

v2:
  - Modified the title and commit message

============================================
WARNING: possible recursive locking detected
6.11.0-mainline
--------------------------------------------
init/1 is trying to acquire lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_bus_normaluse_lock

but task is already holding lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

other info that might help us debug this:
 Possible unsafe locking scenario:

       CPU0
       ----
  lock(&i3cbus->lock);
  lock(&i3cbus->lock);

 *** DEADLOCK ***

 May be due to missing lock nesting notation

2 locks held by init/1:
 #0: fcffff809b6798f8 (&dev->mutex){....}-{3:3}, at: __driver_attach
 #1: f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

stack backtrace:
CPU: 6 UID: 0 PID: 1 Comm: init
Call trace:
 dump_backtrace+0xfc/0x17c
 show_stack+0x18/0x28
 dump_stack_lvl+0x40/0xc0
 dump_stack+0x18/0x24
 print_deadlock_bug+0x388/0x390
 __lock_acquire+0x18bc/0x32ec
 lock_acquire+0x134/0x2b0
 down_read+0x50/0x19c
 i3c_bus_normaluse_lock+0x14/0x24
 i3c_device_get_info+0x24/0x58
 i3c_device_uevent+0x34/0xa4
 dev_uevent+0x310/0x384
 kobject_uevent_env+0x244/0x414
 kobject_uevent+0x14/0x20
 device_add+0x278/0x460
 device_register+0x20/0x34
 i3c_master_register_new_i3c_devs+0x78/0x154
 i3c_master_register+0x6a0/0x6d4
 mtk_i3c_master_probe+0x3b8/0x4d8
 platform_probe+0xa0/0xe0
 really_probe+0x114/0x454
 __driver_probe_device+0xa0/0x15c
 driver_probe_device+0x3c/0x1ac
 __driver_attach+0xc4/0x1f0
 bus_for_each_dev+0x104/0x160
 driver_attach+0x24/0x34
 bus_add_driver+0x14c/0x294
 driver_register+0x68/0x104
 __platform_driver_register+0x20/0x30
 init_module+0x20/0xfe4
 do_one_initcall+0x184/0x464
 do_init_module+0x58/0x1ec
 load_module+0xefc/0x10c8
 __arm64_sys_finit_module+0x238/0x33c
 invoke_syscall+0x58/0x10c
 el0_svc_common+0xa8/0xdc
 do_el0_svc+0x1c/0x28
 el0_svc+0x50/0xac
 el0t_64_sync_handler+0x70/0xbc
 el0t_64_sync+0x1a8/0x1ac

Signed-off-by: Defa Li <defa.li at mediatek.com>
Link: https://lore.kernel.org/r/20241107132549.25439-1-defa.li at mediatek.com
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/i3c/master.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 828fb236a63ae..525f789b0f86c 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -279,7 +279,8 @@ static int i3c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 	struct i3c_device_info devinfo;
 	u16 manuf, part, ext;
 
-	i3c_device_get_info(i3cdev, &devinfo);
+	if (i3cdev->desc)
+		devinfo = i3cdev->desc->info;
 	manuf = I3C_PID_MANUF_ID(devinfo.pid);
 	part = I3C_PID_PART_ID(devinfo.pid);
 	ext = I3C_PID_EXTRA_INFO(devinfo.pid);
-- 
2.43.0



From sashal at kernel.org  Wed Dec  4 08:02:25 2024
From: sashal at kernel.org (Sasha Levin)
Date: Wed,  4 Dec 2024 11:02:25 -0500
Subject: [PATCH AUTOSEL 5.4 4/4] i3c: Use i3cdev->desc->info instead of calling i3c_device_get_info() to avoid deadlock
In-Reply-To: <20241204160227.2217428-1-sashal@kernel.org>
References: <20241204160227.2217428-1-sashal@kernel.org>
Message-ID: <20241204160227.2217428-4-sashal@kernel.org>

From: Defa Li <defa.li at mediatek.com>

[ Upstream commit 6cf7b65f7029914dc0cd7db86fac9ee5159008c6 ]

A deadlock may happen since the i3c_master_register() acquires
&i3cbus->lock twice. See the log below.
Use i3cdev->desc->info instead of calling i3c_device_info() to
avoid acquiring the lock twice.

v2:
  - Modified the title and commit message

============================================
WARNING: possible recursive locking detected
6.11.0-mainline
--------------------------------------------
init/1 is trying to acquire lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_bus_normaluse_lock

but task is already holding lock:
f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

other info that might help us debug this:
 Possible unsafe locking scenario:

       CPU0
       ----
  lock(&i3cbus->lock);
  lock(&i3cbus->lock);

 *** DEADLOCK ***

 May be due to missing lock nesting notation

2 locks held by init/1:
 #0: fcffff809b6798f8 (&dev->mutex){....}-{3:3}, at: __driver_attach
 #1: f1ffff80a6a40dc0 (&i3cbus->lock){++++}-{3:3}, at: i3c_master_register

stack backtrace:
CPU: 6 UID: 0 PID: 1 Comm: init
Call trace:
 dump_backtrace+0xfc/0x17c
 show_stack+0x18/0x28
 dump_stack_lvl+0x40/0xc0
 dump_stack+0x18/0x24
 print_deadlock_bug+0x388/0x390
 __lock_acquire+0x18bc/0x32ec
 lock_acquire+0x134/0x2b0
 down_read+0x50/0x19c
 i3c_bus_normaluse_lock+0x14/0x24
 i3c_device_get_info+0x24/0x58
 i3c_device_uevent+0x34/0xa4
 dev_uevent+0x310/0x384
 kobject_uevent_env+0x244/0x414
 kobject_uevent+0x14/0x20
 device_add+0x278/0x460
 device_register+0x20/0x34
 i3c_master_register_new_i3c_devs+0x78/0x154
 i3c_master_register+0x6a0/0x6d4
 mtk_i3c_master_probe+0x3b8/0x4d8
 platform_probe+0xa0/0xe0
 really_probe+0x114/0x454
 __driver_probe_device+0xa0/0x15c
 driver_probe_device+0x3c/0x1ac
 __driver_attach+0xc4/0x1f0
 bus_for_each_dev+0x104/0x160
 driver_attach+0x24/0x34
 bus_add_driver+0x14c/0x294
 driver_register+0x68/0x104
 __platform_driver_register+0x20/0x30
 init_module+0x20/0xfe4
 do_one_initcall+0x184/0x464
 do_init_module+0x58/0x1ec
 load_module+0xefc/0x10c8
 __arm64_sys_finit_module+0x238/0x33c
 invoke_syscall+0x58/0x10c
 el0_svc_common+0xa8/0xdc
 do_el0_svc+0x1c/0x28
 el0_svc+0x50/0xac
 el0t_64_sync_handler+0x70/0xbc
 el0t_64_sync+0x1a8/0x1ac

Signed-off-by: Defa Li <defa.li at mediatek.com>
Link: https://lore.kernel.org/r/20241107132549.25439-1-defa.li at mediatek.com
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
 drivers/i3c/master.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 02dc8e29c8280..0503f8398a86a 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -257,7 +257,8 @@ static int i3c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 	struct i3c_device_info devinfo;
 	u16 manuf, part, ext;
 
-	i3c_device_get_info(i3cdev, &devinfo);
+	if (i3cdev->desc)
+		devinfo = i3cdev->desc->info;
 	manuf = I3C_PID_MANUF_ID(devinfo.pid);
 	part = I3C_PID_PART_ID(devinfo.pid);
 	ext = I3C_PID_EXTRA_INFO(devinfo.pid);
-- 
2.43.0



From defa.li at mediatek.com  Thu Dec  5 05:29:02 2024
From: defa.li at mediatek.com (Defa Li)
Date: Thu, 5 Dec 2024 21:29:02 +0800
Subject: [PATCH] i3c: master: Improve initialization of numbered I2C adapters
Message-ID: <20241205132934.12110-1-defa.li@mediatek.com>

Add logic to initialize I2C adapters with a specific ID if available,
improving device identification and configuration.

Signed-off-by: Defa Li <defa.li at mediatek.com>
---
 drivers/i3c/master.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 42310c9a00c2..a838cdbb897b 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2486,7 +2486,7 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
 	struct i2c_adapter *adap = i3c_master_to_i2c_adapter(master);
 	struct i2c_dev_desc *i2cdev;
 	struct i2c_dev_boardinfo *i2cboardinfo;
-	int ret;
+	int ret, id = -ENODEV;
 
 	adap->dev.parent = master->dev.parent;
 	adap->owner = master->dev.parent->driver->owner;
@@ -2497,7 +2497,14 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
 	adap->timeout = 1000;
 	adap->retries = 3;
 
-	ret = i2c_add_adapter(adap);
+	if (master->dev.of_node)
+		id = of_alias_get_id(master->dev.of_node, "i2c");
+
+	if (id >= 0) {
+		adap->nr = id;
+		ret = i2c_add_numbered_adapter(adap);
+	} else
+		ret = i2c_add_adapter(adap);
 	if (ret)
 		return ret;
 
-- 
2.45.2



From quic_msavaliy at quicinc.com  Mon Dec  9 10:16:31 2024
From: quic_msavaliy at quicinc.com (Mukesh Kumar Savaliya)
Date: Mon, 9 Dec 2024 23:46:31 +0530
Subject: [PATCH] i3c: master: Improve initialization of numbered I2C
 adapters
In-Reply-To: <20241205132934.12110-1-defa.li@mediatek.com>
References: <20241205132934.12110-1-defa.li@mediatek.com>
Message-ID: <54ac6a4f-5ae0-409f-8401-d6e1326d4358@quicinc.com>



On 12/5/2024 6:59 PM, Defa Li wrote:
> Add logic to initialize I2C adapters with a specific ID if available,
> improving device identification and configuration.
> 
Could you also provide how exactly to define this into DT to have 
numbering while registering the adapter ? Kind of sample to which can be 
defined in DTSI.
> Signed-off-by: Defa Li <defa.li at mediatek.com>
> ---
>   drivers/i3c/master.c | 11 +++++++++--
>   1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index 42310c9a00c2..a838cdbb897b 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c
> @@ -2486,7 +2486,7 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
>   	struct i2c_adapter *adap = i3c_master_to_i2c_adapter(master);
>   	struct i2c_dev_desc *i2cdev;
>   	struct i2c_dev_boardinfo *i2cboardinfo;
> -	int ret;
> +	int ret, id = -ENODEV;
>   
>   	adap->dev.parent = master->dev.parent;
>   	adap->owner = master->dev.parent->driver->owner;
> @@ -2497,7 +2497,14 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
>   	adap->timeout = 1000;
>   	adap->retries = 3;
>   
> -	ret = i2c_add_adapter(adap);
> +	if (master->dev.of_node)
> +		id = of_alias_get_id(master->dev.of_node, "i2c");
> +
> +	if (id >= 0) {
> +		adap->nr = id;
> +		ret = i2c_add_numbered_adapter(adap);
> +	} else
> +		ret = i2c_add_adapter(adap);
Please provide braces for else too.
>   	if (ret)
>   		return ret;
>   



From jianqi.ren.cn at windriver.com  Tue Dec 10 00:20:47 2024
From: jianqi.ren.cn at windriver.com (jianqi.ren.cn at windriver.com)
Date: Tue, 10 Dec 2024 16:20:47 +0800
Subject: [PATCH 6.1.y] i3c: master: cdns: Fix use after free vulnerability in cdns_i3c_master Driver Due to Race Condition
Message-ID: <20241210082047.3808378-1-jianqi.ren.cn@windriver.com>

From: Kaixin Wang <kxwang23 at m.fudan.edu.cn>

[ Upstream commit 609366e7a06d035990df78f1562291c3bf0d4a12 ]

In the cdns_i3c_master_probe function, &master->hj_work is bound with
cdns_i3c_master_hj. And cdns_i3c_master_interrupt can call
cnds_i3c_master_demux_ibis function to start the work.

If we remove the module which will call cdns_i3c_master_remove to
make cleanup, it will free master->base through i3c_master_unregister
while the work mentioned above will be used. The sequence of operations
that may lead to a UAF bug is as follows:

CPU0                                      CPU1

                                     | cdns_i3c_master_hj
cdns_i3c_master_remove               |
i3c_master_unregister(&master->base) |
device_unregister(&master->dev)      |
device_release                       |
//free master->base                  |
                                     | i3c_master_do_daa(&master->base)
                                     | //use master->base

Fix it by ensuring that the work is canceled before proceeding with
the cleanup in cdns_i3c_master_remove.

Signed-off-by: Kaixin Wang <kxwang23 at m.fudan.edu.cn>
Link: https://lore.kernel.org/r/20240911153544.848398-1-kxwang23 at m.fudan.edu.cn
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Jianqi Ren <jianqi.ren.cn at windriver.com>
---
 drivers/i3c/master/i3c-master-cdns.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c
index b9cfda6ae9ae..4473c0b1ae2e 100644
--- a/drivers/i3c/master/i3c-master-cdns.c
+++ b/drivers/i3c/master/i3c-master-cdns.c
@@ -1668,6 +1668,7 @@ static int cdns_i3c_master_remove(struct platform_device *pdev)
 	struct cdns_i3c_master *master = platform_get_drvdata(pdev);
 	int ret;
 
+	cancel_work_sync(&master->hj_work);
 	ret = i3c_master_unregister(&master->base);
 	if (ret)
 		return ret;
-- 
2.25.1



From jianqi.ren.cn at windriver.com  Wed Dec 11 02:11:57 2024
From: jianqi.ren.cn at windriver.com (jianqi.ren.cn at windriver.com)
Date: Wed, 11 Dec 2024 18:11:57 +0800
Subject: [PATCH 6.1.y] i3c: master: cdns: Fix use after free vulnerability in cdns_i3c_master Driver Due to Race Condition
Message-ID: <20241211101157.2070087-1-jianqi.ren.cn@windriver.com>

From: Kaixin Wang <kxwang23 at m.fudan.edu.cn>

[ Upstream commit 609366e7a06d035990df78f1562291c3bf0d4a12 ]

In the cdns_i3c_master_probe function, &master->hj_work is bound with
cdns_i3c_master_hj. And cdns_i3c_master_interrupt can call
cnds_i3c_master_demux_ibis function to start the work.

If we remove the module which will call cdns_i3c_master_remove to
make cleanup, it will free master->base through i3c_master_unregister
while the work mentioned above will be used. The sequence of operations
that may lead to a UAF bug is as follows:

CPU0                                      CPU1

                                     | cdns_i3c_master_hj
cdns_i3c_master_remove               |
i3c_master_unregister(&master->base) |
device_unregister(&master->dev)      |
device_release                       |
//free master->base                  |
                                     | i3c_master_do_daa(&master->base)
                                     | //use master->base

Fix it by ensuring that the work is canceled before proceeding with
the cleanup in cdns_i3c_master_remove.

Signed-off-by: Kaixin Wang <kxwang23 at m.fudan.edu.cn>
Link: https://lore.kernel.org/r/20240911153544.848398-1-kxwang23 at m.fudan.edu.cn
Signed-off-by: Alexandre Belloni <alexandre.belloni at bootlin.com>
Signed-off-by: Jianqi Ren <jianqi.ren.cn at windriver.com>
---
 drivers/i3c/master/i3c-master-cdns.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c
index b9cfda6ae9ae..4473c0b1ae2e 100644
--- a/drivers/i3c/master/i3c-master-cdns.c
+++ b/drivers/i3c/master/i3c-master-cdns.c
@@ -1668,6 +1668,7 @@ static int cdns_i3c_master_remove(struct platform_device *pdev)
 	struct cdns_i3c_master *master = platform_get_drvdata(pdev);
 	int ret;
 
+	cancel_work_sync(&master->hj_work);
 	ret = i3c_master_unregister(&master->base);
 	if (ret)
 		return ret;
-- 
2.25.1



From defa.li at mediatek.com  Thu Dec 12 01:17:53 2024
From: defa.li at mediatek.com (Defa Li)
Date: Thu, 12 Dec 2024 17:17:53 +0800
Subject: [PATCH v2] i3c: master: Improve initialization of numbered I2C adapters
Message-ID: <20241212091818.8591-1-defa.li@mediatek.com>

Add logic to initialize I2C adapters with a specific ID if available,
improving device identification and configuration.

For mixed buses, in addition to the i3c alias, an i2c alias can be added to
assign a fixed bus number to the i2c adapter.

This allows an alias node such as:
    aliases {
        i2c2 = &mixed_bus_a,
        i3c2 = &mixed_bus_a,
        i3c4 = &mixed_bus_b,
    };

    /* assigned "i3c-2" and "i2c-2" */
    mixed_bus_a: i3c-master {
    };

If there is no i2c alias for a mixed bus, the i2c adapter numbers will
remain as is and will be assigned starting after the highest fixed bus
number.

    /* assigned "i3c-4" and likely assigned "i2c-3" */
    mixed_bus_b: i3c-master {
    };

v2:
  - Modify commit message and code format issues

Signed-off-by: Defa Li <defa.li at mediatek.com>
---
 drivers/i3c/master.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 42310c9a00c2..92223e0b6e59 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2486,7 +2486,7 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
 	struct i2c_adapter *adap = i3c_master_to_i2c_adapter(master);
 	struct i2c_dev_desc *i2cdev;
 	struct i2c_dev_boardinfo *i2cboardinfo;
-	int ret;
+	int ret, id = -ENODEV;
 
 	adap->dev.parent = master->dev.parent;
 	adap->owner = master->dev.parent->driver->owner;
@@ -2497,7 +2497,15 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
 	adap->timeout = 1000;
 	adap->retries = 3;
 
-	ret = i2c_add_adapter(adap);
+	if (master->dev.of_node)
+		id = of_alias_get_id(master->dev.of_node, "i2c");
+
+	if (id >= 0) {
+		adap->nr = id;
+		ret = i2c_add_numbered_adapter(adap);
+	} else {
+		ret = i2c_add_adapter(adap);
+	}
 	if (ret)
 		return ret;
 
-- 
2.46.0



From linux at roeck-us.net  Wed Dec 18 09:57:06 2024
From: linux at roeck-us.net (Guenter Roeck)
Date: Wed, 18 Dec 2024 09:57:06 -0800
Subject: DDR5 / SPD5118 connected to I3C bus
Message-ID: <d7ceb8fd-92fd-431b-85de-a3eae40a1981@roeck-us.net>

Hi all,

I have a series of patches which extends sdp5118 support in the Linux kernel
to I3C. Unfortunately, I don't have access to a system with I3C controller,
much less the ability to connect DDR5 memory to it.

Does anyone on this list happen to have access to such as system and would
be able and willing to test the patch series ?

Thanks,
Guenter


From Frank.li at nxp.com  Thu Dec 19 12:08:41 2024
From: Frank.li at nxp.com (Frank Li)
Date: Thu, 19 Dec 2024 15:08:41 -0500
Subject: [PATCH v2] i3c: master: Improve initialization of numbered I2C
 adapters
In-Reply-To: <20241212091818.8591-1-defa.li@mediatek.com>
References: <20241212091818.8591-1-defa.li@mediatek.com>
Message-ID: <Z2R9SUJYJlUJSmtL@lizhi-Precision-Tower-5810>

On Thu, Dec 12, 2024 at 05:17:53PM +0800, Defa Li wrote:
> Add logic to initialize I2C adapters with a specific ID if available,
> improving device identification and configuration.
>
> For mixed buses, in addition to the i3c alias, an i2c alias can be added to
> assign a fixed bus number to the i2c adapter.
>
> This allows an alias node such as:
>     aliases {
>         i2c2 = &mixed_bus_a,
>         i3c2 = &mixed_bus_a,
>         i3c4 = &mixed_bus_b,
>     };
>
>     /* assigned "i3c-2" and "i2c-2" */
>     mixed_bus_a: i3c-master {
>     };
>
> If there is no i2c alias for a mixed bus, the i2c adapter numbers will
> remain as is and will be assigned starting after the highest fixed bus
> number.
>
>     /* assigned "i3c-4" and likely assigned "i2c-3" */
>     mixed_bus_b: i3c-master {
>     };
>
> v2:
>   - Modify commit message and code format issues

v2: ...
 should be after "---"

>
> Signed-off-by: Defa Li <defa.li at mediatek.com>

Reviewed-by: Frank Li <Frank.Li at nxp.com>

> ---
>  drivers/i3c/master.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index 42310c9a00c2..92223e0b6e59 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c
> @@ -2486,7 +2486,7 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
>  	struct i2c_adapter *adap = i3c_master_to_i2c_adapter(master);
>  	struct i2c_dev_desc *i2cdev;
>  	struct i2c_dev_boardinfo *i2cboardinfo;
> -	int ret;
> +	int ret, id = -ENODEV;
>
>  	adap->dev.parent = master->dev.parent;
>  	adap->owner = master->dev.parent->driver->owner;
> @@ -2497,7 +2497,15 @@ static int i3c_master_i2c_adapter_init(struct i3c_master_controller *master)
>  	adap->timeout = 1000;
>  	adap->retries = 3;
>
> -	ret = i2c_add_adapter(adap);
> +	if (master->dev.of_node)
> +		id = of_alias_get_id(master->dev.of_node, "i2c");
> +
> +	if (id >= 0) {
> +		adap->nr = id;
> +		ret = i2c_add_numbered_adapter(adap);
> +	} else {
> +		ret = i2c_add_adapter(adap);
> +	}
>  	if (ret)
>  		return ret;
>
> --
> 2.46.0
>
>
> --
> linux-i3c mailing list
> linux-i3c at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-i3c


From wsa+renesas at sang-engineering.com  Thu Dec 19 14:03:37 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Thu, 19 Dec 2024 23:03:37 +0100
Subject: [PATCH] i3c: fix kdoc parameter description for module_i3c_i2c_driver()
Message-ID: <20241219220338.10315-1-wsa+renesas@sang-engineering.com>

A typo mentioned I3C when it should have been I2C.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
---
 include/linux/i3c/device.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h
index 0a8a44ac2f02..b674f64d0822 100644
--- a/include/linux/i3c/device.h
+++ b/include/linux/i3c/device.h
@@ -283,7 +283,7 @@ static inline void i3c_i2c_driver_unregister(struct i3c_driver *i3cdrv,
  * module_i3c_i2c_driver() - Register a module providing an I3C and an I2C
  *			     driver
  * @__i3cdrv: the I3C driver to register
- * @__i2cdrv: the I3C driver to register
+ * @__i2cdrv: the I2C driver to register
  *
  * Provide generic init/exit functions that simply register/unregister an I3C
  * and an I2C driver.
-- 
2.39.2



From geert at linux-m68k.org  Fri Dec 20 00:46:41 2024
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Fri, 20 Dec 2024 09:46:41 +0100
Subject: [PATCH] i3c: fix kdoc parameter description for module_i3c_i2c_driver()
In-Reply-To: <20241219220338.10315-1-wsa+renesas@sang-engineering.com>
References: <20241219220338.10315-1-wsa+renesas@sang-engineering.com>
Message-ID: <CAMuHMdVE7g7p_ysL6MjJqFxMdM9eY-cuOhXb9mAqDaJp-FOOdQ@mail.gmail.com>

On Thu, Dec 19, 2024 at 11:04?PM Wolfram Sang
<wsa+renesas at sang-engineering.com> wrote:
> A typo mentioned I3C when it should have been I2C.
>
> Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>

Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From wsa+renesas at sang-engineering.com  Fri Dec 20 03:29:58 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Fri, 20 Dec 2024 12:29:58 +0100
Subject: [PATCH RFT 4/5] i3c: mipi-i3c-hci: use get_parity8 helper instead of open coding it
In-Reply-To: <20241220113000.17537-1-wsa+renesas@sang-engineering.com>
References: <20241220113000.17537-1-wsa+renesas@sang-engineering.com>
Message-ID: <20241220113000.17537-5-wsa+renesas@sang-engineering.com>

The kernel has now a generic helper for getting parity with easier to
understand semantics. Make use of it.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
---
 drivers/i3c/master/mipi-i3c-hci/dat_v1.c | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/dat_v1.c b/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
index 47b9b4d4ed3f..ac67016932b0 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
@@ -40,15 +40,6 @@
 #define dat_w0_write(i, v)	writel(v, hci->DAT_regs + (i) * 8)
 #define dat_w1_write(i, v)	writel(v, hci->DAT_regs + (i) * 8 + 4)
 
-static inline bool dynaddr_parity(unsigned int addr)
-{
-	addr |= 1 << 7;
-	addr += addr >> 4;
-	addr += addr >> 2;
-	addr += addr >> 1;
-	return (addr & 1);
-}
-
 static int hci_dat_v1_init(struct i3c_hci *hci)
 {
 	unsigned int dat_idx;
@@ -123,7 +114,7 @@ static void hci_dat_v1_set_dynamic_addr(struct i3c_hci *hci,
 	dat_w0 = dat_w0_read(dat_idx);
 	dat_w0 &= ~(DAT_0_DYNAMIC_ADDRESS | DAT_0_DYNADDR_PARITY);
 	dat_w0 |= FIELD_PREP(DAT_0_DYNAMIC_ADDRESS, address) |
-		  (dynaddr_parity(address) ? DAT_0_DYNADDR_PARITY : 0);
+		  (get_parity8(address) ? 0 : DAT_0_DYNADDR_PARITY);
 	dat_w0_write(dat_idx, dat_w0);
 }
 
-- 
2.39.2



From wsa+renesas at sang-engineering.com  Fri Dec 20 03:29:57 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Fri, 20 Dec 2024 12:29:57 +0100
Subject: [PATCH RFT 3/5] i3c: dw: use get_parity8 helper instead of open coding it
In-Reply-To: <20241220113000.17537-1-wsa+renesas@sang-engineering.com>
References: <20241220113000.17537-1-wsa+renesas@sang-engineering.com>
Message-ID: <20241220113000.17537-4-wsa+renesas@sang-engineering.com>

The kernel has now a generic helper for getting parity with easier to
understand semantics. Make use of it.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
---
 drivers/i3c/master/dw-i3c-master.c | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index d4b80eb8cecd..a6d7fade5007 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -251,14 +251,6 @@ struct dw_i3c_i2c_dev_data {
 	struct i3c_generic_ibi_pool *ibi_pool;
 };
 
-static u8 even_parity(u8 p)
-{
-	p ^= p >> 4;
-	p &= 0xf;
-
-	return (0x9669 >> p) & 1;
-}
-
 static bool dw_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m,
 					   const struct i3c_ccc_cmd *cmd)
 {
@@ -848,7 +840,7 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
 	struct dw_i3c_xfer *xfer;
 	struct dw_i3c_cmd *cmd;
 	u32 olddevs, newdevs;
-	u8 p, last_addr = 0;
+	u8 last_addr = 0;
 	int ret, pos;
 
 	ret = pm_runtime_resume_and_get(master->dev);
@@ -873,9 +865,9 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
 		}
 
 		master->devs[pos].addr = ret;
-		p = even_parity(ret);
 		last_addr = ret;
-		ret |= (p << 7);
+
+		ret |= get_parity8(ret) ? 0 : BIT(7);
 
 		writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(ret),
 		       master->regs +
-- 
2.39.2



From wsa+renesas at sang-engineering.com  Fri Dec 20 03:29:54 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Fri, 20 Dec 2024 12:29:54 +0100
Subject: [PATCH RFT 0/5] i3c: introduce and use generic parity helper
Message-ID: <20241220113000.17537-1-wsa+renesas@sang-engineering.com>

I am currently working on upstreaming another I3C controller driver. As
many others, it needs to ensure odd parity for a dynamically assigned
address. The BSP version of the driver implemented a custom parity
algorithm. Wondering why we don't have a generic helper for this in the
kernel, I found that many I3C controller drivers all implement their
version of handling parity.

So, I sent out an RFC[1] moving the efficient implementation of the
SPD5118 driver to a generic location. The series was well received, but
the path for upstream was not clear. Because I need the implementation
for my I3C controller driver and I3C is a prominent user of this new
function, I got the idea of converting the existing I3C drivers and
resend the series, suggesting this all goes upstream via I3C.

Is this acceptable? The non-I3C patches have all the tags they need,
only the I3C patches would need testing on hardware.

A locally build-tested branch is here:

git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git renesas/i3c/get_parity

Looking forward to comments...

[1] https://lore.kernel.org/all/20241214085833.8695-1-wsa+renesas at sang-engineering.com/


Wolfram Sang (5):
  bitops: add generic parity calculation for u8
  hwmon: (spd5118) Use generic parity calculation
  i3c: dw: use get_parity8 helper instead of open coding it
  i3c: mipi-i3c-hci: use get_parity8 helper instead of open coding it
  i3c: cdns: use get_parity8 helper instead of open coding it

 drivers/hwmon/spd5118.c                  |  8 +-----
 drivers/i3c/master/dw-i3c-master.c       | 14 +++--------
 drivers/i3c/master/i3c-master-cdns.c     |  3 +--
 drivers/i3c/master/mipi-i3c-hci/dat_v1.c | 11 +--------
 include/linux/bitops.h                   | 31 ++++++++++++++++++++++++
 5 files changed, 37 insertions(+), 30 deletions(-)

-- 
2.39.2



From wsa+renesas at sang-engineering.com  Fri Dec 20 03:29:59 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Fri, 20 Dec 2024 12:29:59 +0100
Subject: [PATCH RFT 5/5] i3c: cdns: use get_parity8 helper instead of open coding it
In-Reply-To: <20241220113000.17537-1-wsa+renesas@sang-engineering.com>
References: <20241220113000.17537-1-wsa+renesas@sang-engineering.com>
Message-ID: <20241220113000.17537-6-wsa+renesas@sang-engineering.com>

The kernel has now a generic helper for getting parity with easier to
understand semantics. Make use of it.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
---

Can't the '& 0x7f' be left out here?

 drivers/i3c/master/i3c-master-cdns.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c
index 06c0592487d3..abeef6f70b53 100644
--- a/drivers/i3c/master/i3c-master-cdns.c
+++ b/drivers/i3c/master/i3c-master-cdns.c
@@ -889,8 +889,7 @@ static u32 prepare_rr0_dev_address(u32 addr)
 	ret |= (addr & GENMASK(9, 7)) << 6;
 
 	/* RR0[0] = ~XOR(addr[6:0]) */
-	if (!(hweight8(addr & 0x7f) & 1))
-		ret |= 1;
+	ret |= get_parity8(addr & 0x7f) ? 0 : BIT(0);
 
 	return ret;
 }
-- 
2.39.2



From wsa+renesas at sang-engineering.com  Fri Dec 20 03:33:28 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Fri, 20 Dec 2024 12:33:28 +0100
Subject: [PATCH RFT RESEND 0/5] i3c: introduce and use generic parity helper
Message-ID: <20241220113335.17937-1-wsa+renesas@sang-engineering.com>

[Resending because I3C list was not added on all patches. Sorry!]

I am currently working on upstreaming another I3C controller driver. As
many others, it needs to ensure odd parity for a dynamically assigned
address. The BSP version of the driver implemented a custom parity
algorithm. Wondering why we don't have a generic helper for this in the
kernel, I found that many I3C controller drivers all implement their
version of handling parity.

So, I sent out an RFC[1] moving the efficient implementation of the
SPD5118 driver to a generic location. The series was well received, but
the path for upstream was not clear. Because I need the implementation
for my I3C controller driver and I3C is a prominent user of this new
function, I got the idea of converting the existing I3C drivers and
resend the series, suggesting this all goes upstream via I3C.

Is this acceptable? The non-I3C patches have all the tags they need,
only the I3C patches would need testing on hardware.

A locally build-tested branch is here:

git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git renesas/i3c/get_parity

Looking forward to comments...

[1] https://lore.kernel.org/all/20241214085833.8695-1-wsa+renesas at sang-engineering.com/


Wolfram Sang (5):
  bitops: add generic parity calculation for u8
  hwmon: (spd5118) Use generic parity calculation
  i3c: dw: use get_parity8 helper instead of open coding it
  i3c: mipi-i3c-hci: use get_parity8 helper instead of open coding it
  i3c: cdns: use get_parity8 helper instead of open coding it

 drivers/hwmon/spd5118.c                  |  8 +-----
 drivers/i3c/master/dw-i3c-master.c       | 14 +++--------
 drivers/i3c/master/i3c-master-cdns.c     |  3 +--
 drivers/i3c/master/mipi-i3c-hci/dat_v1.c | 11 +--------
 include/linux/bitops.h                   | 31 ++++++++++++++++++++++++
 5 files changed, 37 insertions(+), 30 deletions(-)

-- 
2.39.2



From wsa+renesas at sang-engineering.com  Fri Dec 20 03:33:29 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Fri, 20 Dec 2024 12:33:29 +0100
Subject: [PATCH RFT RESEND 1/5] bitops: add generic parity calculation for u8
In-Reply-To: <20241220113335.17937-1-wsa+renesas@sang-engineering.com>
References: <20241220113335.17937-1-wsa+renesas@sang-engineering.com>
Message-ID: <20241220113335.17937-2-wsa+renesas@sang-engineering.com>

There are multiple open coded implementations for getting the parity of
a byte in the kernel, even using different approaches. Take the pretty
efficient version from SPD5118 driver and make it generally available by
putting it into the bitops header. As long as there is just one parity
calculation helper, the creation of a distinct 'parity.h' header was
discarded. Also, the usage of hweight8() for architectures having a
popcnt instruction is postponed until a use case within hot paths is
desired. The motivation for this patch is the frequent use of odd parity
in the I3C specification and to simplify drivers there.

Changes compared to the original SPD5118 version are the addition of
kernel documentation, switching the return type from bool to int, and
renaming the argument of the function.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
Tested-by: Guenter Roeck <linux at roeck-us.net>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
Acked-by: Yury Norov <yury.norov at gmail.com>
Reviewed-by: Kuan-Wei Chiu <visitorckw at gmail.com>
Tested-by: Kuan-Wei Chiu <visitorckw at gmail.com>
---
 include/linux/bitops.h | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index ba35bbf07798..4ed430934ffc 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -229,6 +229,37 @@ static inline int get_count_order_long(unsigned long l)
 	return (int)fls_long(--l);
 }
 
+/**
+ * get_parity8 - get the parity of an u8 value
+ * @value: the value to be examined
+ *
+ * Determine the parity of the u8 argument.
+ *
+ * Returns:
+ * 0 for even parity, 1 for odd parity
+ *
+ * Note: This function informs you about the current parity. Example to bail
+ * out when parity is odd:
+ *
+ *	if (get_parity8(val) == 1)
+ *		return -EBADMSG;
+ *
+ * If you need to calculate a parity bit, you need to draw the conclusion from
+ * this result yourself. Example to enforce odd parity, parity bit is bit 7:
+ *
+ *	if (get_parity8(val) == 0)
+ *		val |= BIT(7);
+ */
+static inline int get_parity8(u8 val)
+{
+	/*
+	 * One explanation of this algorithm:
+	 * https://funloop.org/codex/problem/parity/README.html
+	 */
+	val ^= val >> 4;
+	return (0x6996 >> (val & 0xf)) & 1;
+}
+
 /**
  * __ffs64 - find first set bit in a 64 bit word
  * @word: The 64 bit word
-- 
2.39.2



From wsa+renesas at sang-engineering.com  Fri Dec 20 03:33:30 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Fri, 20 Dec 2024 12:33:30 +0100
Subject: [PATCH RFT RESEND 2/5] hwmon: (spd5118) Use generic parity calculation
In-Reply-To: <20241220113335.17937-1-wsa+renesas@sang-engineering.com>
References: <20241220113335.17937-1-wsa+renesas@sang-engineering.com>
Message-ID: <20241220113335.17937-3-wsa+renesas@sang-engineering.com>

Make use of the new generic helper for calculating the parity.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
Tested-by: Guenter Roeck <linux at roeck-us.net>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
Reviewed-by: Kuan-Wei Chiu <visitorckw at gmail.com>
---
 drivers/hwmon/spd5118.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/hwmon/spd5118.c b/drivers/hwmon/spd5118.c
index 6cee48a3e5c3..07ab3a47b00c 100644
--- a/drivers/hwmon/spd5118.c
+++ b/drivers/hwmon/spd5118.c
@@ -291,12 +291,6 @@ static umode_t spd5118_is_visible(const void *_data, enum hwmon_sensor_types typ
 	}
 }
 
-static inline bool spd5118_parity8(u8 w)
-{
-	w ^= w >> 4;
-	return (0x6996 >> (w & 0xf)) & 1;
-}
-
 /*
  * Bank and vendor id are 8-bit fields with seven data bits and odd parity.
  * Vendor IDs 0 and 0x7f are invalid.
@@ -304,7 +298,7 @@ static inline bool spd5118_parity8(u8 w)
  */
 static bool spd5118_vendor_valid(u8 bank, u8 id)
 {
-	if (!spd5118_parity8(bank) || !spd5118_parity8(id))
+	if (get_parity8(bank) == 0 || get_parity8(id) == 0)
 		return false;
 
 	id &= 0x7f;
-- 
2.39.2



From wsa+renesas at sang-engineering.com  Fri Dec 20 03:33:31 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Fri, 20 Dec 2024 12:33:31 +0100
Subject: [PATCH RFT RESEND 3/5] i3c: dw: use get_parity8 helper instead of open coding it
In-Reply-To: <20241220113335.17937-1-wsa+renesas@sang-engineering.com>
References: <20241220113335.17937-1-wsa+renesas@sang-engineering.com>
Message-ID: <20241220113335.17937-4-wsa+renesas@sang-engineering.com>

The kernel has now a generic helper for getting parity with easier to
understand semantics. Make use of it.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
---
 drivers/i3c/master/dw-i3c-master.c | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index d4b80eb8cecd..a6d7fade5007 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -251,14 +251,6 @@ struct dw_i3c_i2c_dev_data {
 	struct i3c_generic_ibi_pool *ibi_pool;
 };
 
-static u8 even_parity(u8 p)
-{
-	p ^= p >> 4;
-	p &= 0xf;
-
-	return (0x9669 >> p) & 1;
-}
-
 static bool dw_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m,
 					   const struct i3c_ccc_cmd *cmd)
 {
@@ -848,7 +840,7 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
 	struct dw_i3c_xfer *xfer;
 	struct dw_i3c_cmd *cmd;
 	u32 olddevs, newdevs;
-	u8 p, last_addr = 0;
+	u8 last_addr = 0;
 	int ret, pos;
 
 	ret = pm_runtime_resume_and_get(master->dev);
@@ -873,9 +865,9 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
 		}
 
 		master->devs[pos].addr = ret;
-		p = even_parity(ret);
 		last_addr = ret;
-		ret |= (p << 7);
+
+		ret |= get_parity8(ret) ? 0 : BIT(7);
 
 		writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(ret),
 		       master->regs +
-- 
2.39.2



From wsa+renesas at sang-engineering.com  Fri Dec 20 03:33:32 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Fri, 20 Dec 2024 12:33:32 +0100
Subject: [PATCH RFT RESEND 4/5] i3c: mipi-i3c-hci: use get_parity8 helper instead of open coding it
In-Reply-To: <20241220113335.17937-1-wsa+renesas@sang-engineering.com>
References: <20241220113335.17937-1-wsa+renesas@sang-engineering.com>
Message-ID: <20241220113335.17937-5-wsa+renesas@sang-engineering.com>

The kernel has now a generic helper for getting parity with easier to
understand semantics. Make use of it.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
---
 drivers/i3c/master/mipi-i3c-hci/dat_v1.c | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/dat_v1.c b/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
index 47b9b4d4ed3f..ac67016932b0 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
@@ -40,15 +40,6 @@
 #define dat_w0_write(i, v)	writel(v, hci->DAT_regs + (i) * 8)
 #define dat_w1_write(i, v)	writel(v, hci->DAT_regs + (i) * 8 + 4)
 
-static inline bool dynaddr_parity(unsigned int addr)
-{
-	addr |= 1 << 7;
-	addr += addr >> 4;
-	addr += addr >> 2;
-	addr += addr >> 1;
-	return (addr & 1);
-}
-
 static int hci_dat_v1_init(struct i3c_hci *hci)
 {
 	unsigned int dat_idx;
@@ -123,7 +114,7 @@ static void hci_dat_v1_set_dynamic_addr(struct i3c_hci *hci,
 	dat_w0 = dat_w0_read(dat_idx);
 	dat_w0 &= ~(DAT_0_DYNAMIC_ADDRESS | DAT_0_DYNADDR_PARITY);
 	dat_w0 |= FIELD_PREP(DAT_0_DYNAMIC_ADDRESS, address) |
-		  (dynaddr_parity(address) ? DAT_0_DYNADDR_PARITY : 0);
+		  (get_parity8(address) ? 0 : DAT_0_DYNADDR_PARITY);
 	dat_w0_write(dat_idx, dat_w0);
 }
 
-- 
2.39.2



From wsa+renesas at sang-engineering.com  Fri Dec 20 03:33:33 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Fri, 20 Dec 2024 12:33:33 +0100
Subject: [PATCH RFT RESEND 5/5] i3c: cdns: use get_parity8 helper instead of open coding it
In-Reply-To: <20241220113335.17937-1-wsa+renesas@sang-engineering.com>
References: <20241220113335.17937-1-wsa+renesas@sang-engineering.com>
Message-ID: <20241220113335.17937-6-wsa+renesas@sang-engineering.com>

The kernel has now a generic helper for getting parity with easier to
understand semantics. Make use of it.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
---

Can't the '& 0x7f' be left out here?

 drivers/i3c/master/i3c-master-cdns.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c
index 06c0592487d3..abeef6f70b53 100644
--- a/drivers/i3c/master/i3c-master-cdns.c
+++ b/drivers/i3c/master/i3c-master-cdns.c
@@ -889,8 +889,7 @@ static u32 prepare_rr0_dev_address(u32 addr)
 	ret |= (addr & GENMASK(9, 7)) << 6;
 
 	/* RR0[0] = ~XOR(addr[6:0]) */
-	if (!(hweight8(addr & 0x7f) & 1))
-		ret |= 1;
+	ret |= get_parity8(addr & 0x7f) ? 0 : BIT(0);
 
 	return ret;
 }
-- 
2.39.2



From linux at roeck-us.net  Fri Dec 20 07:24:46 2024
From: linux at roeck-us.net (Guenter Roeck)
Date: Fri, 20 Dec 2024 07:24:46 -0800
Subject: [PATCH RFT RESEND 2/5] hwmon: (spd5118) Use generic parity
 calculation
In-Reply-To: <20241220113335.17937-3-wsa+renesas@sang-engineering.com>
References: <20241220113335.17937-1-wsa+renesas@sang-engineering.com>
 <20241220113335.17937-3-wsa+renesas@sang-engineering.com>
Message-ID: <d1d5cfa4-b2b0-470f-a9aa-88f7b1266e5f@roeck-us.net>

On 12/20/24 03:33, Wolfram Sang wrote:
> Make use of the new generic helper for calculating the parity.
> 
> Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
> Tested-by: Guenter Roeck <linux at roeck-us.net>
> Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
> Reviewed-by: Kuan-Wei Chiu <visitorckw at gmail.com>

I just noticed I replied to the original version, so here it is again:

For the record:

Acked-by: Guenter Roeck <linux at roeck-us.net>

I don't care about the function name, so please retain the tags if/when
changing it.

Thanks,
Guenter

> ---
>   drivers/hwmon/spd5118.c | 8 +-------
>   1 file changed, 1 insertion(+), 7 deletions(-)
> 
> diff --git a/drivers/hwmon/spd5118.c b/drivers/hwmon/spd5118.c
> index 6cee48a3e5c3..07ab3a47b00c 100644
> --- a/drivers/hwmon/spd5118.c
> +++ b/drivers/hwmon/spd5118.c
> @@ -291,12 +291,6 @@ static umode_t spd5118_is_visible(const void *_data, enum hwmon_sensor_types typ
>   	}
>   }
>   
> -static inline bool spd5118_parity8(u8 w)
> -{
> -	w ^= w >> 4;
> -	return (0x6996 >> (w & 0xf)) & 1;
> -}
> -
>   /*
>    * Bank and vendor id are 8-bit fields with seven data bits and odd parity.
>    * Vendor IDs 0 and 0x7f are invalid.
> @@ -304,7 +298,7 @@ static inline bool spd5118_parity8(u8 w)
>    */
>   static bool spd5118_vendor_valid(u8 bank, u8 id)
>   {
> -	if (!spd5118_parity8(bank) || !spd5118_parity8(id))
> +	if (get_parity8(bank) == 0 || get_parity8(id) == 0)
>   		return false;
>   
>   	id &= 0x7f;



From wsa+renesas at sang-engineering.com  Sun Dec 29 02:12:31 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Sun, 29 Dec 2024 11:12:31 +0100
Subject: [PATCH RFT v2 3/5] i3c: dw: use get_parity8 helper instead of open coding it
In-Reply-To: <20241229101234.2896-1-wsa+renesas@sang-engineering.com>
References: <20241229101234.2896-1-wsa+renesas@sang-engineering.com>
Message-ID: <20241229101234.2896-4-wsa+renesas@sang-engineering.com>

The kernel has now a generic helper for getting parity with easier to
understand semantics. Make use of it.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
---
Changes since v1:

* renamed from 'get_parity8' to 'parity8'
* rebased to 6.13-rc4

 drivers/i3c/master/dw-i3c-master.c | 14 +++-----------
 1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index d4b80eb8cecd..0d4d44458c11 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -251,14 +251,6 @@ struct dw_i3c_i2c_dev_data {
 	struct i3c_generic_ibi_pool *ibi_pool;
 };
 
-static u8 even_parity(u8 p)
-{
-	p ^= p >> 4;
-	p &= 0xf;
-
-	return (0x9669 >> p) & 1;
-}
-
 static bool dw_i3c_master_supports_ccc_cmd(struct i3c_master_controller *m,
 					   const struct i3c_ccc_cmd *cmd)
 {
@@ -848,7 +840,7 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
 	struct dw_i3c_xfer *xfer;
 	struct dw_i3c_cmd *cmd;
 	u32 olddevs, newdevs;
-	u8 p, last_addr = 0;
+	u8 last_addr = 0;
 	int ret, pos;
 
 	ret = pm_runtime_resume_and_get(master->dev);
@@ -873,9 +865,9 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
 		}
 
 		master->devs[pos].addr = ret;
-		p = even_parity(ret);
 		last_addr = ret;
-		ret |= (p << 7);
+
+		ret |= parity8(ret) ? 0 : BIT(7);
 
 		writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(ret),
 		       master->regs +
-- 
2.39.2



From wsa+renesas at sang-engineering.com  Sun Dec 29 02:12:30 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Sun, 29 Dec 2024 11:12:30 +0100
Subject: [PATCH RFT v2 2/5] hwmon: (spd5118) Use generic parity calculation
In-Reply-To: <20241229101234.2896-1-wsa+renesas@sang-engineering.com>
References: <20241229101234.2896-1-wsa+renesas@sang-engineering.com>
Message-ID: <20241229101234.2896-3-wsa+renesas@sang-engineering.com>

Make use of the new generic helper for calculating the parity.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
Tested-by: Guenter Roeck <linux at roeck-us.net>
Acked-by: Guenter Roeck <linux at roeck-us.net>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
Reviewed-by: Kuan-Wei Chiu <visitorckw at gmail.com>
---
Changes since v1:

* renamed from 'get_parity8' to 'parity8'
* added tag from Guenter (thanks!)
* rebased to 6.13-rc4

 drivers/hwmon/spd5118.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/drivers/hwmon/spd5118.c b/drivers/hwmon/spd5118.c
index 6cee48a3e5c3..358152868d96 100644
--- a/drivers/hwmon/spd5118.c
+++ b/drivers/hwmon/spd5118.c
@@ -291,12 +291,6 @@ static umode_t spd5118_is_visible(const void *_data, enum hwmon_sensor_types typ
 	}
 }
 
-static inline bool spd5118_parity8(u8 w)
-{
-	w ^= w >> 4;
-	return (0x6996 >> (w & 0xf)) & 1;
-}
-
 /*
  * Bank and vendor id are 8-bit fields with seven data bits and odd parity.
  * Vendor IDs 0 and 0x7f are invalid.
@@ -304,7 +298,7 @@ static inline bool spd5118_parity8(u8 w)
  */
 static bool spd5118_vendor_valid(u8 bank, u8 id)
 {
-	if (!spd5118_parity8(bank) || !spd5118_parity8(id))
+	if (parity8(bank) == 0 || parity8(id) == 0)
 		return false;
 
 	id &= 0x7f;
-- 
2.39.2



From wsa+renesas at sang-engineering.com  Sun Dec 29 02:12:32 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Sun, 29 Dec 2024 11:12:32 +0100
Subject: [PATCH RFT v2 4/5] i3c: mipi-i3c-hci: use get_parity8 helper instead of open coding it
In-Reply-To: <20241229101234.2896-1-wsa+renesas@sang-engineering.com>
References: <20241229101234.2896-1-wsa+renesas@sang-engineering.com>
Message-ID: <20241229101234.2896-5-wsa+renesas@sang-engineering.com>

The kernel has now a generic helper for getting parity with easier to
understand semantics. Make use of it.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
---
Changes since v1:

* renamed from 'get_parity8' to 'parity8'
* rebased to 6.13-rc4

 drivers/i3c/master/mipi-i3c-hci/dat_v1.c | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/dat_v1.c b/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
index 47b9b4d4ed3f..85c4916972e4 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dat_v1.c
@@ -40,15 +40,6 @@
 #define dat_w0_write(i, v)	writel(v, hci->DAT_regs + (i) * 8)
 #define dat_w1_write(i, v)	writel(v, hci->DAT_regs + (i) * 8 + 4)
 
-static inline bool dynaddr_parity(unsigned int addr)
-{
-	addr |= 1 << 7;
-	addr += addr >> 4;
-	addr += addr >> 2;
-	addr += addr >> 1;
-	return (addr & 1);
-}
-
 static int hci_dat_v1_init(struct i3c_hci *hci)
 {
 	unsigned int dat_idx;
@@ -123,7 +114,7 @@ static void hci_dat_v1_set_dynamic_addr(struct i3c_hci *hci,
 	dat_w0 = dat_w0_read(dat_idx);
 	dat_w0 &= ~(DAT_0_DYNAMIC_ADDRESS | DAT_0_DYNADDR_PARITY);
 	dat_w0 |= FIELD_PREP(DAT_0_DYNAMIC_ADDRESS, address) |
-		  (dynaddr_parity(address) ? DAT_0_DYNADDR_PARITY : 0);
+		  (parity8(address) ? 0 : DAT_0_DYNADDR_PARITY);
 	dat_w0_write(dat_idx, dat_w0);
 }
 
-- 
2.39.2



From wsa+renesas at sang-engineering.com  Sun Dec 29 02:12:28 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Sun, 29 Dec 2024 11:12:28 +0100
Subject: [PATCH RFT v2 0/5] i3c: introduce and use generic parity helper
Message-ID: <20241229101234.2896-1-wsa+renesas@sang-engineering.com>

Changes since v1:

* renamed from 'get_parity8' to 'parity8'
* use XOR instead of OR in the kdoc example (Thanks, Rasmus, for both)
* added tag from Guenter (thanks!)
* rebased to 6.13-rc4

Old coverletter follows:

I am currently working on upstreaming another I3C controller driver. As
many others, it needs to ensure odd parity for a dynamically assigned
address. The BSP version of the driver implemented a custom parity
algorithm. Wondering why we don't have a generic helper for this in the
kernel, I found that many I3C controller drivers all implement their
version of handling parity.

So, I sent out an RFC[1] moving the efficient implementation of the
SPD5118 driver to a generic location. The series was well received, but
the path for upstream was not clear. Because I need the implementation
for my I3C controller driver and I3C is a prominent user of this new
function, I got the idea of converting the existing I3C drivers and
resend the series, suggesting this all goes upstream via I3C.

Is this acceptable? The non-I3C patches have all the tags they need,
only the I3C patches would need testing on hardware.

A build-tested (incl. build-bots) branch is here:

git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git renesas/i3c/get_parity

Looking forward to comments...

[1] https://lore.kernel.org/all/20241214085833.8695-1-wsa+renesas at sang-engineering.com/



Wolfram Sang (5):
  bitops: add generic parity calculation for u8
  hwmon: (spd5118) Use generic parity calculation
  i3c: dw: use get_parity8 helper instead of open coding it
  i3c: mipi-i3c-hci: use get_parity8 helper instead of open coding it
  i3c: cdns: use get_parity8 helper instead of open coding it

 drivers/hwmon/spd5118.c                  |  8 +-----
 drivers/i3c/master/dw-i3c-master.c       | 14 +++--------
 drivers/i3c/master/i3c-master-cdns.c     |  3 +--
 drivers/i3c/master/mipi-i3c-hci/dat_v1.c | 11 +--------
 include/linux/bitops.h                   | 31 ++++++++++++++++++++++++
 5 files changed, 37 insertions(+), 30 deletions(-)

-- 
2.39.2



From wsa+renesas at sang-engineering.com  Sun Dec 29 02:12:29 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Sun, 29 Dec 2024 11:12:29 +0100
Subject: [PATCH RFT v2 1/5] bitops: add generic parity calculation for u8
In-Reply-To: <20241229101234.2896-1-wsa+renesas@sang-engineering.com>
References: <20241229101234.2896-1-wsa+renesas@sang-engineering.com>
Message-ID: <20241229101234.2896-2-wsa+renesas@sang-engineering.com>

There are multiple open coded implementations for getting the parity of
a byte in the kernel, even using different approaches. Take the pretty
efficient version from SPD5118 driver and make it generally available by
putting it into the bitops header. As long as there is just one parity
calculation helper, the creation of a distinct 'parity.h' header was
discarded. Also, the usage of hweight8() for architectures having a
popcnt instruction is postponed until a use case within hot paths is
desired. The motivation for this patch is the frequent use of odd parity
in the I3C specification and to simplify drivers there.

Changes compared to the original SPD5118 version are the addition of
kernel documentation, switching the return type from bool to int, and
renaming the argument of the function.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
Tested-by: Guenter Roeck <linux at roeck-us.net>
Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
Acked-by: Yury Norov <yury.norov at gmail.com>
Reviewed-by: Kuan-Wei Chiu <visitorckw at gmail.com>
Tested-by: Kuan-Wei Chiu <visitorckw at gmail.com>
---
Changes since v1:

* renamed from 'get_parity8' to 'parity8'
* use XOR instead of OR in the kdoc example (Thanks, Rasmus, for both)
* rebased to 6.13-rc4

 include/linux/bitops.h | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index ba35bbf07798..c1cb53cf2f0f 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -229,6 +229,37 @@ static inline int get_count_order_long(unsigned long l)
 	return (int)fls_long(--l);
 }
 
+/**
+ * parity8 - get the parity of an u8 value
+ * @value: the value to be examined
+ *
+ * Determine the parity of the u8 argument.
+ *
+ * Returns:
+ * 0 for even parity, 1 for odd parity
+ *
+ * Note: This function informs you about the current parity. Example to bail
+ * out when parity is odd:
+ *
+ *	if (parity8(val) == 1)
+ *		return -EBADMSG;
+ *
+ * If you need to calculate a parity bit, you need to draw the conclusion from
+ * this result yourself. Example to enforce odd parity, parity bit is bit 7:
+ *
+ *	if (parity8(val) == 0)
+ *		val ^= BIT(7);
+ */
+static inline int parity8(u8 val)
+{
+	/*
+	 * One explanation of this algorithm:
+	 * https://funloop.org/codex/problem/parity/README.html
+	 */
+	val ^= val >> 4;
+	return (0x6996 >> (val & 0xf)) & 1;
+}
+
 /**
  * __ffs64 - find first set bit in a 64 bit word
  * @word: The 64 bit word
-- 
2.39.2



From wsa+renesas at sang-engineering.com  Sun Dec 29 02:12:33 2024
From: wsa+renesas at sang-engineering.com (Wolfram Sang)
Date: Sun, 29 Dec 2024 11:12:33 +0100
Subject: [PATCH RFT v2 5/5] i3c: cdns: use get_parity8 helper instead of open coding it
In-Reply-To: <20241229101234.2896-1-wsa+renesas@sang-engineering.com>
References: <20241229101234.2896-1-wsa+renesas@sang-engineering.com>
Message-ID: <20241229101234.2896-6-wsa+renesas@sang-engineering.com>

The kernel has now a generic helper for getting parity with easier to
understand semantics. Make use of it.

Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
---
Changes since v1:

* renamed from 'get_parity8' to 'parity8'
* rebased to 6.13-rc4

 drivers/i3c/master/i3c-master-cdns.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c
index 06c0592487d3..fedbe6624a1c 100644
--- a/drivers/i3c/master/i3c-master-cdns.c
+++ b/drivers/i3c/master/i3c-master-cdns.c
@@ -889,8 +889,7 @@ static u32 prepare_rr0_dev_address(u32 addr)
 	ret |= (addr & GENMASK(9, 7)) << 6;
 
 	/* RR0[0] = ~XOR(addr[6:0]) */
-	if (!(hweight8(addr & 0x7f) & 1))
-		ret |= 1;
+	ret |= parity8(addr & 0x7f) ? 0 : BIT(0);
 
 	return ret;
 }
-- 
2.39.2



From geert at linux-m68k.org  Sun Dec 29 02:49:55 2024
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Sun, 29 Dec 2024 11:49:55 +0100
Subject: [PATCH RFT v2 5/5] i3c: cdns: use get_parity8 helper instead of
 open coding it
In-Reply-To: <20241229101234.2896-6-wsa+renesas@sang-engineering.com>
References: <20241229101234.2896-1-wsa+renesas@sang-engineering.com> <20241229101234.2896-6-wsa+renesas@sang-engineering.com>
Message-ID: <CAMuHMdWSQvyLwHyci+WVtTj4rGeR-hkjw1ap52=5X29ZzVchSA@mail.gmail.com>

Hi Wolfram,

On Sun, Dec 29, 2024 at 11:13?AM Wolfram Sang
<wsa+renesas at sang-engineering.com> wrote:
> The kernel has now a generic helper for getting parity with easier to
> understand semantics. Make use of it.
>
> Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>

Thanks for your patch!

> --- a/drivers/i3c/master/i3c-master-cdns.c
> +++ b/drivers/i3c/master/i3c-master-cdns.c
> @@ -889,8 +889,7 @@ static u32 prepare_rr0_dev_address(u32 addr)
>         ret |= (addr & GENMASK(9, 7)) << 6;
>
>         /* RR0[0] = ~XOR(addr[6:0]) */
> -       if (!(hweight8(addr & 0x7f) & 1))
> -               ret |= 1;
> +       ret |= parity8(addr & 0x7f) ? 0 : BIT(0);

Perhaps keep the if()-construct, to better match the example in the
documentation in 1/5?

>
>         return ret;
>  }

Gr{oetje,eeting}s,

                        Geert


--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds


From jarkko.nikula at linux.intel.com  Tue Dec 31 03:59:03 2024
From: jarkko.nikula at linux.intel.com (Jarkko Nikula)
Date: Tue, 31 Dec 2024 13:59:03 +0200
Subject: [PATCH 1/2] i3c: mipi-i3c-hci: Add Intel specific quirk to ring resuming
Message-ID: <20241231115904.620052-1-jarkko.nikula@linux.intel.com>

MIPI I3C HCI on Intel hardware requires a quirk where ring needs to stop
and set to run again after resuming the halted controller. This is not
expected from the MIPI I3C HCI specification and is Intel specific.

Add this quirk to generic aborted transfer handling and execute it only
when ring is not in running state after a transfer error and attempted
controller resume. This is the case on Intel hardware.

It is not fully clear to me what is the ring running state in generic
hardware in such case. I would expect if ring is not running, then stop
request is a no-op and run request is either required or does the same
what controller resume would do.

Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
---
 drivers/i3c/master/mipi-i3c-hci/dma.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
index e8e56a8d2057..491dfe70b660 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
@@ -758,9 +758,26 @@ static bool hci_dma_irq_handler(struct i3c_hci *hci)
 			complete(&rh->op_done);
 
 		if (status & INTR_TRANSFER_ABORT) {
+			u32 ring_status;
+
 			dev_notice_ratelimited(&hci->master.dev,
 				"ring %d: Transfer Aborted\n", i);
 			mipi_i3c_hci_resume(hci);
+			ring_status = rh_reg_read(RING_STATUS);
+			if (!(ring_status & RING_STATUS_RUNNING) &&
+			    status & INTR_TRANSFER_COMPLETION &&
+			    status & INTR_TRANSFER_ERR) {
+				/*
+				 * Ring stop followed by run is an Intel
+				 * specific required quirk after resuming the
+				 * halted controller. Do it only when the ring
+				 * is not in running state after a transfer
+				 * error.
+				 */
+				rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE);
+				rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE |
+							   RING_CTRL_RUN_STOP);
+			}
 		}
 		if (status & INTR_WARN_INS_STOP_MODE)
 			dev_warn_ratelimited(&hci->master.dev,
-- 
2.45.2



From jarkko.nikula at linux.intel.com  Tue Dec 31 03:59:04 2024
From: jarkko.nikula at linux.intel.com (Jarkko Nikula)
Date: Tue, 31 Dec 2024 13:59:04 +0200
Subject: [PATCH 2/2] i3c: mipi-i3c-hci: Add support for MIPI I3C HCI on PCI bus
In-Reply-To: <20241231115904.620052-1-jarkko.nikula@linux.intel.com>
References: <20241231115904.620052-1-jarkko.nikula@linux.intel.com>
Message-ID: <20241231115904.620052-2-jarkko.nikula@linux.intel.com>

Add a glue code for the MIPI I3C HCI on PCI bus with Intel Panther Lake
I3C controller PCI IDs.

MIPI I3C HCI on Intel platforms has additional logic around the MIPI I3C
HCI core logic. Those together create so called I3C slice on PCI bus.
Intel specific initialization code does a reset cycle to the I3C slice
before probing the MIPI I3C HCI part.

Signed-off-by: Jarkko Nikula <jarkko.nikula at linux.intel.com>
---
 drivers/i3c/master/Kconfig                    |  11 ++
 drivers/i3c/master/mipi-i3c-hci/Makefile      |   1 +
 .../master/mipi-i3c-hci/mipi-i3c-hci-pci.c    | 148 ++++++++++++++++++
 3 files changed, 160 insertions(+)
 create mode 100644 drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c

diff --git a/drivers/i3c/master/Kconfig b/drivers/i3c/master/Kconfig
index 90dee3ec5520..77da199c7413 100644
--- a/drivers/i3c/master/Kconfig
+++ b/drivers/i3c/master/Kconfig
@@ -57,3 +57,14 @@ config MIPI_I3C_HCI
 
 	  This driver can also be built as a module.  If so, the module will be
 	  called mipi-i3c-hci.
+
+config MIPI_I3C_HCI_PCI
+	tristate "MIPI I3C Host Controller Interface PCI support"
+	depends on MIPI_I3C_HCI
+	depends on PCI
+	help
+	  Support for MIPI I3C Host Controller Interface compatible hardware
+	  on the PCI bus.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called mipi-i3c-hci-pci.
diff --git a/drivers/i3c/master/mipi-i3c-hci/Makefile b/drivers/i3c/master/mipi-i3c-hci/Makefile
index 1f8cd5c48fde..e3d3ef757035 100644
--- a/drivers/i3c/master/mipi-i3c-hci/Makefile
+++ b/drivers/i3c/master/mipi-i3c-hci/Makefile
@@ -5,3 +5,4 @@ mipi-i3c-hci-y				:= core.o ext_caps.o pio.o dma.o \
 					   cmd_v1.o cmd_v2.o \
 					   dat_v1.o dct_v1.o \
 					   hci_quirks.o
+obj-$(CONFIG_MIPI_I3C_HCI_PCI)		+= mipi-i3c-hci-pci.o
diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c
new file mode 100644
index 000000000000..c6c3a3ec11ea
--- /dev/null
+++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCI glue code for MIPI I3C HCI driver
+ *
+ * Copyright (C) 2024 Intel Corporation
+ *
+ * Author: Jarkko Nikula <jarkko.nikula at linux.intel.com>
+ */
+#include <linux/acpi.h>
+#include <linux/idr.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+struct mipi_i3c_hci_pci_info {
+	int (*init)(struct pci_dev *pci);
+};
+
+#define INTEL_PRIV_OFFSET		0x2b0
+#define INTEL_PRIV_SIZE			0x28
+#define INTEL_PRIV_RESETS		0x04
+#define INTEL_PRIV_RESETS_RESET		BIT(0)
+#define INTEL_PRIV_RESETS_RESET_DONE	BIT(1)
+
+static DEFINE_IDA(mipi_i3c_hci_pci_ida);
+
+static int mipi_i3c_hci_pci_intel_init(struct pci_dev *pci)
+{
+	unsigned long timeout;
+	void __iomem *priv;
+
+	priv = devm_ioremap(&pci->dev,
+			    pci_resource_start(pci, 0) + INTEL_PRIV_OFFSET,
+			    INTEL_PRIV_SIZE);
+	if (!priv)
+		return -ENOMEM;
+
+	/* Assert reset, wait for completion and release reset */
+	writel(0, priv + INTEL_PRIV_RESETS);
+	timeout = jiffies + msecs_to_jiffies(10);
+	while (!(readl(priv + INTEL_PRIV_RESETS) &
+		 INTEL_PRIV_RESETS_RESET_DONE)) {
+		if (time_after(jiffies, timeout))
+			break;
+		cpu_relax();
+	}
+	writel(INTEL_PRIV_RESETS_RESET, priv + INTEL_PRIV_RESETS);
+
+	return 0;
+}
+
+static struct mipi_i3c_hci_pci_info intel_info = {
+	.init = mipi_i3c_hci_pci_intel_init,
+};
+
+static int mipi_i3c_hci_pci_probe(struct pci_dev *pci,
+				  const struct pci_device_id *id)
+{
+	struct mipi_i3c_hci_pci_info *info;
+	struct platform_device *pdev;
+	struct resource res[2];
+	int dev_id, ret;
+
+	ret = pcim_enable_device(pci);
+	if (ret)
+		return ret;
+
+	pci_set_master(pci);
+
+	memset(&res, 0, sizeof(res));
+
+	res[0].flags = IORESOURCE_MEM;
+	res[0].start = pci_resource_start(pci, 0);
+	res[0].end = pci_resource_end(pci, 0);
+
+	res[1].flags = IORESOURCE_IRQ;
+	res[1].start = pci->irq;
+	res[1].end = pci->irq;
+
+	dev_id = ida_alloc(&mipi_i3c_hci_pci_ida, GFP_KERNEL);
+	if (dev_id < 0)
+		return dev_id;
+
+	pdev = platform_device_alloc("mipi-i3c-hci", dev_id);
+	if (!pdev)
+		return -ENOMEM;
+
+	pdev->dev.parent = &pci->dev;
+	device_set_node(&pdev->dev, dev_fwnode(&pci->dev));
+
+	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
+	if (ret)
+		goto err;
+
+	info = (struct mipi_i3c_hci_pci_info *)id->driver_data;
+	if (info && info->init) {
+		ret = info->init(pci);
+		if (ret)
+			goto err;
+	}
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto err;
+
+	pci_set_drvdata(pci, pdev);
+
+	return 0;
+
+err:
+	platform_device_put(pdev);
+	ida_free(&mipi_i3c_hci_pci_ida, dev_id);
+	return ret;
+}
+
+static void mipi_i3c_hci_pci_remove(struct pci_dev *pci)
+{
+	struct platform_device *pdev = pci_get_drvdata(pci);
+	int dev_id = pdev->id;
+
+	platform_device_unregister(pdev);
+	ida_free(&mipi_i3c_hci_pci_ida, dev_id);
+}
+
+static const struct pci_device_id mipi_i3c_hci_pci_devices[] = {
+	/* Panther Lake-H */
+	{ PCI_VDEVICE(INTEL, 0xe37c), (kernel_ulong_t)&intel_info},
+	{ PCI_VDEVICE(INTEL, 0xe36f), (kernel_ulong_t)&intel_info},
+	/* Panther Lake-P */
+	{ PCI_VDEVICE(INTEL, 0xe47c), (kernel_ulong_t)&intel_info},
+	{ PCI_VDEVICE(INTEL, 0xe46f), (kernel_ulong_t)&intel_info},
+	{ },
+};
+MODULE_DEVICE_TABLE(pci, mipi_i3c_hci_pci_devices);
+
+static struct pci_driver mipi_i3c_hci_pci_driver = {
+	.name = "mipi_i3c_hci_pci",
+	.id_table = mipi_i3c_hci_pci_devices,
+	.probe = mipi_i3c_hci_pci_probe,
+	.remove = mipi_i3c_hci_pci_remove,
+};
+
+module_pci_driver(mipi_i3c_hci_pci_driver);
+
+MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula at intel.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MIPI I3C HCI driver on PCI bus");
-- 
2.45.2



From linux at treblig.org  Sat Dec 21 06:34:32 2024
From: linux at treblig.org (linux at treblig.org)
Date: Sat, 21 Dec 2024 14:34:32 -0000
Subject: [PATCH] i3c: Remove unused i3c_device_do_setdasa
Message-ID: <20241221143418.86012-1-linux@treblig.org>

From: "Dr. David Alan Gilbert" <linux at treblig.org>

i3c_device_do_setdasa() was added in 2022 as part of
commit 672825cd2823 ("i3c: export SETDASA method")

but has been unused.

It calls i3c_dev_setdasa_locked() which is now also unused.

Remove them both.
(This is effectively a revert of 672825cd2823).

Signed-off-by: Dr. David Alan Gilbert <linux at treblig.org>
---
 drivers/i3c/device.c       | 20 --------------------
 drivers/i3c/internals.h    |  1 -
 drivers/i3c/master.c       | 19 -------------------
 include/linux/i3c/device.h |  2 --
 4 files changed, 42 deletions(-)

diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c
index e80e48756914..984976f28314 100644
--- a/drivers/i3c/device.c
+++ b/drivers/i3c/device.c
@@ -54,26 +54,6 @@ int i3c_device_do_priv_xfers(struct i3c_device *dev,
 }
 EXPORT_SYMBOL_GPL(i3c_device_do_priv_xfers);
 
-/**
- * i3c_device_do_setdasa() - do I3C dynamic address assignement with
- *                           static address
- *
- * @dev: device with which the DAA should be done
- *
- * Return: 0 in case of success, a negative error core otherwise.
- */
-int i3c_device_do_setdasa(struct i3c_device *dev)
-{
-	int ret;
-
-	i3c_bus_normaluse_lock(dev->bus);
-	ret = i3c_dev_setdasa_locked(dev->desc);
-	i3c_bus_normaluse_unlock(dev->bus);
-
-	return ret;
-}
-EXPORT_SYMBOL_GPL(i3c_device_do_setdasa);
-
 /**
  * i3c_device_get_info() - get I3C device information
  *
diff --git a/drivers/i3c/internals.h b/drivers/i3c/internals.h
index 433f6088b7ce..842e1a865877 100644
--- a/drivers/i3c/internals.h
+++ b/drivers/i3c/internals.h
@@ -13,7 +13,6 @@
 void i3c_bus_normaluse_lock(struct i3c_bus *bus);
 void i3c_bus_normaluse_unlock(struct i3c_bus *bus);
 
-int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev);
 int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev,
 				 struct i3c_priv_xfer *xfers,
 				 int nxfers);
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 42310c9a00c2..000187339400 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2916,25 +2916,6 @@ void i3c_master_unregister(struct i3c_master_controller *master)
 }
 EXPORT_SYMBOL_GPL(i3c_master_unregister);
 
-int i3c_dev_setdasa_locked(struct i3c_dev_desc *dev)
-{
-	struct i3c_master_controller *master;
-
-	if (!dev)
-		return -ENOENT;
-
-	master = i3c_dev_get_master(dev);
-	if (!master)
-		return -EINVAL;
-
-	if (!dev->boardinfo || !dev->boardinfo->init_dyn_addr ||
-		!dev->boardinfo->static_addr)
-		return -EINVAL;
-
-	return i3c_master_setdasa_locked(master, dev->info.static_addr,
-						dev->boardinfo->init_dyn_addr);
-}
-
 int i3c_dev_do_priv_xfers_locked(struct i3c_dev_desc *dev,
 				 struct i3c_priv_xfer *xfers,
 				 int nxfers)
diff --git a/include/linux/i3c/device.h b/include/linux/i3c/device.h
index 0a8a44ac2f02..f4e924c179d7 100644
--- a/include/linux/i3c/device.h
+++ b/include/linux/i3c/device.h
@@ -301,8 +301,6 @@ int i3c_device_do_priv_xfers(struct i3c_device *dev,
 			     struct i3c_priv_xfer *xfers,
 			     int nxfers);
 
-int i3c_device_do_setdasa(struct i3c_device *dev);
-
 void i3c_device_get_info(const struct i3c_device *dev, struct i3c_device_info *info);
 
 struct i3c_ibi_payload {
-- 
2.47.1



From david.laight.linux at gmail.com  Sun Dec 29 03:11:29 2024
From: david.laight.linux at gmail.com (David Laight)
Date: Sun, 29 Dec 2024 11:11:29 +0000
Subject: [PATCH RFT v2 1/5] bitops: add generic parity calculation for
 u8
In-Reply-To: <20241229101234.2896-2-wsa+renesas@sang-engineering.com>
References: <20241229101234.2896-1-wsa+renesas@sang-engineering.com>
	<20241229101234.2896-2-wsa+renesas@sang-engineering.com>
Message-ID: <20241229111129.2602d219@dsl-u17-10>

On Sun, 29 Dec 2024 11:12:29 +0100
Wolfram Sang <wsa+renesas at sang-engineering.com> wrote:

> There are multiple open coded implementations for getting the parity of
> a byte in the kernel, even using different approaches. Take the pretty
> efficient version from SPD5118 driver and make it generally available by
> putting it into the bitops header. As long as there is just one parity
> calculation helper, the creation of a distinct 'parity.h' header was
> discarded. Also, the usage of hweight8() for architectures having a
> popcnt instruction is postponed until a use case within hot paths is
> desired. The motivation for this patch is the frequent use of odd parity
> in the I3C specification and to simplify drivers there.
> 
> Changes compared to the original SPD5118 version are the addition of
> kernel documentation, switching the return type from bool to int, and
> renaming the argument of the function.
> 
> Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>
> Tested-by: Guenter Roeck <linux at roeck-us.net>
> Reviewed-by: Geert Uytterhoeven <geert+renesas at glider.be>
> Acked-by: Yury Norov <yury.norov at gmail.com>
> Reviewed-by: Kuan-Wei Chiu <visitorckw at gmail.com>
> Tested-by: Kuan-Wei Chiu <visitorckw at gmail.com>
> ---
> Changes since v1:
> 
> * renamed from 'get_parity8' to 'parity8'
> * use XOR instead of OR in the kdoc example (Thanks, Rasmus, for both)
> * rebased to 6.13-rc4
> 
>  include/linux/bitops.h | 31 +++++++++++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/include/linux/bitops.h b/include/linux/bitops.h
> index ba35bbf07798..c1cb53cf2f0f 100644
> --- a/include/linux/bitops.h
> +++ b/include/linux/bitops.h
> @@ -229,6 +229,37 @@ static inline int get_count_order_long(unsigned long l)
>  	return (int)fls_long(--l);
>  }
>  
> +/**
> + * parity8 - get the parity of an u8 value
> + * @value: the value to be examined
> + *
> + * Determine the parity of the u8 argument.
> + *
> + * Returns:
> + * 0 for even parity, 1 for odd parity

I think I'd return 0x80 for even and 0 for odd.
That just need the 'magic constant' changing and masking with 0x80.
Also rename to parity8_even() - since it returns non-zero for even parity.

> + *
> + * Note: This function informs you about the current parity. Example to bail
> + * out when parity is odd:
> + *
> + *	if (parity8(val) == 1)
> + *		return -EBADMSG;
> + *
> + * If you need to calculate a parity bit, you need to draw the conclusion from
> + * this result yourself. Example to enforce odd parity, parity bit is bit 7:
> + *
> + *	if (parity8(val) == 0)
> + *		val ^= BIT(7);

That then becomes:
	val ^= parity8_even(val);
which is what a lot of the code seems to want to do.
With your definition you could do:
	val ^= (parity8(val) << 7) ^ 0x80;

(and I'm sorry, but IMHO 0x80 is better than BIT(7))

	David

> + */
> +static inline int parity8(u8 val)
> +{
> +	/*
> +	 * One explanation of this algorithm:
> +	 * https://funloop.org/codex/problem/parity/README.html
> +	 */
> +	val ^= val >> 4;
> +	return (0x6996 >> (val & 0xf)) & 1;
> +}
> +
>  /**
>   * __ffs64 - find first set bit in a 64 bit word
>   * @word: The 64 bit word



From david.laight.linux at gmail.com  Sun Dec 29 03:33:11 2024
From: david.laight.linux at gmail.com (David Laight)
Date: Sun, 29 Dec 2024 11:33:11 +0000
Subject: [PATCH RFT v2 5/5] i3c: cdns: use get_parity8 helper instead of
 open coding it
In-Reply-To: <CAMuHMdWSQvyLwHyci+WVtTj4rGeR-hkjw1ap52=5X29ZzVchSA@mail.gmail.com>
References: <20241229101234.2896-1-wsa+renesas@sang-engineering.com>
	<20241229101234.2896-6-wsa+renesas@sang-engineering.com>
	<CAMuHMdWSQvyLwHyci+WVtTj4rGeR-hkjw1ap52=5X29ZzVchSA@mail.gmail.com>
Message-ID: <20241229113311.3b8f70d6@dsl-u17-10>

On Sun, 29 Dec 2024 11:49:55 +0100
Geert Uytterhoeven <geert at linux-m68k.org> wrote:

> Hi Wolfram,
> 
> On Sun, Dec 29, 2024 at 11:13?AM Wolfram Sang
> <wsa+renesas at sang-engineering.com> wrote:
> > The kernel has now a generic helper for getting parity with easier to
> > understand semantics. Make use of it.
> >
> > Signed-off-by: Wolfram Sang <wsa+renesas at sang-engineering.com>  
> 
> Thanks for your patch!
> 
> > --- a/drivers/i3c/master/i3c-master-cdns.c
> > +++ b/drivers/i3c/master/i3c-master-cdns.c
> > @@ -889,8 +889,7 @@ static u32 prepare_rr0_dev_address(u32 addr)
> >         ret |= (addr & GENMASK(9, 7)) << 6;
> >
> >         /* RR0[0] = ~XOR(addr[6:0]) */
> > -       if (!(hweight8(addr & 0x7f) & 1))
> > -               ret |= 1;
> > +       ret |= parity8(addr & 0x7f) ? 0 : BIT(0);  
> 
> Perhaps keep the if()-construct, to better match the example in the
> documentation in 1/5?

That line is hard to read, with parity8() returning 1 for 'odd' it could be:
	ret |= parity8(addr & 0x7f) ^ 1;
But:
	if (!parity8(addr & 0x7f))
		ret |= 1;
is probably easier to read.
But I'd change the name to parity8_odd() for clarity.
(or _even and return 0x80 for even)

	David

> 
> >
> >         return ret;
> >  }  
> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                 -- Linus Torvalds
> 



