mirror of
https://github.com/torvalds/linux.git
synced 2024-12-30 14:52:05 +00:00
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 <sudeep.holla@arm.com> (pcc) Signed-off-by: Elliot Berman <quic_eberman@quicinc.com> Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
This commit is contained in:
parent
6a8f57ae2e
commit
85a9538065
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user