Merge tag 'nfsd-6.5-5' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
[platform/kernel/linux-rpi.git] / drivers / mailbox / mailbox.c
index 4229b9b..adf36c0 100644 (file)
@@ -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;