On Tue, Mar 04, 2025 at 11:18:53AM +0100, Kory Maincent wrote: > +/** > + * pse_flush_pw_ds - flush all PSE power domains of a PSE > + * @pcdev: a pointer to the initialized PSE controller device > + */ > +static void pse_flush_pw_ds(struct pse_controller_dev *pcdev) > +{ > + struct pse_power_domain *pw_d; > + int i; > + > + for (i = 0; i < pcdev->nr_lines; i++) { > + if (!pcdev->pi[i].pw_d) > + continue; > + > + pw_d = xa_load(&pse_pw_d_map, pcdev->pi[i].pw_d->id); > + if (pw_d) { > + regulator_put(pw_d->supply); > + xa_erase(&pse_pw_d_map, pw_d->id); > + } > + } > +} > + > +/** > + * devm_pse_alloc_pw_d - allocate a new PSE power domain for a device > + * @dev: device that is registering this PSE power domain > + * > + * Return: Pointer to the newly allocated PSE power domain or error pointers > + */ > +static struct pse_power_domain *devm_pse_alloc_pw_d(struct device *dev) > +{ > + struct pse_power_domain *pw_d; > + int index, ret; > + > + pw_d = devm_kzalloc(dev, sizeof(*pw_d), GFP_KERNEL); > + if (!pw_d) > + return ERR_PTR(-ENOMEM); > + > + ret = xa_alloc(&pse_pw_d_map, &index, pw_d, XA_LIMIT(1, INT_MAX), GFP_KERNEL); #define PSE_PW_D_LIMIT INT_MAX XA_LIMIT(1, PSE_PW_D_LIMIT) > + if (ret) > + return ERR_PTR(ret); > + > + pw_d->id = index; > + return pw_d; > +} > + > +/** > + * pse_register_pw_ds - register the PSE power domains for a PSE > + * @pcdev: a pointer to the PSE controller device > + * > + * Return: 0 on success and failure value on error > + */ > +static int pse_register_pw_ds(struct pse_controller_dev *pcdev) > +{ > + int i; > + > + for (i = 0; i < pcdev->nr_lines; i++) { > + struct regulator_dev *rdev = pcdev->pi[i].rdev; > + struct pse_power_domain *pw_d; > + struct regulator *supply; > + bool present = false; > + unsigned long index; > + > + /* No regulator or regulator parent supply registered. > + * We need a regulator parent to register a PSE power domain > + */ > + if (!rdev || !rdev->supply) > + continue; > + Should we use xa_lock() before iteration over the map? > + xa_for_each(&pse_pw_d_map, index, pw_d) { > + /* Power supply already registered as a PSE power > + * domain. > + */ > + if (regulator_is_equal(pw_d->supply, rdev->supply)) { > + present = true; > + pcdev->pi[i].pw_d = pw_d; > + break; > + } > + } > + if (present) > + continue; > + > + pw_d = devm_pse_alloc_pw_d(pcdev->dev); > + if (IS_ERR_OR_NULL(pw_d)) > + return PTR_ERR(pw_d); It is better to break the loop and roll back previous allocations. > + > + supply = regulator_get(&rdev->dev, rdev->supply_name); > + if (IS_ERR(supply)) { > + xa_erase(&pse_pw_d_map, pw_d->id); > + return PTR_ERR(supply); same here. > + } > + > + pw_d->supply = supply; > + pcdev->pi[i].pw_d = pw_d; > + } > + > + return 0; > +} -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |