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 |
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); > } >
> > @@ -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?
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>
> 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!
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
> > > > - (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.
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
> > 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 --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); }
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(-)