mailbox: Support blocking transfers in atomic context
authorThierry Reding <treding@nvidia.com>
Wed, 28 Nov 2018 09:54:10 +0000 (10:54 +0100)
committerJassi Brar <jaswinder.singh@linaro.org>
Sat, 22 Dec 2018 04:31:26 +0000 (22:31 -0600)
The mailbox framework supports blocking transfers via completions for
clients that can sleep. In order to support blocking transfers in cases
where the transmission is not permitted to sleep, add a new ->flush()
callback that controller drivers can implement to busy loop until the
transmission has been completed. A new mbox_flush() function can be
called by mailbox consumers in atomic context to make sure a transfer
has completed.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
drivers/mailbox/mailbox.c
include/linux/mailbox_client.h
include/linux/mailbox_controller.h

index 08ce9a1..6abb35f 100644 (file)
@@ -283,6 +283,34 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
 }
 EXPORT_SYMBOL_GPL(mbox_send_message);
 
+/**
+ * mbox_flush - flush a mailbox channel
+ * @chan: mailbox channel to flush
+ * @timeout: time, in milliseconds, to allow the flush operation to succeed
+ *
+ * Mailbox controllers that need to work in atomic context can implement the
+ * ->flush() callback to busy loop until a transmission has been completed.
+ * The implementation must call mbox_chan_txdone() upon success. Clients can
+ * call the mbox_flush() function at any time after mbox_send_message() to
+ * flush the transmission. After the function returns success, the mailbox
+ * transmission is guaranteed to have completed.
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+int mbox_flush(struct mbox_chan *chan, unsigned long timeout)
+{
+       int ret;
+
+       if (!chan->mbox->ops->flush)
+               return -ENOTSUPP;
+
+       ret = chan->mbox->ops->flush(chan, timeout);
+       if (ret < 0)
+               tx_tick(chan, ret);
+
+       return ret;
+}
+
 /**
  * mbox_request_channel - Request a mailbox channel.
  * @cl: Identity of the client requesting the channel.
index 4434871..faa7da3 100644 (file)
@@ -44,6 +44,7 @@ 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);
 int mbox_send_message(struct mbox_chan *chan, void *mssg);
+int mbox_flush(struct mbox_chan *chan, unsigned long timeout);
 void mbox_client_txdone(struct mbox_chan *chan, int r); /* atomic */
 bool mbox_client_peek_data(struct mbox_chan *chan); /* atomic */
 void mbox_free_channel(struct mbox_chan *chan); /* may sleep */
index 9b0b212..4994a43 100644 (file)
@@ -24,6 +24,9 @@ struct mbox_chan;
  *             transmission of data is reported by the controller via
  *             mbox_chan_txdone (if it has some TX ACK irq). It must not
  *             sleep.
+ * @flush:     Called when a client requests transmissions to be blocking but
+ *             the context doesn't allow sleeping. Typically the controller
+ *             will implement a busy loop waiting for the data to flush out.
  * @startup:   Called when a client requests the chan. The controller
  *             could ask clients for additional parameters of communication
  *             to be provided via client's chan_data. This call may
@@ -46,6 +49,7 @@ struct mbox_chan;
  */
 struct mbox_chan_ops {
        int (*send_data)(struct mbox_chan *chan, void *data);
+       int (*flush)(struct mbox_chan *chan, unsigned long timeout);
        int (*startup)(struct mbox_chan *chan);
        void (*shutdown)(struct mbox_chan *chan);
        bool (*last_tx_done)(struct mbox_chan *chan);