Message ID | 20191210164014.50739-2-paul@crapouillou.net (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [v4,1/5] dt-bindings: Document JZ47xx VPU auxiliary processor | expand |
Hi Paul, Good initiative! See me remarks below. On 10/12/2019 5:40 PM, Paul Cercueil wrote: > Add API functions devm_rproc_alloc() and devm_rproc_add(), which behave > like rproc_alloc() and rproc_add() respectively, but register their > respective cleanup function to be called on driver detach. > > Signed-off-by: Paul Cercueil <paul@crapouillou.net> > --- > > Notes: > v3: New patch > v4: No change > > drivers/remoteproc/remoteproc_core.c | 67 ++++++++++++++++++++++++++++ > include/linux/remoteproc.h | 5 +++ > 2 files changed, 72 insertions(+) > > diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c > index 307df98347ba..0a9fc7fdd1c3 100644 > --- a/drivers/remoteproc/remoteproc_core.c > +++ b/drivers/remoteproc/remoteproc_core.c Maybe these devm function shall be defined in a new remoteproc/devres.c file. Although it seems to be a common usage I don't know if there is a rule for that. > @@ -1932,6 +1932,33 @@ int rproc_add(struct rproc *rproc) > } > EXPORT_SYMBOL(rproc_add); > > +static void devm_rproc_remove(void *rproc) > +{ > + rproc_del(rproc); > +} > + > +/** > + * devm_rproc_add() - resource managed rproc_add() > + * @dev: the underlying device > + * @rproc: the remote processor handle to register > + * > + * This function performs like rproc_add() but the registered rproc device will > + * automatically be removed on driver detach. > + * > + * Returns 0 on success and an appropriate error code otherwise. > + */ > +int devm_rproc_add(struct device *dev, struct rproc *rproc) > +{ > + int err; > + > + err = rproc_add(rproc); > + if (err) > + return err; > + > + return devm_add_action_or_reset(dev, devm_rproc_remove, rproc); > +} > +EXPORT_SYMBOL(devm_rproc_add); > + > /** > * rproc_type_release() - release a remote processor instance > * @dev: the rproc's device > @@ -2149,6 +2176,46 @@ int rproc_del(struct rproc *rproc) > } > EXPORT_SYMBOL(rproc_del); > > +static void devm_rproc_free(struct device *dev, void *res) > +{ > + rproc_free(*(struct rproc **)res); > +} > + > +/** > + * devm_rproc_alloc() - resource managed rproc_alloc() > + * @dev: the underlying device > + * @name: name of this remote processor > + * @ops: platform-specific handlers (mainly start/stop) > + * @firmware: name of firmware file to load, can be NULL > + * @len: length of private data needed by the rproc driver (in bytes) > + * > + * This function performs like rproc_alloc() but the acuired rproc device will typo: s/acuired/acquired > + * automatically be released on driver detach. > + * > + * On success the new rproc is returned, and on failure, NULL. > + */ > +struct rproc *devm_rproc_alloc(struct device *dev, const char *name, > + const struct rproc_ops *ops, > + const char *firmware, int len) > +{ > + struct rproc **ptr, *rproc; > + > + ptr = devres_alloc(devm_rproc_free, sizeof(*ptr), GFP_KERNEL); > + if (!ptr) > + return ERR_PTR(-ENOMEM); > + > + rproc = rproc_alloc(dev, name, ops, firmware, len); > + if (rproc) { > + *ptr = rproc; > + devres_add(dev, ptr); > + } else { > + devres_free(ptr); > + } > + > + return rproc; Can't you use devm_add_action_or_reset() here too? > +} > +EXPORT_SYMBOL(devm_rproc_alloc); > + > /** > * rproc_add_subdev() - add a subdevice to a remoteproc > * @rproc: rproc handle to add the subdevice to > diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h > index 16ad66683ad0..5f201f0c86c3 100644 > --- a/include/linux/remoteproc.h > +++ b/include/linux/remoteproc.h > @@ -595,6 +595,11 @@ int rproc_add(struct rproc *rproc); > int rproc_del(struct rproc *rproc); > void rproc_free(struct rproc *rproc); > > +struct rproc *devm_rproc_alloc(struct device *dev, const char *name, > + const struct rproc_ops *ops, > + const char *firmware, int len); > +int devm_rproc_add(struct device *dev, struct rproc *rproc); > + > void rproc_add_carveout(struct rproc *rproc, struct rproc_mem_entry *mem); > > struct rproc_mem_entry * BR Fabien
Hi Fabien, Le jeu., déc. 12, 2019 at 09:43, Fabien DESSENNE <fabien.dessenne@st.com> a écrit : > Hi Paul, > > > Good initiative! See me remarks below. > > > On 10/12/2019 5:40 PM, Paul Cercueil wrote: >> Add API functions devm_rproc_alloc() and devm_rproc_add(), which >> behave >> like rproc_alloc() and rproc_add() respectively, but register their >> respective cleanup function to be called on driver detach. >> >> Signed-off-by: Paul Cercueil <paul@crapouillou.net> >> --- >> >> Notes: >> v3: New patch >> v4: No change >> >> drivers/remoteproc/remoteproc_core.c | 67 >> ++++++++++++++++++++++++++++ >> include/linux/remoteproc.h | 5 +++ >> 2 files changed, 72 insertions(+) >> >> diff --git a/drivers/remoteproc/remoteproc_core.c >> b/drivers/remoteproc/remoteproc_core.c >> index 307df98347ba..0a9fc7fdd1c3 100644 >> --- a/drivers/remoteproc/remoteproc_core.c >> +++ b/drivers/remoteproc/remoteproc_core.c > > > Maybe these devm function shall be defined in a new > remoteproc/devres.c > file. Although it seems to be a common usage I don't know if there is > a > rule for that. It's not a rule, more like a good practice. I'll do that. > >> @@ -1932,6 +1932,33 @@ int rproc_add(struct rproc *rproc) >> } >> EXPORT_SYMBOL(rproc_add); >> >> +static void devm_rproc_remove(void *rproc) >> +{ >> + rproc_del(rproc); >> +} >> + >> +/** >> + * devm_rproc_add() - resource managed rproc_add() >> + * @dev: the underlying device >> + * @rproc: the remote processor handle to register >> + * >> + * This function performs like rproc_add() but the registered >> rproc device will >> + * automatically be removed on driver detach. >> + * >> + * Returns 0 on success and an appropriate error code otherwise. >> + */ >> +int devm_rproc_add(struct device *dev, struct rproc *rproc) >> +{ >> + int err; >> + >> + err = rproc_add(rproc); >> + if (err) >> + return err; >> + >> + return devm_add_action_or_reset(dev, devm_rproc_remove, rproc); >> +} >> +EXPORT_SYMBOL(devm_rproc_add); >> + >> /** >> * rproc_type_release() - release a remote processor instance >> * @dev: the rproc's device >> @@ -2149,6 +2176,46 @@ int rproc_del(struct rproc *rproc) >> } >> EXPORT_SYMBOL(rproc_del); >> >> +static void devm_rproc_free(struct device *dev, void *res) >> +{ >> + rproc_free(*(struct rproc **)res); >> +} >> + >> +/** >> + * devm_rproc_alloc() - resource managed rproc_alloc() >> + * @dev: the underlying device >> + * @name: name of this remote processor >> + * @ops: platform-specific handlers (mainly start/stop) >> + * @firmware: name of firmware file to load, can be NULL >> + * @len: length of private data needed by the rproc driver (in >> bytes) >> + * >> + * This function performs like rproc_alloc() but the acuired rproc >> device will > > > typo: s/acuired/acquired > > >> + * automatically be released on driver detach. >> + * >> + * On success the new rproc is returned, and on failure, NULL. >> + */ >> +struct rproc *devm_rproc_alloc(struct device *dev, const char >> *name, >> + const struct rproc_ops *ops, >> + const char *firmware, int len) >> +{ >> + struct rproc **ptr, *rproc; >> + >> + ptr = devres_alloc(devm_rproc_free, sizeof(*ptr), GFP_KERNEL); >> + if (!ptr) >> + return ERR_PTR(-ENOMEM); >> + >> + rproc = rproc_alloc(dev, name, ops, firmware, len); >> + if (rproc) { >> + *ptr = rproc; >> + devres_add(dev, ptr); >> + } else { >> + devres_free(ptr); >> + } >> + >> + return rproc; > > > Can't you use devm_add_action_or_reset() here too? Yes, I guess that will make things simpler. Thanks, -Paul > >> +} >> +EXPORT_SYMBOL(devm_rproc_alloc); >> + >> /** >> * rproc_add_subdev() - add a subdevice to a remoteproc >> * @rproc: rproc handle to add the subdevice to >> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h >> index 16ad66683ad0..5f201f0c86c3 100644 >> --- a/include/linux/remoteproc.h >> +++ b/include/linux/remoteproc.h >> @@ -595,6 +595,11 @@ int rproc_add(struct rproc *rproc); >> int rproc_del(struct rproc *rproc); >> void rproc_free(struct rproc *rproc); >> >> +struct rproc *devm_rproc_alloc(struct device *dev, const char >> *name, >> + const struct rproc_ops *ops, >> + const char *firmware, int len); >> +int devm_rproc_add(struct device *dev, struct rproc *rproc); >> + >> void rproc_add_carveout(struct rproc *rproc, struct >> rproc_mem_entry *mem); >> >> struct rproc_mem_entry * > > > BR > > Fabien
Hi Paul, I tested it on our driver and freeing/remove are called correctly on probe error and on module removal. Tested-By: Clement Leger <cleger@kalray.eu> Regards, Clément ----- On 10 Dec, 2019, at 17:40, Paul Cercueil paul@crapouillou.net wrote: > Add API functions devm_rproc_alloc() and devm_rproc_add(), which behave > like rproc_alloc() and rproc_add() respectively, but register their > respective cleanup function to be called on driver detach. > > Signed-off-by: Paul Cercueil <paul@crapouillou.net> > --- > > Notes: > v3: New patch > v4: No change > > drivers/remoteproc/remoteproc_core.c | 67 ++++++++++++++++++++++++++++ > include/linux/remoteproc.h | 5 +++ > 2 files changed, 72 insertions(+) > > diff --git a/drivers/remoteproc/remoteproc_core.c > b/drivers/remoteproc/remoteproc_core.c > index 307df98347ba..0a9fc7fdd1c3 100644 > --- a/drivers/remoteproc/remoteproc_core.c > +++ b/drivers/remoteproc/remoteproc_core.c > @@ -1932,6 +1932,33 @@ int rproc_add(struct rproc *rproc) > } > EXPORT_SYMBOL(rproc_add); > > +static void devm_rproc_remove(void *rproc) > +{ > + rproc_del(rproc); > +} > + > +/** > + * devm_rproc_add() - resource managed rproc_add() > + * @dev: the underlying device > + * @rproc: the remote processor handle to register > + * > + * This function performs like rproc_add() but the registered rproc device will > + * automatically be removed on driver detach. > + * > + * Returns 0 on success and an appropriate error code otherwise. > + */ > +int devm_rproc_add(struct device *dev, struct rproc *rproc) > +{ > + int err; > + > + err = rproc_add(rproc); > + if (err) > + return err; > + > + return devm_add_action_or_reset(dev, devm_rproc_remove, rproc); > +} > +EXPORT_SYMBOL(devm_rproc_add); > + > /** > * rproc_type_release() - release a remote processor instance > * @dev: the rproc's device > @@ -2149,6 +2176,46 @@ int rproc_del(struct rproc *rproc) > } > EXPORT_SYMBOL(rproc_del); > > +static void devm_rproc_free(struct device *dev, void *res) > +{ > + rproc_free(*(struct rproc **)res); > +} > + > +/** > + * devm_rproc_alloc() - resource managed rproc_alloc() > + * @dev: the underlying device > + * @name: name of this remote processor > + * @ops: platform-specific handlers (mainly start/stop) > + * @firmware: name of firmware file to load, can be NULL > + * @len: length of private data needed by the rproc driver (in bytes) > + * > + * This function performs like rproc_alloc() but the acuired rproc device will > + * automatically be released on driver detach. > + * > + * On success the new rproc is returned, and on failure, NULL. > + */ > +struct rproc *devm_rproc_alloc(struct device *dev, const char *name, > + const struct rproc_ops *ops, > + const char *firmware, int len) > +{ > + struct rproc **ptr, *rproc; > + > + ptr = devres_alloc(devm_rproc_free, sizeof(*ptr), GFP_KERNEL); > + if (!ptr) > + return ERR_PTR(-ENOMEM); > + > + rproc = rproc_alloc(dev, name, ops, firmware, len); > + if (rproc) { > + *ptr = rproc; > + devres_add(dev, ptr); > + } else { > + devres_free(ptr); > + } > + > + return rproc; > +} > +EXPORT_SYMBOL(devm_rproc_alloc); > + > /** > * rproc_add_subdev() - add a subdevice to a remoteproc > * @rproc: rproc handle to add the subdevice to > diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h > index 16ad66683ad0..5f201f0c86c3 100644 > --- a/include/linux/remoteproc.h > +++ b/include/linux/remoteproc.h > @@ -595,6 +595,11 @@ int rproc_add(struct rproc *rproc); > int rproc_del(struct rproc *rproc); > void rproc_free(struct rproc *rproc); > > +struct rproc *devm_rproc_alloc(struct device *dev, const char *name, > + const struct rproc_ops *ops, > + const char *firmware, int len); > +int devm_rproc_add(struct device *dev, struct rproc *rproc); > + > void rproc_add_carveout(struct rproc *rproc, struct rproc_mem_entry *mem); > > struct rproc_mem_entry * > -- > 2.24.0
Hi Clément, Le lun., déc. 16, 2019 at 11:46, Clément Leger <cleger@kalray.eu> a écrit : > Hi Paul, > > I tested it on our driver and freeing/remove are called correctly on > probe error and on module removal. > > Tested-By: Clement Leger <cleger@kalray.eu> Great, thanks. Did you also test the prepare/unprepare callbacks? Is it working for you? Thanks, -Paul > ----- On 10 Dec, 2019, at 17:40, Paul Cercueil paul@crapouillou.net > wrote: > >> Add API functions devm_rproc_alloc() and devm_rproc_add(), which >> behave >> like rproc_alloc() and rproc_add() respectively, but register their >> respective cleanup function to be called on driver detach. >> >> Signed-off-by: Paul Cercueil <paul@crapouillou.net> >> --- >> >> Notes: >> v3: New patch >> v4: No change >> >> drivers/remoteproc/remoteproc_core.c | 67 >> ++++++++++++++++++++++++++++ >> include/linux/remoteproc.h | 5 +++ >> 2 files changed, 72 insertions(+) >> >> diff --git a/drivers/remoteproc/remoteproc_core.c >> b/drivers/remoteproc/remoteproc_core.c >> index 307df98347ba..0a9fc7fdd1c3 100644 >> --- a/drivers/remoteproc/remoteproc_core.c >> +++ b/drivers/remoteproc/remoteproc_core.c >> @@ -1932,6 +1932,33 @@ int rproc_add(struct rproc *rproc) >> } >> EXPORT_SYMBOL(rproc_add); >> >> +static void devm_rproc_remove(void *rproc) >> +{ >> + rproc_del(rproc); >> +} >> + >> +/** >> + * devm_rproc_add() - resource managed rproc_add() >> + * @dev: the underlying device >> + * @rproc: the remote processor handle to register >> + * >> + * This function performs like rproc_add() but the registered >> rproc device will >> + * automatically be removed on driver detach. >> + * >> + * Returns 0 on success and an appropriate error code otherwise. >> + */ >> +int devm_rproc_add(struct device *dev, struct rproc *rproc) >> +{ >> + int err; >> + >> + err = rproc_add(rproc); >> + if (err) >> + return err; >> + >> + return devm_add_action_or_reset(dev, devm_rproc_remove, rproc); >> +} >> +EXPORT_SYMBOL(devm_rproc_add); >> + >> /** >> * rproc_type_release() - release a remote processor instance >> * @dev: the rproc's device >> @@ -2149,6 +2176,46 @@ int rproc_del(struct rproc *rproc) >> } >> EXPORT_SYMBOL(rproc_del); >> >> +static void devm_rproc_free(struct device *dev, void *res) >> +{ >> + rproc_free(*(struct rproc **)res); >> +} >> + >> +/** >> + * devm_rproc_alloc() - resource managed rproc_alloc() >> + * @dev: the underlying device >> + * @name: name of this remote processor >> + * @ops: platform-specific handlers (mainly start/stop) >> + * @firmware: name of firmware file to load, can be NULL >> + * @len: length of private data needed by the rproc driver (in >> bytes) >> + * >> + * This function performs like rproc_alloc() but the acuired rproc >> device will >> + * automatically be released on driver detach. >> + * >> + * On success the new rproc is returned, and on failure, NULL. >> + */ >> +struct rproc *devm_rproc_alloc(struct device *dev, const char >> *name, >> + const struct rproc_ops *ops, >> + const char *firmware, int len) >> +{ >> + struct rproc **ptr, *rproc; >> + >> + ptr = devres_alloc(devm_rproc_free, sizeof(*ptr), GFP_KERNEL); >> + if (!ptr) >> + return ERR_PTR(-ENOMEM); >> + >> + rproc = rproc_alloc(dev, name, ops, firmware, len); >> + if (rproc) { >> + *ptr = rproc; >> + devres_add(dev, ptr); >> + } else { >> + devres_free(ptr); >> + } >> + >> + return rproc; >> +} >> +EXPORT_SYMBOL(devm_rproc_alloc); >> + >> /** >> * rproc_add_subdev() - add a subdevice to a remoteproc >> * @rproc: rproc handle to add the subdevice to >> diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h >> index 16ad66683ad0..5f201f0c86c3 100644 >> --- a/include/linux/remoteproc.h >> +++ b/include/linux/remoteproc.h >> @@ -595,6 +595,11 @@ int rproc_add(struct rproc *rproc); >> int rproc_del(struct rproc *rproc); >> void rproc_free(struct rproc *rproc); >> >> +struct rproc *devm_rproc_alloc(struct device *dev, const char >> *name, >> + const struct rproc_ops *ops, >> + const char *firmware, int len); >> +int devm_rproc_add(struct device *dev, struct rproc *rproc); >> + >> void rproc_add_carveout(struct rproc *rproc, struct rproc_mem_entry >> *mem); >> >> struct rproc_mem_entry * >> -- >> 2.24.0
On Thu 12 Dec 01:43 PST 2019, Fabien DESSENNE wrote: > Hi Paul, > > > Good initiative! See me remarks below. > I concur! > > On 10/12/2019 5:40 PM, Paul Cercueil wrote: > > Add API functions devm_rproc_alloc() and devm_rproc_add(), which behave > > like rproc_alloc() and rproc_add() respectively, but register their > > respective cleanup function to be called on driver detach. > > > > Signed-off-by: Paul Cercueil <paul@crapouillou.net> > > --- > > > > Notes: > > v3: New patch > > v4: No change > > > > drivers/remoteproc/remoteproc_core.c | 67 ++++++++++++++++++++++++++++ > > include/linux/remoteproc.h | 5 +++ > > 2 files changed, 72 insertions(+) > > > > diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c > > index 307df98347ba..0a9fc7fdd1c3 100644 > > --- a/drivers/remoteproc/remoteproc_core.c > > +++ b/drivers/remoteproc/remoteproc_core.c > > > Maybe these devm function shall be defined in a new remoteproc/devres.c > file. Although it seems to be a common usage I don't know if there is a > rule for that. > Let's keep it in this same file, the devres.c would be tiny. > > > @@ -1932,6 +1932,33 @@ int rproc_add(struct rproc *rproc) > > } > > EXPORT_SYMBOL(rproc_add); > > > > +static void devm_rproc_remove(void *rproc) > > +{ > > + rproc_del(rproc); > > +} > > + > > +/** > > + * devm_rproc_add() - resource managed rproc_add() > > + * @dev: the underlying device > > + * @rproc: the remote processor handle to register > > + * > > + * This function performs like rproc_add() but the registered rproc device will > > + * automatically be removed on driver detach. > > + * > > + * Returns 0 on success and an appropriate error code otherwise. > > + */ > > +int devm_rproc_add(struct device *dev, struct rproc *rproc) > > +{ > > + int err; > > + > > + err = rproc_add(rproc); > > + if (err) > > + return err; > > + > > + return devm_add_action_or_reset(dev, devm_rproc_remove, rproc); > > +} > > +EXPORT_SYMBOL(devm_rproc_add); > > + > > /** > > * rproc_type_release() - release a remote processor instance > > * @dev: the rproc's device > > @@ -2149,6 +2176,46 @@ int rproc_del(struct rproc *rproc) > > } > > EXPORT_SYMBOL(rproc_del); > > > > +static void devm_rproc_free(struct device *dev, void *res) > > +{ > > + rproc_free(*(struct rproc **)res); > > +} > > + > > +/** > > + * devm_rproc_alloc() - resource managed rproc_alloc() > > + * @dev: the underlying device > > + * @name: name of this remote processor > > + * @ops: platform-specific handlers (mainly start/stop) > > + * @firmware: name of firmware file to load, can be NULL > > + * @len: length of private data needed by the rproc driver (in bytes) > > + * > > + * This function performs like rproc_alloc() but the acuired rproc device will > > > typo: s/acuired/acquired > > > > + * automatically be released on driver detach. > > + * > > + * On success the new rproc is returned, and on failure, NULL. > > + */ > > +struct rproc *devm_rproc_alloc(struct device *dev, const char *name, > > + const struct rproc_ops *ops, > > + const char *firmware, int len) > > +{ > > + struct rproc **ptr, *rproc; > > + > > + ptr = devres_alloc(devm_rproc_free, sizeof(*ptr), GFP_KERNEL); > > + if (!ptr) > > + return ERR_PTR(-ENOMEM); > > + > > + rproc = rproc_alloc(dev, name, ops, firmware, len); > > + if (rproc) { > > + *ptr = rproc; > > + devres_add(dev, ptr); > > + } else { > > + devres_free(ptr); > > + } > > + > > + return rproc; > > > Can't you use devm_add_action_or_reset() here too? > The proposed function matches how everyone else is doing devm_*_alloc(), so I would like to keep it as is. Regards, Bjorn > > > +} > > +EXPORT_SYMBOL(devm_rproc_alloc); > > + > > /** > > * rproc_add_subdev() - add a subdevice to a remoteproc > > * @rproc: rproc handle to add the subdevice to > > diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h > > index 16ad66683ad0..5f201f0c86c3 100644 > > --- a/include/linux/remoteproc.h > > +++ b/include/linux/remoteproc.h > > @@ -595,6 +595,11 @@ int rproc_add(struct rproc *rproc); > > int rproc_del(struct rproc *rproc); > > void rproc_free(struct rproc *rproc); > > > > +struct rproc *devm_rproc_alloc(struct device *dev, const char *name, > > + const struct rproc_ops *ops, > > + const char *firmware, int len); > > +int devm_rproc_add(struct device *dev, struct rproc *rproc); > > + > > void rproc_add_carveout(struct rproc *rproc, struct rproc_mem_entry *mem); > > > > struct rproc_mem_entry * > > > BR > > Fabien
On Tue 10 Dec 08:40 PST 2019, Paul Cercueil wrote: [..] > +/** > + * devm_rproc_add() - resource managed rproc_add() > + * @dev: the underlying device > + * @rproc: the remote processor handle to register > + * > + * This function performs like rproc_add() but the registered rproc device will > + * automatically be removed on driver detach. > + * > + * Returns 0 on success and an appropriate error code otherwise. The kerneldoc format is "Return: foo on bar...". So please update this to Return: 0 on success, negative errno on failure > + */ > +int devm_rproc_add(struct device *dev, struct rproc *rproc) > +{ [..] > +/** > + * devm_rproc_alloc() - resource managed rproc_alloc() > + * @dev: the underlying device > + * @name: name of this remote processor > + * @ops: platform-specific handlers (mainly start/stop) > + * @firmware: name of firmware file to load, can be NULL > + * @len: length of private data needed by the rproc driver (in bytes) > + * > + * This function performs like rproc_alloc() but the acuired rproc device will > + * automatically be released on driver detach. > + * > + * On success the new rproc is returned, and on failure, NULL. Return: new rproc instance, NULL on failure Regards, Bjorn
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 307df98347ba..0a9fc7fdd1c3 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -1932,6 +1932,33 @@ int rproc_add(struct rproc *rproc) } EXPORT_SYMBOL(rproc_add); +static void devm_rproc_remove(void *rproc) +{ + rproc_del(rproc); +} + +/** + * devm_rproc_add() - resource managed rproc_add() + * @dev: the underlying device + * @rproc: the remote processor handle to register + * + * This function performs like rproc_add() but the registered rproc device will + * automatically be removed on driver detach. + * + * Returns 0 on success and an appropriate error code otherwise. + */ +int devm_rproc_add(struct device *dev, struct rproc *rproc) +{ + int err; + + err = rproc_add(rproc); + if (err) + return err; + + return devm_add_action_or_reset(dev, devm_rproc_remove, rproc); +} +EXPORT_SYMBOL(devm_rproc_add); + /** * rproc_type_release() - release a remote processor instance * @dev: the rproc's device @@ -2149,6 +2176,46 @@ int rproc_del(struct rproc *rproc) } EXPORT_SYMBOL(rproc_del); +static void devm_rproc_free(struct device *dev, void *res) +{ + rproc_free(*(struct rproc **)res); +} + +/** + * devm_rproc_alloc() - resource managed rproc_alloc() + * @dev: the underlying device + * @name: name of this remote processor + * @ops: platform-specific handlers (mainly start/stop) + * @firmware: name of firmware file to load, can be NULL + * @len: length of private data needed by the rproc driver (in bytes) + * + * This function performs like rproc_alloc() but the acuired rproc device will + * automatically be released on driver detach. + * + * On success the new rproc is returned, and on failure, NULL. + */ +struct rproc *devm_rproc_alloc(struct device *dev, const char *name, + const struct rproc_ops *ops, + const char *firmware, int len) +{ + struct rproc **ptr, *rproc; + + ptr = devres_alloc(devm_rproc_free, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + rproc = rproc_alloc(dev, name, ops, firmware, len); + if (rproc) { + *ptr = rproc; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return rproc; +} +EXPORT_SYMBOL(devm_rproc_alloc); + /** * rproc_add_subdev() - add a subdevice to a remoteproc * @rproc: rproc handle to add the subdevice to diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index 16ad66683ad0..5f201f0c86c3 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -595,6 +595,11 @@ int rproc_add(struct rproc *rproc); int rproc_del(struct rproc *rproc); void rproc_free(struct rproc *rproc); +struct rproc *devm_rproc_alloc(struct device *dev, const char *name, + const struct rproc_ops *ops, + const char *firmware, int len); +int devm_rproc_add(struct device *dev, struct rproc *rproc); + void rproc_add_carveout(struct rproc *rproc, struct rproc_mem_entry *mem); struct rproc_mem_entry *
Add API functions devm_rproc_alloc() and devm_rproc_add(), which behave like rproc_alloc() and rproc_add() respectively, but register their respective cleanup function to be called on driver detach. Signed-off-by: Paul Cercueil <paul@crapouillou.net> --- Notes: v3: New patch v4: No change drivers/remoteproc/remoteproc_core.c | 67 ++++++++++++++++++++++++++++ include/linux/remoteproc.h | 5 +++ 2 files changed, 72 insertions(+)