Skip to content

Commit 85a9538

Browse files
eberman-quicJassiBrar
authored andcommitted
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]> Signed-off-by: Jassi Brar <[email protected]>
1 parent 6a8f57a commit 85a9538

File tree

2 files changed

+69
-28
lines changed

2 files changed

+69
-28
lines changed

drivers/mailbox/mailbox.c

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,71 @@ int mbox_flush(struct mbox_chan *chan, unsigned long timeout)
317317
}
318318
EXPORT_SYMBOL_GPL(mbox_flush);
319319

320+
static int __mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl)
321+
{
322+
struct device *dev = cl->dev;
323+
unsigned long flags;
324+
int ret;
325+
326+
if (chan->cl || !try_module_get(chan->mbox->dev->driver->owner)) {
327+
dev_dbg(dev, "%s: mailbox not free\n", __func__);
328+
return -EBUSY;
329+
}
330+
331+
spin_lock_irqsave(&chan->lock, flags);
332+
chan->msg_free = 0;
333+
chan->msg_count = 0;
334+
chan->active_req = NULL;
335+
chan->cl = cl;
336+
init_completion(&chan->tx_complete);
337+
338+
if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
339+
chan->txdone_method = TXDONE_BY_ACK;
340+
341+
spin_unlock_irqrestore(&chan->lock, flags);
342+
343+
if (chan->mbox->ops->startup) {
344+
ret = chan->mbox->ops->startup(chan);
345+
346+
if (ret) {
347+
dev_err(dev, "Unable to startup the chan (%d)\n", ret);
348+
mbox_free_channel(chan);
349+
return ret;
350+
}
351+
}
352+
353+
return 0;
354+
}
355+
356+
/**
357+
* mbox_bind_client - Request a mailbox channel.
358+
* @chan: The mailbox channel to bind the client to.
359+
* @cl: Identity of the client requesting the channel.
360+
*
361+
* The Client specifies its requirements and capabilities while asking for
362+
* a mailbox channel. It can't be called from atomic context.
363+
* The channel is exclusively allocated and can't be used by another
364+
* client before the owner calls mbox_free_channel.
365+
* After assignment, any packet received on this channel will be
366+
* handed over to the client via the 'rx_callback'.
367+
* The framework holds reference to the client, so the mbox_client
368+
* structure shouldn't be modified until the mbox_free_channel returns.
369+
*
370+
* Return: 0 if the channel was assigned to the client successfully.
371+
* <0 for request failure.
372+
*/
373+
int mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl)
374+
{
375+
int ret;
376+
377+
mutex_lock(&con_mutex);
378+
ret = __mbox_bind_client(chan, cl);
379+
mutex_unlock(&con_mutex);
380+
381+
return ret;
382+
}
383+
EXPORT_SYMBOL_GPL(mbox_bind_client);
384+
320385
/**
321386
* mbox_request_channel - Request a mailbox channel.
322387
* @cl: Identity of the client requesting the channel.
@@ -340,7 +405,6 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
340405
struct mbox_controller *mbox;
341406
struct of_phandle_args spec;
342407
struct mbox_chan *chan;
343-
unsigned long flags;
344408
int ret;
345409

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

375-
if (chan->cl || !try_module_get(mbox->dev->driver->owner)) {
376-
dev_dbg(dev, "%s: mailbox not free\n", __func__);
377-
mutex_unlock(&con_mutex);
378-
return ERR_PTR(-EBUSY);
379-
}
380-
381-
spin_lock_irqsave(&chan->lock, flags);
382-
chan->msg_free = 0;
383-
chan->msg_count = 0;
384-
chan->active_req = NULL;
385-
chan->cl = cl;
386-
init_completion(&chan->tx_complete);
387-
388-
if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
389-
chan->txdone_method = TXDONE_BY_ACK;
390-
391-
spin_unlock_irqrestore(&chan->lock, flags);
392-
393-
if (chan->mbox->ops->startup) {
394-
ret = chan->mbox->ops->startup(chan);
395-
396-
if (ret) {
397-
dev_err(dev, "Unable to startup the chan (%d)\n", ret);
398-
mbox_free_channel(chan);
399-
chan = ERR_PTR(ret);
400-
}
401-
}
439+
ret = __mbox_bind_client(chan, cl);
440+
if (ret)
441+
chan = ERR_PTR(ret);
402442

403443
mutex_unlock(&con_mutex);
404444
return chan;

include/linux/mailbox_client.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ struct mbox_client {
3737
void (*tx_done)(struct mbox_client *cl, void *mssg, int r);
3838
};
3939

40+
int mbox_bind_client(struct mbox_chan *chan, struct mbox_client *cl);
4041
struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,
4142
const char *name);
4243
struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index);

0 commit comments

Comments
 (0)