All of lore.kernel.org
 help / color / mirror / Atom feed
From: lee.jones@linaro.org (Lee Jones)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 3/6] mailbox: Add support for ST's Mailbox IP
Date: Tue, 21 Jul 2015 16:06:29 +0100	[thread overview]
Message-ID: <20150721150629.GJ3061@x1> (raw)
In-Reply-To: <CABb+yY2nAT6V4Q8suAXRtPXrXkArGWVTAW28ts4Z3C_ybuJovA@mail.gmail.com>

On Tue, 21 Jul 2015, Jassi Brar wrote:

> On Fri, Jul 17, 2015 at 5:34 PM, Lee Jones <lee.jones@linaro.org> wrote:
> > ST's platforms currently support a maximum of 5 Mailboxes, one for
> > each of the supported co-processors situated on the platform.  Each
> > Mailbox is divided up into 4 instances which consist of 32 channels.
> > Messages are passed between the application and co-processors using
> > shared memory areas.  It is the Client's responsibility to manage
> > these areas.
> >
> Thanks. It's a lot better than the old driver. However a few nits as usual :)

Never a problem. :)

> > +
> > +#define STI_MBOX_INST_MAX      4      /* RAM saving: Max supported instances */
> >
> Above you say 5 instances. Another u32 doesn't cost much.

4 instances, 5 mailboxes.

> > +#define STI_MBOX_CHAN_MAX      20     /* RAM saving: Max supported channels  */
> > +
> This assumption is reasonable.
> 
> > +
> > +static void sti_mbox_enable_channel(struct mbox_chan *chan)
> > +{
> > +       struct sti_channel *chan_info = chan->con_priv;
> > +       struct sti_mbox_device *mdev = chan_info->mdev;
> > +       struct sti_mbox_pdata *pdata = dev_get_platdata(mdev->dev);
> > +       unsigned int instance = chan_info->instance;
> > +       unsigned int channel = chan_info->channel;
> > +       unsigned long flags;
> > +       void __iomem *base;
> > +
> > +       base = mdev->base + (instance * sizeof(u32));
> > +
> Maybe have something simpler like MBOX_BASE(instance)? Or some inline
> function to avoid this 5-lines ritual?

I think some of the functions also make use of the intermediary
pointers, but I'll look into it.

> > +       spin_lock_irqsave(&sti_mbox_chan_lock, flags);
> > +       mdev->enabled[instance] |= BIT(channel);
> > +       writel_relaxed(BIT(channel), base + pdata->ena_set);
> > +       spin_unlock_irqrestore(&sti_mbox_chan_lock, flags);
> >
> You don't need locking for SET/CLR type registers which are meant for
> when they could be accessed by processors that can not share a lock.
> So maybe drop the lock here and elsewhere.

Okay.

> However, you need some mechanism to check if you succeeded 'owning'
> the channel by reading back what you write to own the channel (not
> sure which is that register here). Usually we need that action and
> verification when we assign a channel to some user.

I don't think there is a technical reason why it wouldn't succeed.  We
don't normally read back every register change me make.  Why is this
IP different?

> > +static int sti_mbox_send_data(struct mbox_chan *chan, void *data)
> > +{
> > +       struct sti_channel *chan_info = chan->con_priv;
> > +       struct sti_mbox_device *mdev = chan_info->mdev;
> > +       struct sti_mbox_pdata *pdata = dev_get_platdata(mdev->dev);
> > +       unsigned int instance = chan_info->instance;
> > +       unsigned int channel = chan_info->channel;
> > +       void __iomem *base;
> > +
> > +       if (!sti_mbox_tx_is_ready(chan))
> > +               return -EBUSY;
> This is the first thing I look out for in every new driver :)  this
> check is unnecessary.

In what way?  What if the channel is disabled or there is an IRQ
already pending?

> > +static void sti_mbox_shutdown_chan(struct mbox_chan *chan)
> > +{
> > +       struct sti_channel *chan_info = chan->con_priv;
> > +       struct mbox_controller *mbox = chan_info->mdev->mbox;
> > +       int i;
> > +
> > +       for (i = 0; i < mbox->num_chans; i++)
> > +               if (chan == &mbox->chans[i])
> > +                       break;
> > +
> > +       if (mbox->num_chans == i) {
> > +               dev_warn(mbox->dev, "Request to free non-existent channel\n");
> > +               return;
> > +       }
> > +
> > +       sti_mbox_disable_channel(chan);
> > +       sti_mbox_clear_irq(chan);
> > +
> > +       /* Reset channel */
> > +       memset(chan, 0, sizeof(*chan));
> > +       chan->mbox = mbox;
> > +       chan->txdone_method = TXDONE_BY_POLL;
> >
> No please. mbox_chan is owned by the API. At most you could clear con_priv.

I will look for the API call to reset the channel then.

> > +static struct mbox_chan *sti_mbox_xlate(struct mbox_controller *mbox,
> > +                                       const struct of_phandle_args *spec)
> > +{
> > +       struct sti_mbox_device *mdev = dev_get_drvdata(mbox->dev);
> > +       struct sti_mbox_pdata *pdata = dev_get_platdata(mdev->dev);
> > +       struct sti_channel *chan_info;
> > +       struct mbox_chan *chan = NULL;
> > +       unsigned int instance  = spec->args[0];
> > +       unsigned int channel   = spec->args[1];
> > +       unsigned int direction = spec->args[2];
> > +       int i;
> > +
> > +       /* Bounds checking */
> > +       if (instance >= pdata->num_inst || channel  >= pdata->num_chan) {
> > +               dev_err(mbox->dev,
> > +                       "Invalid channel requested instance: %d channel: %d\n",
> > +                       instance, channel);
> > +               return NULL;
> > +       }
> > +
> > +       for (i = 0; i < mbox->num_chans; i++) {
> > +               chan_info = mbox->chans[i].con_priv;
> > +
> > +               /* Is requested channel free? */
> > +               if (direction != MBOX_LOOPBACK &&
> > +                   chan_info &&
> > +                   mbox->dev == chan_info->mdev->dev &&
> > +                   instance == chan_info->instance &&
> > +                   channel == chan_info->channel) {
> > +                       dev_err(mbox->dev, "Channel in use\n");
> > +                       return NULL;
> > +               }
> > +
> > +               /* Find the first free slot */
> > +               if (!chan && !chan_info)
> > +                       chan = &mbox->chans[i];
>         shouldn't it break out of loop here?

Yes, I guess it should.  Good spot.

> > +       }
> > +
> Doesn't mbox->chans[i].con_priv need some locking here?

I can add some.

> > +static const struct sti_mbox_pdata mbox_stih407_pdata = {
> > +       .num_inst       = 4,
> > +       .num_chan       = 32,
> > +       .irq_val        = 0x04,
> > +       .irq_set        = 0x24,
> > +       .irq_clr        = 0x44,
> > +       .ena_val        = 0x64,
> > +       .ena_set        = 0x84,
> > +       .ena_clr        = 0xa4,
> >
> Register offsets are parameters of the controller

And this is a controller driver?  Not sure I get the point.

> and also these look ugly. Please make these #define's

Sure.

> > +static int __init sti_mbox_init(void)
> > +{
> > +       return platform_driver_register(&sti_mbox_driver);
> > +}
> > +
> > +static void __exit sti_mbox_exit(void)
> > +{
> > +       platform_driver_unregister(&sti_mbox_driver);
> > +}
> > +
> > +postcore_initcall(sti_mbox_init);
> >
> This seems fragile. Shouldn't the users defer probe if they don't get a channel?

I'm not sure why we have to be early.  I will investigate.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

WARNING: multiple messages have this Message-ID (diff)
From: Lee Jones <lee.jones@linaro.org>
To: Jassi Brar <jassisinghbrar@gmail.com>
Cc: "linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	kernel@stlinux.com, Devicetree List <devicetree@vger.kernel.org>
Subject: Re: [PATCH 3/6] mailbox: Add support for ST's Mailbox IP
Date: Tue, 21 Jul 2015 16:06:29 +0100	[thread overview]
Message-ID: <20150721150629.GJ3061@x1> (raw)
In-Reply-To: <CABb+yY2nAT6V4Q8suAXRtPXrXkArGWVTAW28ts4Z3C_ybuJovA@mail.gmail.com>

On Tue, 21 Jul 2015, Jassi Brar wrote:

> On Fri, Jul 17, 2015 at 5:34 PM, Lee Jones <lee.jones@linaro.org> wrote:
> > ST's platforms currently support a maximum of 5 Mailboxes, one for
> > each of the supported co-processors situated on the platform.  Each
> > Mailbox is divided up into 4 instances which consist of 32 channels.
> > Messages are passed between the application and co-processors using
> > shared memory areas.  It is the Client's responsibility to manage
> > these areas.
> >
> Thanks. It's a lot better than the old driver. However a few nits as usual :)

Never a problem. :)

> > +
> > +#define STI_MBOX_INST_MAX      4      /* RAM saving: Max supported instances */
> >
> Above you say 5 instances. Another u32 doesn't cost much.

4 instances, 5 mailboxes.

> > +#define STI_MBOX_CHAN_MAX      20     /* RAM saving: Max supported channels  */
> > +
> This assumption is reasonable.
> 
> > +
> > +static void sti_mbox_enable_channel(struct mbox_chan *chan)
> > +{
> > +       struct sti_channel *chan_info = chan->con_priv;
> > +       struct sti_mbox_device *mdev = chan_info->mdev;
> > +       struct sti_mbox_pdata *pdata = dev_get_platdata(mdev->dev);
> > +       unsigned int instance = chan_info->instance;
> > +       unsigned int channel = chan_info->channel;
> > +       unsigned long flags;
> > +       void __iomem *base;
> > +
> > +       base = mdev->base + (instance * sizeof(u32));
> > +
> Maybe have something simpler like MBOX_BASE(instance)? Or some inline
> function to avoid this 5-lines ritual?

I think some of the functions also make use of the intermediary
pointers, but I'll look into it.

> > +       spin_lock_irqsave(&sti_mbox_chan_lock, flags);
> > +       mdev->enabled[instance] |= BIT(channel);
> > +       writel_relaxed(BIT(channel), base + pdata->ena_set);
> > +       spin_unlock_irqrestore(&sti_mbox_chan_lock, flags);
> >
> You don't need locking for SET/CLR type registers which are meant for
> when they could be accessed by processors that can not share a lock.
> So maybe drop the lock here and elsewhere.

Okay.

> However, you need some mechanism to check if you succeeded 'owning'
> the channel by reading back what you write to own the channel (not
> sure which is that register here). Usually we need that action and
> verification when we assign a channel to some user.

I don't think there is a technical reason why it wouldn't succeed.  We
don't normally read back every register change me make.  Why is this
IP different?

> > +static int sti_mbox_send_data(struct mbox_chan *chan, void *data)
> > +{
> > +       struct sti_channel *chan_info = chan->con_priv;
> > +       struct sti_mbox_device *mdev = chan_info->mdev;
> > +       struct sti_mbox_pdata *pdata = dev_get_platdata(mdev->dev);
> > +       unsigned int instance = chan_info->instance;
> > +       unsigned int channel = chan_info->channel;
> > +       void __iomem *base;
> > +
> > +       if (!sti_mbox_tx_is_ready(chan))
> > +               return -EBUSY;
> This is the first thing I look out for in every new driver :)  this
> check is unnecessary.

In what way?  What if the channel is disabled or there is an IRQ
already pending?

> > +static void sti_mbox_shutdown_chan(struct mbox_chan *chan)
> > +{
> > +       struct sti_channel *chan_info = chan->con_priv;
> > +       struct mbox_controller *mbox = chan_info->mdev->mbox;
> > +       int i;
> > +
> > +       for (i = 0; i < mbox->num_chans; i++)
> > +               if (chan == &mbox->chans[i])
> > +                       break;
> > +
> > +       if (mbox->num_chans == i) {
> > +               dev_warn(mbox->dev, "Request to free non-existent channel\n");
> > +               return;
> > +       }
> > +
> > +       sti_mbox_disable_channel(chan);
> > +       sti_mbox_clear_irq(chan);
> > +
> > +       /* Reset channel */
> > +       memset(chan, 0, sizeof(*chan));
> > +       chan->mbox = mbox;
> > +       chan->txdone_method = TXDONE_BY_POLL;
> >
> No please. mbox_chan is owned by the API. At most you could clear con_priv.

I will look for the API call to reset the channel then.

> > +static struct mbox_chan *sti_mbox_xlate(struct mbox_controller *mbox,
> > +                                       const struct of_phandle_args *spec)
> > +{
> > +       struct sti_mbox_device *mdev = dev_get_drvdata(mbox->dev);
> > +       struct sti_mbox_pdata *pdata = dev_get_platdata(mdev->dev);
> > +       struct sti_channel *chan_info;
> > +       struct mbox_chan *chan = NULL;
> > +       unsigned int instance  = spec->args[0];
> > +       unsigned int channel   = spec->args[1];
> > +       unsigned int direction = spec->args[2];
> > +       int i;
> > +
> > +       /* Bounds checking */
> > +       if (instance >= pdata->num_inst || channel  >= pdata->num_chan) {
> > +               dev_err(mbox->dev,
> > +                       "Invalid channel requested instance: %d channel: %d\n",
> > +                       instance, channel);
> > +               return NULL;
> > +       }
> > +
> > +       for (i = 0; i < mbox->num_chans; i++) {
> > +               chan_info = mbox->chans[i].con_priv;
> > +
> > +               /* Is requested channel free? */
> > +               if (direction != MBOX_LOOPBACK &&
> > +                   chan_info &&
> > +                   mbox->dev == chan_info->mdev->dev &&
> > +                   instance == chan_info->instance &&
> > +                   channel == chan_info->channel) {
> > +                       dev_err(mbox->dev, "Channel in use\n");
> > +                       return NULL;
> > +               }
> > +
> > +               /* Find the first free slot */
> > +               if (!chan && !chan_info)
> > +                       chan = &mbox->chans[i];
>         shouldn't it break out of loop here?

Yes, I guess it should.  Good spot.

> > +       }
> > +
> Doesn't mbox->chans[i].con_priv need some locking here?

I can add some.

> > +static const struct sti_mbox_pdata mbox_stih407_pdata = {
> > +       .num_inst       = 4,
> > +       .num_chan       = 32,
> > +       .irq_val        = 0x04,
> > +       .irq_set        = 0x24,
> > +       .irq_clr        = 0x44,
> > +       .ena_val        = 0x64,
> > +       .ena_set        = 0x84,
> > +       .ena_clr        = 0xa4,
> >
> Register offsets are parameters of the controller

And this is a controller driver?  Not sure I get the point.

> and also these look ugly. Please make these #define's

Sure.

> > +static int __init sti_mbox_init(void)
> > +{
> > +       return platform_driver_register(&sti_mbox_driver);
> > +}
> > +
> > +static void __exit sti_mbox_exit(void)
> > +{
> > +       platform_driver_unregister(&sti_mbox_driver);
> > +}
> > +
> > +postcore_initcall(sti_mbox_init);
> >
> This seems fragile. Shouldn't the users defer probe if they don't get a channel?

I'm not sure why we have to be early.  I will investigate.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

  reply	other threads:[~2015-07-21 15:06 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-07-17 12:04 [PATCH 0/6] Mailbox: Provide support STi based platforms Lee Jones
2015-07-17 12:04 ` Lee Jones
2015-07-17 12:04 ` [PATCH 1/6] mailbox: dt: Supply bindings for ST's Mailbox IP Lee Jones
2015-07-17 12:04   ` Lee Jones
2015-07-17 12:04   ` Lee Jones
2015-07-17 12:04 ` [PATCH 2/6] mailbox: dt-bindings: Add shared [driver <=> device tree] defines Lee Jones
2015-07-17 12:04   ` Lee Jones
2015-07-17 12:04 ` [PATCH 3/6] mailbox: Add support for ST's Mailbox IP Lee Jones
2015-07-17 12:04   ` Lee Jones
2015-07-21 14:41   ` Jassi Brar
2015-07-21 14:41     ` Jassi Brar
2015-07-21 14:41     ` Jassi Brar
2015-07-21 15:06     ` Lee Jones [this message]
2015-07-21 15:06       ` Lee Jones
2015-07-21 15:29       ` Jassi Brar
2015-07-21 15:29         ` Jassi Brar
2015-07-21 15:52         ` Lee Jones
2015-07-21 15:52           ` Lee Jones
2015-07-21 15:52           ` Lee Jones
2015-07-21 16:09           ` Jassi Brar
2015-07-21 16:09             ` Jassi Brar
2015-07-21 17:48             ` Lee Jones
2015-07-21 17:48               ` Lee Jones
2015-07-21 18:36               ` Jassi Brar
2015-07-21 18:36                 ` Jassi Brar
2015-07-21 18:36                 ` Jassi Brar
2015-07-23  8:29     ` Lee Jones
2015-07-23  8:29       ` Lee Jones
2015-07-23  8:29       ` Lee Jones
2015-07-23 16:31       ` Jassi Brar
2015-07-23 16:31         ` Jassi Brar
2015-07-24  9:36         ` Lee Jones
2015-07-24  9:36           ` Lee Jones
2015-07-24 17:34           ` Jassi Brar
2015-07-24 17:34             ` Jassi Brar
2015-07-23 17:23   ` Alexey Klimov
2015-07-23 17:23     ` Alexey Klimov
2015-07-23 17:23     ` Alexey Klimov
2015-07-24  9:52     ` Lee Jones
2015-07-24  9:52       ` Lee Jones
2015-07-17 12:04 ` [PATCH 4/6] ARM: STi: stih407-family: Add nodes for Mailbox Lee Jones
2015-07-17 12:04   ` Lee Jones
2015-07-17 12:04 ` [PATCH 5/6] mailbox: Add generic mechanism for testing Mailbox Controllers Lee Jones
2015-07-17 12:04   ` Lee Jones
2015-07-17 12:04   ` Lee Jones
2015-07-17 12:04 ` [PATCH 6/6] ARM: STi: DT: STiH407: Enable Mailbox testing facility Lee Jones
2015-07-17 12:04   ` Lee Jones

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150721150629.GJ3061@x1 \
    --to=lee.jones@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.