Thread (9 messages) 9 messages, 3 authors, 2015-03-19

Re: [PATCH v5 4/4] mdio-mux-gpio: use new gpiod_get_array and gpiod_put_array functions

From: Alexandre Courbot <hidden>
Date: 2015-03-04 13:22:46
Also in: linux-gpio

On Tue, Mar 3, 2015 at 6:45 PM, Rojhalat Ibrahim [off-list ref] wrote:
On Thursday 26 February 2015 18:54:53 Alexandre Courbot wrote:
quoted
On Thu, Feb 12, 2015 at 1:28 AM, Rojhalat Ibrahim [off-list ref] wrote:
quoted
Use the new gpiod_get_array and gpiod_put_array functions for obtaining and
disposing of GPIO descriptors.

Cc: David Miller <davem@davemloft.net>
Signed-off-by: Rojhalat Ibrahim <redacted>
---
Change log:
  v5: no change
  v4: use shorter names for members of struct gpio_descs
  v3: no change
  v2: use the new interface

 drivers/net/phy/mdio-mux-gpio.c | 60 ++++++++++++-----------------------------
 1 file changed, 17 insertions(+), 43 deletions(-)
diff --git a/drivers/net/phy/mdio-mux-gpio.c b/drivers/net/phy/mdio-mux-gpio.c
index 320eb15..c49ad09 100644
--- a/drivers/net/phy/mdio-mux-gpio.c
+++ b/drivers/net/phy/mdio-mux-gpio.c
@@ -12,33 +12,30 @@
 #include <linux/module.h>
 #include <linux/phy.h>
 #include <linux/mdio-mux.h>
-#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>

 #define DRV_VERSION "1.1"
 #define DRV_DESCRIPTION "GPIO controlled MDIO bus multiplexer driver"

-#define MDIO_MUX_GPIO_MAX_BITS 8
-
 struct mdio_mux_gpio_state {
-       struct gpio_desc *gpio[MDIO_MUX_GPIO_MAX_BITS];
-       unsigned int num_gpios;
+       struct gpio_descs *gpios;
        void *mux_handle;
 };

 static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
                                   void *data)
 {
-       int values[MDIO_MUX_GPIO_MAX_BITS];
-       unsigned int n;
        struct mdio_mux_gpio_state *s = data;
+       int values[s->gpios->ndescs];
+       unsigned int n;

        if (current_child == desired_child)
                return 0;

-       for (n = 0; n < s->num_gpios; n++) {
+       for (n = 0; n < s->gpios->ndescs; n++)
                values[n] = (desired_child >> n) & 1;
-       }
-       gpiod_set_array_cansleep(s->num_gpios, s->gpio, values);
+
+       gpiod_set_array_cansleep(s->gpios->ndescs, s->gpios->desc, values);
One suggestion for a possible further improvement: it would be great
if the gpiod_set/get_array() functions would work on a struct
gpio_descs so users don't have to pass both the number of GPIOs and
the array.

I don't know whether it would be desirable to keep alternative
functions that preserve the current form, for users who want to set
multiple GPIOs but cannot use gpiod_get_array(). struct gpiod_descs is
easy to build, so maybe we don't need them?
I thought about that, but didn't want to change the interface in this
patch series.

Furthermore there is this use case (my use case):

I acquire a descriptor array for multiple data outputs and (among others) a
single descriptor for a clock output. Afterwards I want to set the data bits
and simultaneously clear the clock bit (using gpiod_set_array) before setting
only the clock output (using gpiod_set_value).

Therefore I need an array containing the data bits and the clock bit which
is easy to build.

I could also create a struct gpiod_descs but it would be more complicated
since I would have to allocate a new struct before populating it with the
descriptors and also free the allocated memory afterwards. It's not really
a big deal but more complicated than before.

But this might not be a very common use case.

If we can assume that for the common use case the group of descriptors that
can be acquired using gpiod_get_array() is the same group that should be
set using gpiod_set_array(), it might make sense to change the interface.
Ah, thanks for sharing your use-case. I wish I had heard it earlier as
it seems we should make things more flexible than they currently are.

If I followed you correctly, you need to call gpiod_get_array() to
obtain the data lines, and gpiod_get() for the clock line. Then you
need to allocate a new array of gpio_desc * and copy all the
descriptors there before calling gpiod_set_array(). So simply put, the
struct gpio_descs you obtained is just useless to you.

It seems like we have been doing things wrong. Maybe gpiod_get_array()
should simply take a pointer to a gpio_desc * array that it would
fill, as you originally proposed?

So now, the question is: do we need struct gpiod_descs at all? It can
help reducing the number of arguments passed to functions, but also
makes the whole API more rigid. Use it with gpiod_get_array(), and you
end up with unneeded copies and memory allocations. Pass it to
gpiod_set_array() and you cannot do things like setting only part of
the GPIOs you requested.

Argh, and looking closer there is some possible confusion between
gpiod_set_array() and gpiod_get_array(). One might expect the latter
to return the *values* of the GPIOs, considering the name of the
former, while it actually is the array counterpart of gpiod_get(). To
be consistent with the single descriptor API, I suppose we should
rename gpiod_set_array() to gpiod_set_array_value(). But that's a
separate issue.

For now, since you are the main user of the array API, what is your
opinion about gpiod_descs? Do you think it is worth making the API
less flexible just to not have to carry an array lengh separately?
Should we just get rid of it?
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help