Re: [PATCH v2 08/10] gpio: aggregator: expoose aggregator created via legacy sysfs to configfs

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

 



On Wed, Feb 12, 2025 at 04:36:13PM GMT, Geert Uytterhoeven wrote:
> Hi Den-san,
> 
> Thanks for your patch!
> 
> On Mon, 3 Feb 2025 at 04:14, Koichiro Den <koichiro.den@xxxxxxxxxxxxx> wrote:
> > Expose settings for aggregators created using the sysfs 'new_device'
> > interface to configfs. Once written to 'new_device', an "_auto.<N>" path
> > appears in the configfs regardless of whether the probe succeeds.
> > Consequently, users can no longer use that prefix for custom GPIO
> > aggregator names. The 'live' attribute changes to 1 when the probe
> > succeeds and the GPIO forwarder is instantiated.
> >
> > Note that the aggregator device created via sysfs is asynchrnous, i.e.
> 
> asynchronous
> 
> > writing into 'new_device' returns without waiting for probe completion,
> > and the probe may succeed, fail, or eventually succeed via deferred
> > probe. Thus, the 'live' attribute may change from 0 to 1 asynchronously
> > without notice. So, editting key/offset/name while it's waiting for
> 
> editing
> 
> > deferred probe is prohibited.
> >
> > The configfs auto-generation relies on create_default_group(), which
> > inherently prohibits rmdir(2). To align with the limitation, this commit
> > also prohibits mkdir(2) for them. When users want to change the number
> > of lines for an aggregator initialized via 'new_device', they need to
> > tear down the device using 'delete_device' and reconfigure it from
> > scratch. This does not break previous behaviour; users of legacy sysfs
> > interface simply gain additional almost read-only configfs exposure.
> >
> > Still, users can write into 'live' attribute to toggle the device unless
> 
> write to the
> 
> > it's waiting for deferred probe. So once probe succeeds, they can
> > deactivate it in the same manner as the devices initialized via
> > configfs.
> >
> > Signed-off-by: Koichiro Den <koichiro.den@xxxxxxxxxxxxx>
> 
> > @@ -73,6 +76,10 @@ struct gpio_aggregator_line {
> >         enum gpio_lookup_flags flags;
> >  };
> >
> > +struct gpio_aggregator_pdev_meta {
> > +       bool init_via_sysfs;
> > +};

Thanks for pointing out all of them above. Will fix them all in v3.

> 
> The use of this structure to indicate the instantiation method looks
> a bit hacky to me, but I don't see a better way...

I agree.

> 
> > +
> >  static DEFINE_MUTEX(gpio_aggregator_lock);     /* protects idr */
> >  static DEFINE_IDR(gpio_aggregator_idr);
> >
> > @@ -127,6 +134,14 @@ static bool aggr_is_active(struct gpio_aggregator *aggr)
> >         return !!aggr->pdev && platform_get_drvdata(aggr->pdev);
> >  }
> >
> > +/* Only aggregators created via legacy sysfs can be "activating". */
> > +static bool aggr_is_activating(struct gpio_aggregator *aggr)
> > +{
> > +       lockdep_assert_held(&aggr->lock);
> > +
> > +       return !!aggr->pdev && !platform_get_drvdata(aggr->pdev);
> 
> No need for "!!".

Will fix in v3.

> 
> > +}
> > +
> >  static size_t aggr_count_lines(struct gpio_aggregator *aggr)
> >  {
> >         lockdep_assert_held(&aggr->lock);
> 
> > @@ -1002,6 +1048,14 @@ gpio_aggr_make_group(struct config_group *group, const char *name)
> >         if (!aggr)
> >                 return ERR_PTR(-ENOMEM);
> >
> > +       /*
> > +        * "_auto" prefix is reserved for auto-generated config group
> > +        * for devices create via legacy sysfs interface.
> > +        */
> > +       if (strncmp(name, AGGREGATOR_LEGACY_PREFIX,
> > +                   sizeof(AGGREGATOR_LEGACY_PREFIX)) == 0)
> > +               return ERR_PTR(-EINVAL);
> 
> Missing kfree(aggr) in case of failure.

My bad. Will fix in v3.

> 
> > +
> >         mutex_lock(&gpio_aggregator_lock);
> >         aggr->id = idr_alloc(&gpio_aggregator_idr, aggr, 0, 0, GFP_KERNEL);
> >         mutex_unlock(&gpio_aggregator_lock);
> > @@ -1044,6 +1098,8 @@ static struct configfs_subsystem gpio_aggr_subsys = {
> >  static int aggr_parse(struct gpio_aggregator *aggr)
> >  {
> >         char *args = skip_spaces(aggr->args);
> > +       struct gpio_aggregator_line *line;
> > +       char name[CONFIGFS_ITEM_NAME_LEN];
> >         char *key, *offsets, *p;
> >         unsigned int i, n = 0;
> >         int error = 0;
> > @@ -1055,14 +1111,29 @@ static int aggr_parse(struct gpio_aggregator *aggr)
> >
> >         args = next_arg(args, &key, &p);
> >         while (*args) {
> > +               scnprintf(name, CONFIGFS_ITEM_NAME_LEN, "line%u", n);
> 
> sizeof(name), to protect against future changes of name[].

Right, will fix it in v3.

> 
> >  static ssize_t new_device_store(struct device_driver *driver, const char *buf,
> >                                 size_t count)
> >  {
> > +       struct gpio_aggregator_pdev_meta meta;
> 
> You might as well pre-initialize this:
> 
>    = { .init_via_sysfs = true };
>

Will do so in v3.

> > +       char name[CONFIGFS_ITEM_NAME_LEN];
> >         struct gpio_aggregator *aggr;
> >         struct platform_device *pdev;
> >         int res, id;
> > @@ -1112,6 +1210,7 @@ static ssize_t new_device_store(struct device_driver *driver, const char *buf,
> >
> >         memcpy(aggr->args, buf, count + 1);
> >
> > +       aggr->init_via_sysfs = true;
> >         aggr->lookups = kzalloc(struct_size(aggr->lookups, table, 1),
> >                                 GFP_KERNEL);
> >         if (!aggr->lookups) {
> > @@ -1128,10 +1227,22 @@ static ssize_t new_device_store(struct device_driver *driver, const char *buf,
> >                 goto free_table;
> >         }
> >
> > +       scnprintf(name, CONFIGFS_ITEM_NAME_LEN,
> 
> sizeof(name)

Will fix in v3.

> 
> > +                 "%s.%d", AGGREGATOR_LEGACY_PREFIX, id);
> > +       INIT_LIST_HEAD(&aggr->list_head);
> > +       mutex_init(&aggr->lock);
> > +       config_group_init_type_name(&aggr->group, name, &gpio_aggr_device_type);
> > +       init_completion(&aggr->probe_completion);
> 
> The code above is now almost identical to gpio_aggr_make_group().

(As I replied to your feedback to [PATCH v2 02/10]) I'll factor out the
common part and add new funcs, then use them in each.

> 
> > +
> > +       /* Expose to configfs */
> > +       res = configfs_register_group(&gpio_aggr_subsys.su_group, &aggr->group);
> > +       if (res)
> > +               goto remove_idr;
> > +
> >         aggr->lookups->dev_id = kasprintf(GFP_KERNEL, "%s.%d", DRV_NAME, id);
> >         if (!aggr->lookups->dev_id) {
> >                 res = -ENOMEM;
> > -               goto remove_idr;
> > +               goto unregister_group;
> >         }
> >
> >         res = aggr_parse(aggr);
> > @@ -1140,7 +1251,9 @@ static ssize_t new_device_store(struct device_driver *driver, const char *buf,
> >
> >         gpiod_add_lookup_table(aggr->lookups);
> >
> > -       pdev = platform_device_register_simple(DRV_NAME, id, NULL, 0);
> > +       meta.init_via_sysfs = true;
> > +
> > +       pdev = platform_device_register_data(NULL, DRV_NAME, id, &meta, sizeof(meta));
> >         if (IS_ERR(pdev)) {
> >                 res = PTR_ERR(pdev);
> >                 goto remove_table;
> 
> > @@ -1258,7 +1379,26 @@ static struct platform_driver gpio_aggregator_driver = {
> >
> >  static int __exit gpio_aggregator_idr_remove(int id, void *p, void *data)
> >  {
> > -       aggr_free(p);
> > +       /*
> > +        * There should be no aggregator created via configfs, as their
> > +        * presence would prevent module unloading.
> > +        */
> > +       struct gpio_aggregator *aggr = (struct gpio_aggregator *)p;
> 
> The cast is not needed.

Will fix in v3.

Thanks!

Koichiro

> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@xxxxxxxxxxxxxx
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                 -- Linus Torvalds




[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