Skip to content

Commit

Permalink
mailbox: Allow direct registration to a channel
Browse files Browse the repository at this point in the history
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]>
Signed-off-by: Jassi Brar <[email protected]>
  • Loading branch information
eberman-quic authored and JassiBrar committed Apr 18, 2023
1 parent 6a8f57a commit 85a9538
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 28 deletions.
96 changes: 68 additions & 28 deletions drivers/mailbox/mailbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions include/linux/mailbox_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 85a9538

Please sign in to comment.