[PATCH v7 1/2] ARM: davinci: Remoteproc driver support for OMAP-L138 DSP

Ohad Ben-Cohen ohad at wizery.com
Fri Feb 15 03:07:17 EST 2013


Hi Rob,

On Fri, Feb 1, 2013 at 4:24 AM, Robert Tivy <rtivy at ti.com> wrote:
>  drivers/remoteproc/Kconfig            |   29 ++-
>  drivers/remoteproc/Makefile           |    1 +
>  drivers/remoteproc/da8xx_remoteproc.c |  346 +++++++++++++++++++++++++++++++++
>  drivers/remoteproc/remoteproc_core.c  |   22 ++-

It looks like this patch squashes:
1. A fix to drivers/remoteproc/Kconfig
2. New functionality in remoteproc_core.c
3. A new da8xx driver

These are independent changes, so we better split them up to separate patches.

>  config OMAP_REMOTEPROC
>         tristate "OMAP remoteproc support"
> -       depends on EXPERIMENTAL
...
>  config STE_MODEM_RPROC
>         tristate "STE-Modem remoteproc support"
> -       depends on EXPERIMENTAL

These look unrelated to this patch, and it seems that Kees Cook
submitted these awhile ago so it should probably already be in
linux-next (haven't looked). I think we can drop these.

> +/**
> + * handle_event() - inbound virtqueue message workqueue function
> + *
> + * This function is registered as a kernel thread and is scheduled by the
> + * kernel handler.
> + */
> +static irqreturn_t handle_event(int irq, void *p)
> +{
> +       struct rproc *rproc = (struct rproc *)p;
> +
> +       /* Process incoming buffers on our vring */
> +       while (IRQ_HANDLED == rproc_vq_interrupt(rproc, 0))
> +               ;
> +
> +       /* Must allow wakeup of potenitally blocking senders */
> +       rproc_vq_interrupt(rproc, 1);

IIRC we agreed on removing this part, and instead adding it to the
generic remoteproc framework (i.e. Cyril's patch).

> +static int da8xx_rproc_start(struct rproc *rproc)
> +{
...
> +       dsp_clk = devm_clk_get(dev, NULL);
> +       if (IS_ERR(dsp_clk)) {
> +               dev_err(dev, "clk_get error: %ld\n", PTR_ERR(dsp_clk));
> +
> +               return PTR_RET(dsp_clk);
> +       }
> +       drproc->dsp_clk = dsp_clk;

Have you considered doing this in ->probe() instead? Do we need to
call get/put every time we start/stop the remote processor?

> +/* kick a virtqueue */
> +static void da8xx_rproc_kick(struct rproc *rproc, int vqid)
> +{
> +       struct da8xx_rproc *drproc = (struct da8xx_rproc *)rproc->priv;
> +       int timed_out;
> +       unsigned long timeout;
> +
> +       timed_out = 0;
> +       timeout = jiffies + HZ/100;
> +
> +       /* Poll for ack from other side first */
> +       while (readl(drproc->chipsig) & SYSCFG_CHIPSIG2)
> +               if (time_after(jiffies, timeout)) {
> +                       if (readl(drproc->chipsig) & SYSCFG_CHIPSIG2) {
> +                               dev_err(rproc->dev.parent,
> +                                       "failed to receive ack\n");
> +                               timed_out = 1;
> +                       }
> +
> +                       break;
> +               }

This still looks a bit out of place here.

Kicking should be a fast unilateral action, that doesn't depend on the
other side.

> +static int da8xx_rproc_probe(struct platform_device *pdev)
> +{
...
> +       ret = rproc_add(rproc);
> +       if (ret) {
> +               dev_err(dev, "rproc_add failed: %d\n", ret);
> +               goto free_rproc;
> +       }
> +
> +       drproc->chipsig = chipsig;
> +       drproc->bootreg = bootreg;
> +       drproc->ack_fxn = irq_data->chip->irq_ack;
> +       drproc->irq_data = irq_data;
> +       drproc->irq = irq;
> +
> +       /* everything the ISR needs is now setup, so hook it up */
> +       ret = devm_request_threaded_irq(dev, irq, da8xx_rproc_callback,
> +               handle_event, 0, "da8xx-remoteproc", rproc);
> +       if (ret) {
> +               dev_err(dev, "devm_request_threaded_irq error: %d\n", ret);
> +               rproc_del(rproc);
> +               goto free_rproc;
> +       }

Shouldn't we be requesting this before we rproc_add() ?

> +static int da8xx_rproc_remove(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct rproc *rproc = platform_get_drvdata(pdev);
> +       struct da8xx_rproc *drproc = (struct da8xx_rproc *)rproc->priv;
> +       int ret;
...
> +       ret = rproc_del(rproc);

You can safely remove 'ret' altogether. We will just crash in
rproc_put if rproc is NULL.

> +       rproc_put(rproc);
> +
> +       return ret;
> +}

> diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
> index dd3bfaf..e0f703e 100644
> --- a/drivers/remoteproc/remoteproc_core.c
> +++ b/drivers/remoteproc/remoteproc_core.c
> @@ -1222,19 +1222,39 @@ struct rproc *rproc_alloc(struct device *dev, const char *name,
>                                 const char *firmware, int len)
>  {
>         struct rproc *rproc;
> +       char *template = "rproc-%s-fw";
> +       char *p;
>
>         if (!dev || !name || !ops)
>                 return NULL;
>
> +       if (!firmware)
> +               /*
> +                * Make room for default firmware name (minus %s plus '\0').
> +                * If the caller didn't pass in a firmware name then
> +                * construct a default name.  We're already glomming 'len'
> +                * bytes onto the end of the struct rproc allocation, so do
> +                * a few more for the default firmware name (but only if
> +                * the caller doesn't pass one).
> +                */
> +               len += strlen(name) + strlen(template) - 2 + 1;
> +
>         rproc = kzalloc(sizeof(struct rproc) + len, GFP_KERNEL);
>         if (!rproc) {
>                 dev_err(dev, "%s: kzalloc failed\n", __func__);
>                 return NULL;
>         }
>
> +       if (!firmware) {
> +               p = (char *)rproc + sizeof(struct rproc) + len;
> +               sprintf(p, template, name);

Looks like p you're writing to is outside of the rproc memory allocation.

Thanks,
Ohad.



More information about the linux-arm-kernel mailing list