X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fmailbox%2Fmailbox.c;h=afcb430508eceac7887ee436ec19c15fcfad89cd;hb=43e7406efd7822d75c64310461d2cbca0ece19f0;hp=607dd91e87a16b9a851ce103ece8a30a30c3b2ba;hpb=a44e5e7cf580307809147cbec3d326e77524f757;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c index 607dd91e87a1..afcb430508ec 100644 --- a/drivers/mailbox/mailbox.c +++ b/drivers/mailbox/mailbox.c @@ -1,7 +1,7 @@ /* * Mailbox: Common code for Mailbox controllers and users * - * Copyright (C) 2014 Linaro Ltd. + * Copyright (C) 2013-2014 Linaro Ltd. * Author: Jassi Brar * * This program is free software; you can redistribute it and/or modify @@ -17,17 +17,18 @@ #include #include #include +#include #include #include -#define TXDONE_BY_IRQ (1 << 0) /* controller has remote RTR irq */ -#define TXDONE_BY_POLL (1 << 1) /* controller can read status of last TX */ -#define TXDONE_BY_ACK (1 << 2) /* S/W ACK recevied by Client ticks the TX */ +#define TXDONE_BY_IRQ BIT(0) /* controller has remote RTR irq */ +#define TXDONE_BY_POLL BIT(1) /* controller can read status of last TX */ +#define TXDONE_BY_ACK BIT(2) /* S/W ACK recevied by Client ticks the TX */ static LIST_HEAD(mbox_cons); static DEFINE_MUTEX(con_mutex); -static int _add_to_rbuf(struct mbox_chan *chan, void *mssg) +static int add_to_rbuf(struct mbox_chan *chan, void *mssg) { int idx; unsigned long flags; @@ -37,7 +38,7 @@ static int _add_to_rbuf(struct mbox_chan *chan, void *mssg) /* See if there is any space left */ if (chan->msg_count == MBOX_TX_QUEUE_LEN) { spin_unlock_irqrestore(&chan->lock, flags); - return -ENOMEM; + return -ENOBUFS; } idx = chan->msg_free; @@ -54,7 +55,7 @@ static int _add_to_rbuf(struct mbox_chan *chan, void *mssg) return idx; } -static void _msg_submit(struct mbox_chan *chan) +static void msg_submit(struct mbox_chan *chan) { unsigned count, idx; unsigned long flags; @@ -63,10 +64,8 @@ static void _msg_submit(struct mbox_chan *chan) spin_lock_irqsave(&chan->lock, flags); - if (!chan->msg_count || chan->active_req) { - spin_unlock_irqrestore(&chan->lock, flags); - return; - } + if (!chan->msg_count || chan->active_req) + goto exit; count = chan->msg_count; idx = chan->msg_free; @@ -83,7 +82,7 @@ static void _msg_submit(struct mbox_chan *chan) chan->active_req = data; chan->msg_count--; } - +exit: spin_unlock_irqrestore(&chan->lock, flags); } @@ -98,13 +97,14 @@ static void tx_tick(struct mbox_chan *chan, int r) spin_unlock_irqrestore(&chan->lock, flags); /* Submit next message */ - _msg_submit(chan); + msg_submit(chan); /* Notify the client */ + if (mssg && chan->cl->tx_done) + chan->cl->tx_done(chan->cl, mssg, r); + if (chan->cl->tx_block) complete(&chan->tx_complete); - else if (mssg && chan->cl->tx_done) - chan->cl->tx_done(chan->cl, mssg, r); } static void poll_txdone(unsigned long data) @@ -125,15 +125,15 @@ static void poll_txdone(unsigned long data) } if (resched) - mod_timer(&mbox->poll, - jiffies + msecs_to_jiffies(mbox->period)); + mod_timer(&mbox->poll, jiffies + + msecs_to_jiffies(mbox->txpoll_period)); } /** * mbox_chan_received_data - A way for controller driver to push data * received from remote to the upper layer. * @chan: Pointer to the mailbox channel on which RX happened. - * @data: Client specific message typecasted as void * + * @mssg: Client specific message typecasted as void * * * After startup and before shutdown any data received on the chan * is passed on to the API via atomic mbox_chan_received_data(). @@ -160,7 +160,8 @@ EXPORT_SYMBOL_GPL(mbox_chan_received_data); void mbox_chan_txdone(struct mbox_chan *chan, int r) { if (unlikely(!(chan->txdone_method & TXDONE_BY_IRQ))) { - pr_err("Controller can't run the TX ticker\n"); + dev_err(chan->mbox->dev, + "Controller can't run the TX ticker\n"); return; } @@ -180,7 +181,7 @@ EXPORT_SYMBOL_GPL(mbox_chan_txdone); void mbox_client_txdone(struct mbox_chan *chan, int r) { if (unlikely(!(chan->txdone_method & TXDONE_BY_ACK))) { - pr_err("Client can't run the TX ticker\n"); + dev_err(chan->mbox->dev, "Client can't run the TX ticker\n"); return; } @@ -227,8 +228,6 @@ EXPORT_SYMBOL_GPL(mbox_client_peek_data); * is not queued, a negative token is returned. Upon failure or successful * TX, the API calls 'tx_done' from atomic context, from which the client * could submit yet another request. - * In blocking mode, 'tx_done' is not called, effectively making the - * queue length 1. * The pointer to message should be preserved until it is sent * over the chan, i.e, tx_done() is made. * This function could be called from atomic context as it simply @@ -245,15 +244,13 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg) if (!chan || !chan->cl) return -EINVAL; - t = _add_to_rbuf(chan, mssg); + t = add_to_rbuf(chan, mssg); if (t < 0) { - pr_err("Try increasing MBOX_TX_QUEUE_LEN\n"); + dev_err(chan->mbox->dev, "Try increasing MBOX_TX_QUEUE_LEN\n"); return t; } - _msg_submit(chan); - - init_completion(&chan->tx_complete); + msg_submit(chan); if (chan->txdone_method == TXDONE_BY_POLL) poll_txdone((unsigned long)chan->mbox); @@ -262,7 +259,7 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg) unsigned long wait; int ret; - if (!chan->cl->tx_tout) /* wait for ever */ + if (!chan->cl->tx_tout) /* wait forever */ wait = msecs_to_jiffies(3600000); else wait = msecs_to_jiffies(chan->cl->tx_tout); @@ -281,6 +278,7 @@ EXPORT_SYMBOL_GPL(mbox_send_message); /** * mbox_request_channel - Request a mailbox channel. * @cl: Identity of the client requesting the channel. + * @index: Index of mailbox specifier in 'mboxes' property. * * The Client specifies its requirements and capabilities while asking for * a mailbox channel. It can't be called from atomic context. @@ -294,64 +292,42 @@ EXPORT_SYMBOL_GPL(mbox_send_message); * Return: Pointer to the channel assigned to the client if successful. * ERR_PTR for request failure. */ -struct mbox_chan *mbox_request_channel(struct mbox_client *cl) +struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index) { struct device *dev = cl->dev; struct mbox_controller *mbox; struct of_phandle_args spec; struct mbox_chan *chan; unsigned long flags; - int count, i, ret; + int ret; if (!dev || !dev->of_node) { - pr_err("%s: No owner device node\n", __func__); - return ERR_PTR(-ENODEV); - } - - count = of_property_count_strings(dev->of_node, "mbox-names"); - if (count < 0) { - pr_err("%s: mbox-names property of node '%s' missing\n", - __func__, dev->of_node->full_name); + pr_debug("%s: No owner device node\n", __func__); return ERR_PTR(-ENODEV); } mutex_lock(&con_mutex); - ret = -ENODEV; - for (i = 0; i < count; i++) { - const char *s; - - if (of_property_read_string_index(dev->of_node, - "mbox-names", i, &s)) - continue; - - if (strcmp(cl->chan_name, s)) - continue; - - if (of_parse_phandle_with_args(dev->of_node, - "mbox", "#mbox-cells", i, &spec)) - continue; - - chan = NULL; - list_for_each_entry(mbox, &mbox_cons, node) - if (mbox->dev->of_node == spec.np) { - chan = mbox->of_xlate(mbox, &spec); - break; - } - - of_node_put(spec.np); - - if (!chan) - continue; + if (of_parse_phandle_with_args(dev->of_node, "mboxes", + "#mbox-cells", index, &spec)) { + dev_dbg(dev, "%s: can't parse \"mboxes\" property\n", __func__); + mutex_unlock(&con_mutex); + return ERR_PTR(-ENODEV); + } - ret = -EBUSY; - if (!chan->cl && try_module_get(mbox->dev->driver->owner)) + chan = NULL; + list_for_each_entry(mbox, &mbox_cons, node) + if (mbox->dev->of_node == spec.np) { + chan = mbox->of_xlate(mbox, &spec); break; - } + } - if (i == count) { + of_node_put(spec.np); + + if (!chan || 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(ret); + return ERR_PTR(-EBUSY); } spin_lock_irqsave(&chan->lock, flags); @@ -361,14 +337,14 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl) chan->cl = cl; init_completion(&chan->tx_complete); - if (chan->txdone_method == TXDONE_BY_POLL - && cl->knows_txdone) + if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone) chan->txdone_method |= TXDONE_BY_ACK; + spin_unlock_irqrestore(&chan->lock, flags); ret = chan->mbox->ops->startup(chan); if (ret) { - pr_err("Unable to startup the chan (%d)\n", ret); + dev_err(dev, "Unable to startup the chan (%d)\n", ret); mbox_free_channel(chan); chan = ERR_PTR(ret); } @@ -406,7 +382,7 @@ EXPORT_SYMBOL_GPL(mbox_free_channel); static struct mbox_chan * of_mbox_index_xlate(struct mbox_controller *mbox, - const struct of_phandle_args *sp) + const struct of_phandle_args *sp) { int ind = sp->args[0]; @@ -420,7 +396,7 @@ of_mbox_index_xlate(struct mbox_controller *mbox, * mbox_controller_register - Register the mailbox controller * @mbox: Pointer to the mailbox controller. * - * The controller driver registers its communication chans + * The controller driver registers its communication channels */ int mbox_controller_register(struct mbox_controller *mbox) { @@ -445,6 +421,7 @@ int mbox_controller_register(struct mbox_controller *mbox) for (i = 0; i < mbox->num_chans; i++) { struct mbox_chan *chan = &mbox->chans[i]; + chan->cl = NULL; chan->mbox = mbox; chan->txdone_method = txdone; @@ -463,7 +440,7 @@ int mbox_controller_register(struct mbox_controller *mbox) EXPORT_SYMBOL_GPL(mbox_controller_register); /** - * mbox_controller_unregister - UnRegister the mailbox controller + * mbox_controller_unregister - Unregister the mailbox controller * @mbox: Pointer to the mailbox controller. */ void mbox_controller_unregister(struct mbox_controller *mbox)