Simplify the code,should not modify its logic.
Fixes: 761b5c30c206 ("gpio: mmio: replace open-coded for_each_set_bit()")
Signed-off-by: Yan Wang <[email protected]>
---
drivers/gpio/gpio-mmio.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index d9dff3dc92ae..c2347ef3a4df 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -271,10 +271,14 @@ static void bgpio_multiple_get_masks(struct gpio_chip *gc,
*clear_mask = 0;
for_each_set_bit(i, mask, gc->bgpio_bits) {
- if (test_bit(i, bits))
- *set_mask |= bgpio_line2mask(gc, i);
- else
- *clear_mask |= bgpio_line2mask(gc, i);
+ if (*mask == 0)
+ break;
+ if (__test_and_clear_bit(i, mask)) {
+ if (test_bit(i, bits))
+ *set_mask |= bgpio_line2mask(gc, i);
+ else
+ *clear_mask |= bgpio_line2mask(gc, i);
+ }
}
}
--
2.17.1
Hi Yan,
thanks for your patch!
On Sun, Apr 23, 2023 at 11:07 AM Yan Wang <[email protected]> wrote:
> Simplify the code,should not modify its logic.
I don't see how it simplifies the code, it seems to me that it is
making it more complex?
> Fixes: 761b5c30c206 ("gpio: mmio: replace open-coded for_each_set_bit()")
> Signed-off-by: Yan Wang <[email protected]>
> ---
> drivers/gpio/gpio-mmio.c | 12 ++++++++----
> 1 file changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
> index d9dff3dc92ae..c2347ef3a4df 100644
> --- a/drivers/gpio/gpio-mmio.c
> +++ b/drivers/gpio/gpio-mmio.c
> @@ -271,10 +271,14 @@ static void bgpio_multiple_get_masks(struct gpio_chip *gc,
> *clear_mask = 0;
>
> for_each_set_bit(i, mask, gc->bgpio_bits) {
> - if (test_bit(i, bits))
> - *set_mask |= bgpio_line2mask(gc, i);
> - else
> - *clear_mask |= bgpio_line2mask(gc, i);
> + if (*mask == 0)
> + break;
> + if (__test_and_clear_bit(i, mask)) {
> + if (test_bit(i, bits))
> + *set_mask |= bgpio_line2mask(gc, i);
> + else
> + *clear_mask |= bgpio_line2mask(gc, i);
> + }
The intention of the change seems to be to break out of the loop
when all set bits are handled, by successively masking off one
bit at a time from mask. So this is intended as an optimization,
not a simplification.
I think for_each_set_bit() is already skipping over every bit
that is zero, see include/linux/find.h.
So this optimization gains us nothing.
Yours,
Linus Walleij
On 4/24/2023 2:56 PM, Linus Walleij wrote:
> Hi Yan,
>
> thanks for your patch!
>
> On Sun, Apr 23, 2023 at 11:07 AM Yan Wang <[email protected]> wrote:
>
>> Simplify the code,should not modify its logic.
> I don't see how it simplifies the code, it seems to me that it is
> making it more complex?
yes ,it is .
The description is wrong.
>> Fixes: 761b5c30c206 ("gpio: mmio: replace open-coded for_each_set_bit()")
>> Signed-off-by: Yan Wang <[email protected]>
>> ---
>> drivers/gpio/gpio-mmio.c | 12 ++++++++----
>> 1 file changed, 8 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
>> index d9dff3dc92ae..c2347ef3a4df 100644
>> --- a/drivers/gpio/gpio-mmio.c
>> +++ b/drivers/gpio/gpio-mmio.c
>> @@ -271,10 +271,14 @@ static void bgpio_multiple_get_masks(struct gpio_chip *gc,
>> *clear_mask = 0;
>>
>> for_each_set_bit(i, mask, gc->bgpio_bits) {
>> - if (test_bit(i, bits))
>> - *set_mask |= bgpio_line2mask(gc, i);
>> - else
>> - *clear_mask |= bgpio_line2mask(gc, i);
>> + if (*mask == 0)
>> + break;
>> + if (__test_and_clear_bit(i, mask)) {
>> + if (test_bit(i, bits))
>> + *set_mask |= bgpio_line2mask(gc, i);
>> + else
>> + *clear_mask |= bgpio_line2mask(gc, i);
>> + }
> The intention of the change seems to be to break out of the loop
> when all set bits are handled, by successively masking off one
> bit at a time from mask. So this is intended as an optimization,
> not a simplification.
Because my description is wrong and there is a difference in
understanding between us.
I think using for_each_set_bit() , but the __test_and_clear_bit() should
not remove.
> I think for_each_set_bit() is already skipping over every bit
> that is zero, see include/linux/find.h.
>
> So this optimization gains us nothing.
this a patch that only restores to original logic.the
__test_and_clear_bit() clear mask
then get a new set_mask. this logic can affect functions of
gpiod_set_raw_array_value ().
The effect of this patch is as follows:
gpiod_set_raw_array_value->
gpiod_set_array_value_complex->
{
..
if (array_info && array_info->desc == desc_array &&
array_size <= array_info->size &&
(void *)array_info == desc_array + array_info->size) {
if (!can_sleep)
WARN_ON(array_info->chip->can_sleep);
if (!raw && !bitmap_empty(array_info->invert_mask, array_size))
bitmap_xor(value_bitmap, value_bitmap,
array_info->invert_mask, array_size);
gpio_chip_set_multiple(array_info->chip, array_info->set_mask,
value_bitmap);
i = find_first_zero_bit(array_info->set_mask, array_size);
if (i == array_size)
return 0;
} else {
array_info = NULL;
}
-> while (i < array_size) {
struct gpio_chip *gc = desc_array[i]->gdev->chip;
DECLARE_BITMAP(fastpath_mask, FASTPATH_NGPIO);
DECLARE_BITMAP(fastpath_bits, FASTPATH_NGPIO);
unsigned long *mask, *bits;
int count = 0;
..............
if (count != 0)
gpio_chip_set_multiple(gc, mask, bits);
..............
}
return 0;
}
Due to __test_and_clear_bit() clear array_info->set_mask,the i <
array_size condition holds.
then calculate a new mask based on the GPIO number of the hardware.
I reconfirmed it,Although it works, it should not be modified in the place.
I think have a wrong of gpiod_get_array() and not
bgpio_multiple_get_masks().
Link:
https://lore.kernel.org/linux-gpio/KL1PR01MB5448327326B6EDA8001AF714E6669@KL1PR01MB5448.apcprd01.prod.exchangelabs.com/
this is a new patch. can you take a look ?
Thank you.
> Yours,
> Linus Walleij
On Sun, Apr 23, 2023 at 05:06:48PM +0800, Yan Wang wrote:
> Simplify the code,should not modify its logic.
> Fixes: 761b5c30c206 ("gpio: mmio: replace open-coded for_each_set_bit()")
What does it fix?
...
> for_each_set_bit(i, mask, gc->bgpio_bits) {
> - if (test_bit(i, bits))
> - *set_mask |= bgpio_line2mask(gc, i);
> - else
> - *clear_mask |= bgpio_line2mask(gc, i);
> + if (*mask == 0)
> + break;
Huh?!
We never enter here if mask is 0. So, do not add a dead code, please.
Moreover, in principle mask can be longer than 1 long, this code simply wrong.
NAK
> + if (__test_and_clear_bit(i, mask)) {
> + if (test_bit(i, bits))
> + *set_mask |= bgpio_line2mask(gc, i);
> + else
> + *clear_mask |= bgpio_line2mask(gc, i);
> + }
> }
--
With Best Regards,
Andy Shevchenko
> On Apr 24, 2023, at 21:31, Andy Shevchenko <[email protected]> wrote:
>
> On Sun, Apr 23, 2023 at 05:06:48PM +0800, Yan Wang wrote:
>> Simplify the code,should not modify its logic.
>
>> Fixes: 761b5c30c206 ("gpio: mmio: replace open-coded for_each_set_bit()")
>
> What does it fix?
>
> ...
>
>> for_each_set_bit(i, mask, gc->bgpio_bits) {
>> - if (test_bit(i, bits))
>> - *set_mask |= bgpio_line2mask(gc, i);
>> - else
>> - *clear_mask |= bgpio_line2mask(gc, i);
>> + if (*mask == 0)
>> + break;
>
> Huh?!
>
> We never enter here if mask is 0. So, do not add a dead code, please.
>
> Moreover, in principle mask can be longer than 1 long, this code simply wrong.
You are right.
Because I use gpiod_set_array_value_cansleep() to set multiple gpios
occur wrong . I restored logic of the original code and found it to be effective.
So,I try to modify it.
I recheck logic of this position that it’s correct. I think there should be a error in
Gpiolib.
> NAK
>
>> + if (__test_and_clear_bit(i, mask)) {
>> + if (test_bit(i, bits))
>> + *set_mask |= bgpio_line2mask(gc, i);
>> + else
>> + *clear_mask |= bgpio_line2mask(gc, i);
>> + }
>> }
>
> --
> With Best Regards,
> Andy Shevchenko
>
>