On 2017-07-08 00:03, [email protected] wrote:
> From: Kuppuswamy Sathyanarayanan <[email protected]>
> 
> Currently this driver only provides a single API, mux_control_get() to
> get mux_control reference based on mux_name, and also this API has tight
> dependency on device tree node. For devices, that does not use device
> tree, it makes it difficult to use this API. This patch adds new
> API to access mux_control reference based on device name, chip index and
> controller index value.

I assume this is for the Intel USB Multiplexer that you sent a driver for
a month or so ago? If so, you still have not answered these questions:

   Is any other consumer in the charts at all? Can this existing consumer
   ever make use of some other mux? If the answer to both those questions
   are 'no', then I do not see much point in involving the mux subsystem at
   all. The Broxton USB PHY driver could just as well write to the register
   all by itself, no?

that I asked in https://lkml.org/lkml/2017/5/31/58

What is the point of that driver?

> Signed-off-by: Kuppuswamy Sathyanarayanan 
> <[email protected]>
> ---
>  drivers/mux/mux-core.c       | 114 
> +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mux/consumer.h |   6 ++-
>  2 files changed, 119 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mux/mux-core.c b/drivers/mux/mux-core.c
> index 90b8995..f8796b9 100644
> --- a/drivers/mux/mux-core.c
> +++ b/drivers/mux/mux-core.c
> @@ -422,6 +422,87 @@ static struct mux_chip *of_find_mux_chip_by_node(struct 
> device_node *np)
>       return dev ? to_mux_chip(dev) : NULL;
>  }
>  
> +static int dev_parent_name_match(struct device *dev, const void *data)
> +{
> +     const char *devname = dev_name(dev->parent);
> +     unsigned int i;
> +
> +     if (!devname || !data)
> +             return 0;
> +
> +     for (i = 0; i < strlen(devname); i++) {
> +             if (devname[i] == '.')
> +                     break;
> +     }
> +
> +     return !strncmp(devname, data, i-1);

Ouch, strlen as a termination test is wasteful, you want to remove the loop
and do something like this

        return !strncmp(devname, data, strcspn(devname, "."));

> +}
> +
> +/**
> + * mux_chip_get_by_index() - Get the mux-chip associated with give device.
> + * @devname: Name of the device which registered the mux-chip.
> + * @index: Index of the mux chip.
> + *
> + * Return: A pointer to the mux-chip, or an ERR_PTR with a negative errno.
> + */
> +static struct mux_chip *mux_chip_get_by_index(const char *devname, int index)
> +{
> +     struct device *dev;
> +     int found = -1;
> +
> +     if (!devname)
> +             return ERR_PTR(-EINVAL);
> +
> +     do {
> +             dev = class_find_device(&mux_class, NULL, devname,
> +                                     dev_parent_name_match);
> +
> +             if (dev != NULL)
> +                     found++;
> +
> +             if (found >= index)
> +                     break;
> +     } while (dev != NULL);

This loop is broken. class_find_device will always return the same device.

Also, if you fix the loop, why is the ordering stable and something to rely
on?

> +
> +     if ((found == index) && dev)
> +             return to_mux_chip(dev);
> +
> +     return ERR_PTR(-ENODEV);
> +}
> +
> +/**
> + * mux_control_get_by_index() - Get the mux-control of given device based on
> + *                           device name, chip and control index.
> + * @devname: Name of the device which registered the mux-chip.
> + * @chip_index: Index of the mux chip.
> + * @ctrl_index: Index of the mux controller.
> + *
> + * Return: A pointer to the mux-control, or an ERR_PTR with a negative errno.
> + */
> +struct mux_control *mux_control_get_by_index(const char *devname,
> +                                          unsigned int chip_index,
> +                                          unsigned int ctrl_index)
> +{
> +     struct mux_chip *mux_chip;
> +
> +     mux_chip = mux_chip_get_by_index(devname, chip_index);
> +
> +     if (IS_ERR(mux_chip))
> +             return ERR_PTR(PTR_ERR(mux_chip));
> +
> +     if (ctrl_index >= mux_chip->controllers) {
> +             dev_err(&mux_chip->dev,
> +                             "Invalid controller index, maximum value is 
> %d\n",
> +                             mux_chip->controllers);
> +             return ERR_PTR(-EINVAL);
> +     }
> +
> +     get_device(&mux_chip->dev);
> +
> +     return &mux_chip->mux[ctrl_index];
> +}
> +EXPORT_SYMBOL_GPL(mux_control_get_by_index);
> +
>  /**
>   * mux_control_get() - Get the mux-control for a device.
>   * @dev: The device that needs a mux-control.
> @@ -533,6 +614,39 @@ struct mux_control *devm_mux_control_get(struct device 
> *dev,
>  }
>  EXPORT_SYMBOL_GPL(devm_mux_control_get);
>  
> +/**
> + * devm_mux_control_get_by_index() - Get the mux-control for a device of 
> given
> + *                                index value.
> + * @dev: The device that needs a mux-control.
> + * @devname: Name of the device which registered the mux-chip.
> + * @chip_index: Index of the mux chip.
> + * @ctrl_index: Index of the mux controller.
> + *
> + * Return: Pointer to the mux-control, or an ERR_PTR with a negative errno.
> + */
> +struct mux_control *devm_mux_control_get_by_index(struct device *dev,
> +             const char *devname, unsigned int chip_index,
> +             unsigned int ctrl_index)
> +{
> +     struct mux_control **ptr, *mux;
> +
> +     ptr = devres_alloc(devm_mux_control_release, sizeof(*ptr), GFP_KERNEL);
> +     if (!ptr)
> +             return ERR_PTR(-ENOMEM);
> +
> +     mux = mux_control_get_by_index(devname, chip_index, ctrl_index);
> +     if (IS_ERR(mux)) {
> +             devres_free(ptr);
> +             return mux;
> +     }
> +
> +     *ptr = mux;
> +     devres_add(dev, ptr);
> +
> +     return mux;
> +}
> +EXPORT_SYMBOL_GPL(devm_mux_control_get_by_index);
> +
>  /*
>   * Using subsys_initcall instead of module_init here to try to ensure - for
>   * the non-modular case - that the subsystem is initialized when mux 
> consumers
> diff --git a/include/linux/mux/consumer.h b/include/linux/mux/consumer.h
> index 5577e1b..e02485b 100644
> --- a/include/linux/mux/consumer.h
> +++ b/include/linux/mux/consumer.h
> @@ -28,5 +28,9 @@ void mux_control_put(struct mux_control *mux);
>  
>  struct mux_control *devm_mux_control_get(struct device *dev,
>                                        const char *mux_name);
> -
> +struct mux_control *mux_control_get_by_index(const char *devname,
> +             unsigned int chip_index, unsigned int ctrl_index);
> +struct mux_control *devm_mux_control_get_by_index(struct device *dev,
> +             const char *devname, unsigned int chip_index,
> +             unsigned int ctrl_index);

I want an empty line here.

Cheers,
peda

>  #endif /* _LINUX_MUX_CONSUMER_H */
> 

Reply via email to