2023-04-10 16:26:32

by Elliot Berman

[permalink] [raw]
Subject: [PATCH v3 0/3] mailbox: Allow direct registration to a channel

Two mailbox controllers have channel/client binding mechanisms that are
controller-specific and not using the devicetree binding mechanisms. Mailbox
channel/client is conceptually done in two steps: selecting the channel
and binding the selected to channel to a client. Channel selection is sometimes
controller specific (pcc and omap are examples). The channel/client binding
code is all the same.

This small series de-duplicates and refactors the channel/client binding
into a common framework function: "mbox_bind_client" which all of the
channel selection mechanisms can use.

I found this duplicate code while working on the support for Gunyah hypervisor
message queues [1]. I've only been able to compile-test omap-mailbox and pcc,
however it is a straightforward conversion here.

[1]: https://lore.kernel.org/all/[email protected]/

Chagnes since v2:
- Fix warnings in drivers/mailbox/pcc.c reported by [email protected]

Changes since v1:
- Rebase to https://git.linaro.org/landing-teams/working/fujitsu/integration.git/log/?h=mailbox-for-next
- Add Tested-By from Sudeep (thanks!)

Elliot Berman (3):
mailbox: Allow direct registration to a channel
mailbox: omap: Use mbox_bind_client
mailbox: pcc: Use mbox_bind_client

drivers/mailbox/mailbox.c | 96 ++++++++++++++++++++++++----------
drivers/mailbox/omap-mailbox.c | 22 ++------
drivers/mailbox/pcc.c | 84 +++++++++++++++--------------
include/linux/mailbox_client.h | 1 +
4 files changed, 118 insertions(+), 85 deletions(-)


base-commit: 6ccbe33a39523f6d62b22c5ee99c6695993c935e
--
2.39.2


2023-04-10 16:26:57

by Elliot Berman

[permalink] [raw]
Subject: [PATCH v3 3/3] mailbox: pcc: Use mbox_bind_client

Use generic mbox_bind_client() to bind omap mailbox channel to a client.

mbox_bind_client is identical to the replaced lines, except that it:
- Does the operation under con_mutex which prevents possible races in
removal path
- Sets TXDONE_BY_ACK if pcc uses TXDONE_BY_POLL and the client knows
when tx is done. TXDONE_BY_ACK is already set if there's no interrupt,
so this is not applicable.
- Calls chan->mbox->ops->startup. This is usecase for requesting irq:
move the devm_request_irq into the startup callback and unregister it
in the shutdown path.

Tested-by: Sudeep Holla <[email protected]>
Signed-off-by: Elliot Berman <[email protected]>
---
drivers/mailbox/pcc.c | 84 +++++++++++++++++++++++--------------------
1 file changed, 45 insertions(+), 39 deletions(-)

diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index 105d46c9801b..a44d4b3e5beb 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -282,8 +282,7 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
{
struct pcc_chan_info *pchan;
struct mbox_chan *chan;
- struct device *dev;
- unsigned long flags;
+ int rc;

if (subspace_id < 0 || subspace_id >= pcc_chan_count)
return ERR_PTR(-ENOENT);
@@ -294,32 +293,10 @@ pcc_mbox_request_channel(struct mbox_client *cl, int subspace_id)
pr_err("Channel not found for idx: %d\n", subspace_id);
return ERR_PTR(-EBUSY);
}
- dev = chan->mbox->dev;

- spin_lock_irqsave(&chan->lock, flags);
- chan->msg_free = 0;
- chan->msg_count = 0;
- chan->active_req = NULL;
- chan->cl = cl;
- init_completion(&chan->tx_complete);
-
- if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
- chan->txdone_method = TXDONE_BY_ACK;
-
- spin_unlock_irqrestore(&chan->lock, flags);
-
- if (pchan->plat_irq > 0) {
- int rc;
-
- rc = devm_request_irq(dev, pchan->plat_irq, pcc_mbox_irq, 0,
- MBOX_IRQ_NAME, chan);
- if (unlikely(rc)) {
- dev_err(dev, "failed to register PCC interrupt %d\n",
- pchan->plat_irq);
- pcc_mbox_free_channel(&pchan->chan);
- return ERR_PTR(rc);
- }
- }
+ rc = mbox_bind_client(chan, cl);
+ if (rc)
+ return ERR_PTR(rc);

return &pchan->chan;
}
@@ -333,23 +310,12 @@ EXPORT_SYMBOL_GPL(pcc_mbox_request_channel);
*/
void pcc_mbox_free_channel(struct pcc_mbox_chan *pchan)
{
- struct pcc_chan_info *pchan_info = to_pcc_chan_info(pchan);
struct mbox_chan *chan = pchan->mchan;
- unsigned long flags;

if (!chan || !chan->cl)
return;

- if (pchan_info->plat_irq > 0)
- devm_free_irq(chan->mbox->dev, pchan_info->plat_irq, chan);
-
- spin_lock_irqsave(&chan->lock, flags);
- chan->cl = NULL;
- chan->active_req = NULL;
- if (chan->txdone_method == TXDONE_BY_ACK)
- chan->txdone_method = TXDONE_BY_POLL;
-
- spin_unlock_irqrestore(&chan->lock, flags);
+ mbox_free_channel(chan);
}
EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);

@@ -377,8 +343,48 @@ static int pcc_send_data(struct mbox_chan *chan, void *data)
return pcc_chan_reg_read_modify_write(&pchan->db);
}

+/**
+ * pcc_startup - Called from Mailbox Controller code. Used here
+ * to request the interrupt.
+ * @chan: Pointer to Mailbox channel to startup.
+ *
+ * Return: Err if something failed else 0 for success.
+ */
+static int pcc_startup(struct mbox_chan *chan)
+{
+ struct pcc_chan_info *pchan = chan->con_priv;
+ int rc;
+
+ if (pchan->plat_irq > 0) {
+ rc = devm_request_irq(chan->mbox->dev, pchan->plat_irq, pcc_mbox_irq, 0,
+ MBOX_IRQ_NAME, chan);
+ if (unlikely(rc)) {
+ dev_err(chan->mbox->dev, "failed to register PCC interrupt %d\n",
+ pchan->plat_irq);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * pcc_shutdown - Called from Mailbox Controller code. Used here
+ * to free the interrupt.
+ * @chan: Pointer to Mailbox channel to shutdown.
+ */
+static void pcc_shutdown(struct mbox_chan *chan)
+{
+ struct pcc_chan_info *pchan = chan->con_priv;
+
+ if (pchan->plat_irq > 0)
+ devm_free_irq(chan->mbox->dev, pchan->plat_irq, chan);
+}
+
static const struct mbox_chan_ops pcc_chan_ops = {
.send_data = pcc_send_data,
+ .startup = pcc_startup,
+ .shutdown = pcc_shutdown,
};

/**
--
2.39.2

2023-04-10 16:27:10

by Elliot Berman

[permalink] [raw]
Subject: [PATCH v3 1/3] mailbox: Allow direct registration to a channel

Support virtual mailbox controllers and clients which are not platform
devices or come from the devicetree by allowing them to match client to
channel via some other mechanism.

Tested-by: Sudeep Holla <[email protected]> (pcc)
Signed-off-by: Elliot Berman <[email protected]>
---
drivers/mailbox/mailbox.c | 96 ++++++++++++++++++++++++----------
include/linux/mailbox_client.h | 1 +
2 files changed, 69 insertions(+), 28 deletions(-)

diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
index 4229b9b5da98..adf36c05fa43 100644
--- a/drivers/mailbox/mailbox.c
+++ b/drivers/mailbox/mailbox.c
@@ -317,6 +317,71 @@ int mbox_flush(struct mbox_chan *chan, unsigned long timeout)
}
EXPORT_SYMBOL_GPL(mbox_flush);

+static int __mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl)
+{
+ struct device *dev = cl->dev;
+ unsigned long flags;
+ int ret;
+
+ if (chan->cl || !try_module_get(chan->mbox->dev->driver->owner)) {
+ dev_dbg(dev, "%s: mailbox not free\n", __func__);
+ return -EBUSY;
+ }
+
+ spin_lock_irqsave(&chan->lock, flags);
+ chan->msg_free = 0;
+ chan->msg_count = 0;
+ chan->active_req = NULL;
+ chan->cl = cl;
+ init_completion(&chan->tx_complete);
+
+ if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
+ chan->txdone_method = TXDONE_BY_ACK;
+
+ spin_unlock_irqrestore(&chan->lock, flags);
+
+ if (chan->mbox->ops->startup) {
+ ret = chan->mbox->ops->startup(chan);
+
+ if (ret) {
+ dev_err(dev, "Unable to startup the chan (%d)\n", ret);
+ mbox_free_channel(chan);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * mbox_bind_client - Request a mailbox channel.
+ * @chan: The mailbox channel to bind the client to.
+ * @cl: Identity of the client requesting the channel.
+ *
+ * The Client specifies its requirements and capabilities while asking for
+ * a mailbox channel. It can't be called from atomic context.
+ * The channel is exclusively allocated and can't be used by another
+ * client before the owner calls mbox_free_channel.
+ * After assignment, any packet received on this channel will be
+ * handed over to the client via the 'rx_callback'.
+ * The framework holds reference to the client, so the mbox_client
+ * structure shouldn't be modified until the mbox_free_channel returns.
+ *
+ * Return: 0 if the channel was assigned to the client successfully.
+ * <0 for request failure.
+ */
+int mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl)
+{
+ int ret;
+
+ mutex_lock(&con_mutex);
+ ret = __mbox_bind_client(chan, cl);
+ mutex_unlock(&con_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(mbox_bind_client);
+
/**
* mbox_request_channel - Request a mailbox channel.
* @cl: Identity of the client requesting the channel.
@@ -340,7 +405,6 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
struct mbox_controller *mbox;
struct of_phandle_args spec;
struct mbox_chan *chan;
- unsigned long flags;
int ret;

if (!dev || !dev->of_node) {
@@ -372,33 +436,9 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
return chan;
}

- if (chan->cl || !try_module_get(mbox->dev->driver->owner)) {
- dev_dbg(dev, "%s: mailbox not free\n", __func__);
- mutex_unlock(&con_mutex);
- return ERR_PTR(-EBUSY);
- }
-
- spin_lock_irqsave(&chan->lock, flags);
- chan->msg_free = 0;
- chan->msg_count = 0;
- chan->active_req = NULL;
- chan->cl = cl;
- init_completion(&chan->tx_complete);
-
- if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
- chan->txdone_method = TXDONE_BY_ACK;
-
- spin_unlock_irqrestore(&chan->lock, flags);
-
- if (chan->mbox->ops->startup) {
- ret = chan->mbox->ops->startup(chan);
-
- if (ret) {
- dev_err(dev, "Unable to startup the chan (%d)\n", ret);
- mbox_free_channel(chan);
- chan = ERR_PTR(ret);
- }
- }
+ ret = __mbox_bind_client(chan, cl);
+ if (ret)
+ chan = ERR_PTR(ret);

mutex_unlock(&con_mutex);
return chan;
diff --git a/include/linux/mailbox_client.h b/include/linux/mailbox_client.h
index 65229a45590f..734694912ef7 100644
--- a/include/linux/mailbox_client.h
+++ b/include/linux/mailbox_client.h
@@ -37,6 +37,7 @@ struct mbox_client {
void (*tx_done)(struct mbox_client *cl, void *mssg, int r);
};

+int mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl);
struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,
const char *name);
struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index);
--
2.39.2

2023-04-10 16:27:14

by Elliot Berman

[permalink] [raw]
Subject: [PATCH v3 2/3] mailbox: omap: Use mbox_bind_client

Use generic mbox_bind_client() to bind omap mailbox channel to a client.

mbox_bind_client is identical to the replaced lines, except that it:
- Does the operation under con_mutex which prevents possible races in
removal path
- Sets TXDONE_BY_ACK if omap uses TXDONE_BY_POLL. omap uses
TXDONE_BY_IRQ, so this check is not applicable.
- Calls chan->mbox->ops->startup, if available. omap doesn't have, so
this is not applicable.

Signed-off-by: Elliot Berman <[email protected]>
---
drivers/mailbox/omap-mailbox.c | 22 ++++------------------
1 file changed, 4 insertions(+), 18 deletions(-)

diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index 098c82d87137..dfe82a5ff403 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -417,8 +417,6 @@ struct mbox_chan *omap_mbox_request_channel(struct mbox_client *cl,
struct device *dev = cl->dev;
struct omap_mbox *mbox = NULL;
struct omap_mbox_device *mdev;
- struct mbox_chan *chan;
- unsigned long flags;
int ret;

if (!dev)
@@ -441,23 +439,11 @@ struct mbox_chan *omap_mbox_request_channel(struct mbox_client *cl,
if (!mbox || !mbox->chan)
return ERR_PTR(-ENOENT);

- chan = mbox->chan;
- spin_lock_irqsave(&chan->lock, flags);
- chan->msg_free = 0;
- chan->msg_count = 0;
- chan->active_req = NULL;
- chan->cl = cl;
- init_completion(&chan->tx_complete);
- spin_unlock_irqrestore(&chan->lock, flags);
-
- ret = chan->mbox->ops->startup(chan);
- if (ret) {
- pr_err("Unable to startup the chan (%d)\n", ret);
- mbox_free_channel(chan);
- chan = ERR_PTR(ret);
- }
+ ret = mbox_bind_client(mbox->chan, cl);
+ if (ret)
+ return ERR_PTR(ret);

- return chan;
+ return mbox->chan;
}
EXPORT_SYMBOL(omap_mbox_request_channel);

--
2.39.2

2023-04-17 19:29:13

by Jassi Brar

[permalink] [raw]
Subject: Re: [PATCH v3 0/3] mailbox: Allow direct registration to a channel

On Mon, Apr 10, 2023 at 11:17 AM Elliot Berman <[email protected]> wrote:
>
> Two mailbox controllers have channel/client binding mechanisms that are
> controller-specific and not using the devicetree binding mechanisms. Mailbox
> channel/client is conceptually done in two steps: selecting the channel
> and binding the selected to channel to a client. Channel selection is sometimes
> controller specific (pcc and omap are examples). The channel/client binding
> code is all the same.
>
> This small series de-duplicates and refactors the channel/client binding
> into a common framework function: "mbox_bind_client" which all of the
> channel selection mechanisms can use.
>
> I found this duplicate code while working on the support for Gunyah hypervisor
> message queues [1]. I've only been able to compile-test omap-mailbox and pcc,
> however it is a straightforward conversion here.
>
> [1]: https://lore.kernel.org/all/[email protected]/
>
> Chagnes since v2:
> - Fix warnings in drivers/mailbox/pcc.c reported by [email protected]
>
> Changes since v1:
> - Rebase to https://git.linaro.org/landing-teams/working/fujitsu/integration.git/log/?h=mailbox-for-next
> - Add Tested-By from Sudeep (thanks!)
>
> Elliot Berman (3):
> mailbox: Allow direct registration to a channel
> mailbox: omap: Use mbox_bind_client
> mailbox: pcc: Use mbox_bind_client
>
> drivers/mailbox/mailbox.c | 96 ++++++++++++++++++++++++----------
> drivers/mailbox/omap-mailbox.c | 22 ++------
> drivers/mailbox/pcc.c | 84 +++++++++++++++--------------
> include/linux/mailbox_client.h | 1 +
> 4 files changed, 118 insertions(+), 85 deletions(-)
>
Seems fine. Will pick these up for the coming merge window.

Thanks.