diff mbox series

[RFT,v2,4/5] i3c: mipi-i3c-hci: use get_parity8 helper instead of open coding it

Message ID 20241229101234.2896-5-wsa+renesas@sang-engineering.com (mailing list archive)
State New
Delegated to: Geert Uytterhoeven
Headers show
Series i3c: introduce and use generic parity helper | expand

Commit Message

Wolfram Sang Dec. 29, 2024, 10:12 a.m. UTC
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@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(-)

Comments

David Laight Jan. 1, 2025, 12:14 p.m. UTC | #1
On Sun, 29 Dec 2024 11:12:32 +0100
Wolfram Sang <wsa+renesas@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@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);

NAK - that isn't the same code at all.

	David

>  	dat_w0_write(dat_idx, dat_w0);
>  }
>
Wolfram Sang Jan. 2, 2025, 9:01 a.m. UTC | #2
> > @@ -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);
> 
> NAK - that isn't the same code at all.

But the same algorithm? Please elaborate where you think the new code
will fail compared to the old one. And frankly, are you aware of
different parity calculations? Have you read the link which was in the
kdocs of my new function?
Jarkko Nikula Jan. 2, 2025, 2:19 p.m. UTC | #3
On 12/29/24 12:12 PM, Wolfram Sang 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@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(-)
> 
Please rename s/get_parity8/parity8/ also in the subject line of patches 
3-5.

For this patch:

Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Wolfram Sang Jan. 2, 2025, 2:46 p.m. UTC | #4
> Please rename s/get_parity8/parity8/ also in the subject line of patches
> 3-5.

Oops, yes, will fix!

> For this patch:
> 
> Tested-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>

Thank you!
David Laight Jan. 2, 2025, 6:51 p.m. UTC | #5
On Thu, 2 Jan 2025 10:01:48 +0100
Wolfram Sang <wsa+renesas@sang-engineering.com> wrote:

> > > @@ -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);  
> > 
> > NAK - that isn't the same code at all.  
> 
> But the same algorithm? Please elaborate where you think the new code
> will fail compared to the old one. And frankly, are you aware of
> different parity calculations? Have you read the link which was in the
> kdocs of my new function?
> 

The old code is:
> -static inline bool dynaddr_parity(unsigned int addr)
> -{
> -	addr |= 1 << 7;
> -	addr += addr >> 4;
> -	addr += addr >> 2;
> -	addr += addr >> 1;
> -	return (addr & 1);
> -}

So:
1) it always sets 0x80.
2) it uses addition not exclusive or.

So just not the same definition of 'parity'.

	David
Wolfram Sang Jan. 3, 2025, 10:02 a.m. UTC | #6
> > > > -		  (dynaddr_parity(address) ? DAT_0_DYNADDR_PARITY : 0);
> > > > +		  (parity8(address) ? 0 : DAT_0_DYNADDR_PARITY);  

...

> The old code is:
> > -static inline bool dynaddr_parity(unsigned int addr)
> > -{
> > -	addr |= 1 << 7;
> > -	addr += addr >> 4;
> > -	addr += addr >> 2;
> > -	addr += addr >> 1;
> > -	return (addr & 1);
> > -}
> 
> So:
> 1) it always sets 0x80.

Right, this is why the arguments of the ternary operator above are
exchanged. The old function was basically 'is_odd'.

> 2) it uses addition not exclusive or.

True, but it will work nonetheless because we are only interested in bit
0 of the result. For one bit, XOR and addition are interchangable. The
overflow to other bits is not important.

> So just not the same definition of 'parity'.

I think it is. I mean, I3C wants odd parity, otherwise it will not work.
And Jarkko kindly confirmed it still works.
David Laight Jan. 3, 2025, 1:49 p.m. UTC | #7
On Fri, 3 Jan 2025 11:02:30 +0100
Wolfram Sang <wsa+renesas@sang-engineering.com> wrote:

> > > > > -		  (dynaddr_parity(address) ? DAT_0_DYNADDR_PARITY : 0);
> > > > > +		  (parity8(address) ? 0 : DAT_0_DYNADDR_PARITY);    
> 
> ...
> 
> > The old code is:  
> > > -static inline bool dynaddr_parity(unsigned int addr)
> > > -{
> > > -	addr |= 1 << 7;
> > > -	addr += addr >> 4;
> > > -	addr += addr >> 2;
> > > -	addr += addr >> 1;
> > > -	return (addr & 1);
> > > -}  
> > 
> > So:
> > 1) it always sets 0x80.  
> 
> Right, this is why the arguments of the ternary operator above are
> exchanged. The old function was basically 'is_odd'.

Provided the high bit isn't already set - which it may not be.

> > 2) it uses addition not exclusive or.  
> 
> True, but it will work nonetheless because we are only interested in bit
> 0 of the result. For one bit, XOR and addition are interchangable. The
> overflow to other bits is not important.

add: 00010001 => xxxx0010 => xx10 => x1
xor: 00010001 => xxxx0000 => 00xx => x0

> 
> > So just not the same definition of 'parity'.  
> 
> I think it is. I mean, I3C wants odd parity, otherwise it will not work.
> And Jarkko kindly confirmed it still works.

I bet the target isn't checking...

So you might be fixing a bug.

	David
Wolfram Sang Jan. 3, 2025, 9:17 p.m. UTC | #8
> > Right, this is why the arguments of the ternary operator above are
> > exchanged. The old function was basically 'is_odd'.
> 
> Provided the high bit isn't already set - which it may not be.

Not here. Temporary I3C addresses are in the range 0-0x7f.

> add: 00010001 => xxxx0010 => xx10 => x1
> xor: 00010001 => xxxx0000 => 00xx => x0

This point goes to you :)

> I bet the target isn't checking...

Could be, I can't tell. I don't have this HW.

> So you might be fixing a bug.

Heh, which better argument could one have for a generic implementation.
diff mbox series

Patch

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);
 }