Re: [PATCH v1] gpio: mmio: restroe get multiple gpio mask

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





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 <rk.code@xxxxxxxxxxx> 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 <rk.code@xxxxxxxxxxx>
---
  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@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/

this is a new patch. can you take a look ?

Thank you.
Yours,
Linus Walleij




[Index of Archives]     [Linux SPI]     [Linux Kernel]     [Linux ARM (vger)]     [Linux ARM MSM]     [Linux Omap]     [Linux Arm]     [Linux Tegra]     [Fedora ARM]     [Linux for Samsung SOC]     [eCos]     [Linux Fastboot]     [Gcc Help]     [Git]     [DCCP]     [IETF Announce]     [Security]     [Linux MIPS]     [Yosemite Campsites]

  Powered by Linux