linux/drivers/mailbox/mailbox.c
<<
>>
Prefs
   1/*
   2 * Mailbox: Common code for Mailbox controllers and users
   3 *
   4 * Copyright (C) 2013-2014 Linaro Ltd.
   5 * Author: Jassi Brar <jassisinghbrar@gmail.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/interrupt.h>
  13#include <linux/spinlock.h>
  14#include <linux/mutex.h>
  15#include <linux/delay.h>
  16#include <linux/slab.h>
  17#include <linux/err.h>
  18#include <linux/module.h>
  19#include <linux/device.h>
  20#include <linux/bitops.h>
  21#include <linux/mailbox_client.h>
  22#include <linux/mailbox_controller.h>
  23
  24#include "mailbox.h"
  25
  26static LIST_HEAD(mbox_cons);
  27static DEFINE_MUTEX(con_mutex);
  28
  29static int add_to_rbuf(struct mbox_chan *chan, void *mssg)
  30{
  31        int idx;
  32        unsigned long flags;
  33
  34        spin_lock_irqsave(&chan->lock, flags);
  35
  36        /* See if there is any space left */
  37        if (chan->msg_count == MBOX_TX_QUEUE_LEN) {
  38                spin_unlock_irqrestore(&chan->lock, flags);
  39                return -ENOBUFS;
  40        }
  41
  42        idx = chan->msg_free;
  43        chan->msg_data[idx] = mssg;
  44        chan->msg_count++;
  45
  46        if (idx == MBOX_TX_QUEUE_LEN - 1)
  47                chan->msg_free = 0;
  48        else
  49                chan->msg_free++;
  50
  51        spin_unlock_irqrestore(&chan->lock, flags);
  52
  53        return idx;
  54}
  55
  56static void msg_submit(struct mbox_chan *chan)
  57{
  58        unsigned count, idx;
  59        unsigned long flags;
  60        void *data;
  61        int err = -EBUSY;
  62
  63        spin_lock_irqsave(&chan->lock, flags);
  64
  65        if (!chan->msg_count || chan->active_req)
  66                goto exit;
  67
  68        count = chan->msg_count;
  69        idx = chan->msg_free;
  70        if (idx >= count)
  71                idx -= count;
  72        else
  73                idx += MBOX_TX_QUEUE_LEN - count;
  74
  75        data = chan->msg_data[idx];
  76
  77        if (chan->cl->tx_prepare)
  78                chan->cl->tx_prepare(chan->cl, data);
  79        /* Try to submit a message to the MBOX controller */
  80        err = chan->mbox->ops->send_data(chan, data);
  81        if (!err) {
  82                chan->active_req = data;
  83                chan->msg_count--;
  84        }
  85exit:
  86        spin_unlock_irqrestore(&chan->lock, flags);
  87
  88        if (!err && (chan->txdone_method & TXDONE_BY_POLL))
  89                /* kick start the timer immediately to avoid delays */
  90                hrtimer_start(&chan->mbox->poll_hrt, 0, HRTIMER_MODE_REL);
  91}
  92
  93static void tx_tick(struct mbox_chan *chan, int r)
  94{
  95        unsigned long flags;
  96        void *mssg;
  97
  98        spin_lock_irqsave(&chan->lock, flags);
  99        mssg = chan->active_req;
 100        chan->active_req = NULL;
 101        spin_unlock_irqrestore(&chan->lock, flags);
 102
 103        /* Submit next message */
 104        msg_submit(chan);
 105
 106        if (!mssg)
 107                return;
 108
 109        /* Notify the client */
 110        if (chan->cl->tx_done)
 111                chan->cl->tx_done(chan->cl, mssg, r);
 112
 113        if (r != -ETIME && chan->cl->tx_block)
 114                complete(&chan->tx_complete);
 115}
 116
 117static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer)
 118{
 119        struct mbox_controller *mbox =
 120                container_of(hrtimer, struct mbox_controller, poll_hrt);
 121        bool txdone, resched = false;
 122        int i;
 123
 124        for (i = 0; i < mbox->num_chans; i++) {
 125                struct mbox_chan *chan = &mbox->chans[i];
 126
 127                if (chan->active_req && chan->cl) {
 128                        txdone = chan->mbox->ops->last_tx_done(chan);
 129                        if (txdone)
 130                                tx_tick(chan, 0);
 131                        else
 132                                resched = true;
 133                }
 134        }
 135
 136        if (resched) {
 137                hrtimer_forward_now(hrtimer, ms_to_ktime(mbox->txpoll_period));
 138                return HRTIMER_RESTART;
 139        }
 140        return HRTIMER_NORESTART;
 141}
 142
 143/**
 144 * mbox_chan_received_data - A way for controller driver to push data
 145 *                              received from remote to the upper layer.
 146 * @chan: Pointer to the mailbox channel on which RX happened.
 147 * @mssg: Client specific message typecasted as void *
 148 *
 149 * After startup and before shutdown any data received on the chan
 150 * is passed on to the API via atomic mbox_chan_received_data().
 151 * The controller should ACK the RX only after this call returns.
 152 */
 153void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)
 154{
 155        /* No buffering the received data */
 156        if (chan->cl->rx_callback)
 157                chan->cl->rx_callback(chan->cl, mssg);
 158}
 159EXPORT_SYMBOL_GPL(mbox_chan_received_data);
 160
 161/**
 162 * mbox_chan_txdone - A way for controller driver to notify the
 163 *                      framework that the last TX has completed.
 164 * @chan: Pointer to the mailbox chan on which TX happened.
 165 * @r: Status of last TX - OK or ERROR
 166 *
 167 * The controller that has IRQ for TX ACK calls this atomic API
 168 * to tick the TX state machine. It works only if txdone_irq
 169 * is set by the controller.
 170 */
 171void mbox_chan_txdone(struct mbox_chan *chan, int r)
 172{
 173        if (unlikely(!(chan->txdone_method & TXDONE_BY_IRQ))) {
 174                dev_err(chan->mbox->dev,
 175                       "Controller can't run the TX ticker\n");
 176                return;
 177        }
 178
 179        tx_tick(chan, r);
 180}
 181EXPORT_SYMBOL_GPL(mbox_chan_txdone);
 182
 183/**
 184 * mbox_client_txdone - The way for a client to run the TX state machine.
 185 * @chan: Mailbox channel assigned to this client.
 186 * @r: Success status of last transmission.
 187 *
 188 * The client/protocol had received some 'ACK' packet and it notifies
 189 * the API that the last packet was sent successfully. This only works
 190 * if the controller can't sense TX-Done.
 191 */
 192void mbox_client_txdone(struct mbox_chan *chan, int r)
 193{
 194        if (unlikely(!(chan->txdone_method & TXDONE_BY_ACK))) {
 195                dev_err(chan->mbox->dev, "Client can't run the TX ticker\n");
 196                return;
 197        }
 198
 199        tx_tick(chan, r);
 200}
 201EXPORT_SYMBOL_GPL(mbox_client_txdone);
 202
 203/**
 204 * mbox_client_peek_data - A way for client driver to pull data
 205 *                      received from remote by the controller.
 206 * @chan: Mailbox channel assigned to this client.
 207 *
 208 * A poke to controller driver for any received data.
 209 * The data is actually passed onto client via the
 210 * mbox_chan_received_data()
 211 * The call can be made from atomic context, so the controller's
 212 * implementation of peek_data() must not sleep.
 213 *
 214 * Return: True, if controller has, and is going to push after this,
 215 *          some data.
 216 *         False, if controller doesn't have any data to be read.
 217 */
 218bool mbox_client_peek_data(struct mbox_chan *chan)
 219{
 220        if (chan->mbox->ops->peek_data)
 221                return chan->mbox->ops->peek_data(chan);
 222
 223        return false;
 224}
 225EXPORT_SYMBOL_GPL(mbox_client_peek_data);
 226
 227/**
 228 * mbox_send_message -  For client to submit a message to be
 229 *                              sent to the remote.
 230 * @chan: Mailbox channel assigned to this client.
 231 * @mssg: Client specific message typecasted.
 232 *
 233 * For client to submit data to the controller destined for a remote
 234 * processor. If the client had set 'tx_block', the call will return
 235 * either when the remote receives the data or when 'tx_tout' millisecs
 236 * run out.
 237 *  In non-blocking mode, the requests are buffered by the API and a
 238 * non-negative token is returned for each queued request. If the request
 239 * is not queued, a negative token is returned. Upon failure or successful
 240 * TX, the API calls 'tx_done' from atomic context, from which the client
 241 * could submit yet another request.
 242 * The pointer to message should be preserved until it is sent
 243 * over the chan, i.e, tx_done() is made.
 244 * This function could be called from atomic context as it simply
 245 * queues the data and returns a token against the request.
 246 *
 247 * Return: Non-negative integer for successful submission (non-blocking mode)
 248 *      or transmission over chan (blocking mode).
 249 *      Negative value denotes failure.
 250 */
 251int mbox_send_message(struct mbox_chan *chan, void *mssg)
 252{
 253        int t;
 254
 255        if (!chan || !chan->cl)
 256                return -EINVAL;
 257
 258        t = add_to_rbuf(chan, mssg);
 259        if (t < 0) {
 260                dev_err(chan->mbox->dev, "Try increasing MBOX_TX_QUEUE_LEN\n");
 261                return t;
 262        }
 263
 264        msg_submit(chan);
 265
 266        if (chan->cl->tx_block) {
 267                unsigned long wait;
 268                int ret;
 269
 270                if (!chan->cl->tx_tout) /* wait forever */
 271                        wait = msecs_to_jiffies(3600000);
 272                else
 273                        wait = msecs_to_jiffies(chan->cl->tx_tout);
 274
 275                ret = wait_for_completion_timeout(&chan->tx_complete, wait);
 276                if (ret == 0) {
 277                        t = -ETIME;
 278                        tx_tick(chan, t);
 279                }
 280        }
 281
 282        return t;
 283}
 284EXPORT_SYMBOL_GPL(mbox_send_message);
 285
 286/**
 287 * mbox_request_channel - Request a mailbox channel.
 288 * @cl: Identity of the client requesting the channel.
 289 * @index: Index of mailbox specifier in 'mboxes' property.
 290 *
 291 * The Client specifies its requirements and capabilities while asking for
 292 * a mailbox channel. It can't be called from atomic context.
 293 * The channel is exclusively allocated and can't be used by another
 294 * client before the owner calls mbox_free_channel.
 295 * After assignment, any packet received on this channel will be
 296 * handed over to the client via the 'rx_callback'.
 297 * The framework holds reference to the client, so the mbox_client
 298 * structure shouldn't be modified until the mbox_free_channel returns.
 299 *
 300 * Return: Pointer to the channel assigned to the client if successful.
 301 *              ERR_PTR for request failure.
 302 */
 303struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
 304{
 305        struct device *dev = cl->dev;
 306        struct mbox_controller *mbox;
 307        struct of_phandle_args spec;
 308        struct mbox_chan *chan;
 309        unsigned long flags;
 310        int ret;
 311
 312        if (!dev || !dev->of_node) {
 313                pr_debug("%s: No owner device node\n", __func__);
 314                return ERR_PTR(-ENODEV);
 315        }
 316
 317        mutex_lock(&con_mutex);
 318
 319        if (of_parse_phandle_with_args(dev->of_node, "mboxes",
 320                                       "#mbox-cells", index, &spec)) {
 321                dev_dbg(dev, "%s: can't parse \"mboxes\" property\n", __func__);
 322                mutex_unlock(&con_mutex);
 323                return ERR_PTR(-ENODEV);
 324        }
 325
 326        chan = ERR_PTR(-EPROBE_DEFER);
 327        list_for_each_entry(mbox, &mbox_cons, node)
 328                if (mbox->dev->of_node == spec.np) {
 329                        chan = mbox->of_xlate(mbox, &spec);
 330                        break;
 331                }
 332
 333        of_node_put(spec.np);
 334
 335        if (IS_ERR(chan)) {
 336                mutex_unlock(&con_mutex);
 337                return chan;
 338        }
 339
 340        if (chan->cl || !try_module_get(mbox->dev->driver->owner)) {
 341                dev_dbg(dev, "%s: mailbox not free\n", __func__);
 342                mutex_unlock(&con_mutex);
 343                return ERR_PTR(-EBUSY);
 344        }
 345
 346        spin_lock_irqsave(&chan->lock, flags);
 347        chan->msg_free = 0;
 348        chan->msg_count = 0;
 349        chan->active_req = NULL;
 350        chan->cl = cl;
 351        init_completion(&chan->tx_complete);
 352
 353        if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
 354                chan->txdone_method = TXDONE_BY_ACK;
 355
 356        spin_unlock_irqrestore(&chan->lock, flags);
 357
 358        if (chan->mbox->ops->startup) {
 359                ret = chan->mbox->ops->startup(chan);
 360
 361                if (ret) {
 362                        dev_err(dev, "Unable to startup the chan (%d)\n", ret);
 363                        mbox_free_channel(chan);
 364                        chan = ERR_PTR(ret);
 365                }
 366        }
 367
 368        mutex_unlock(&con_mutex);
 369        return chan;
 370}
 371EXPORT_SYMBOL_GPL(mbox_request_channel);
 372
 373struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,
 374                                              const char *name)
 375{
 376        struct device_node *np = cl->dev->of_node;
 377        struct property *prop;
 378        const char *mbox_name;
 379        int index = 0;
 380
 381        if (!np) {
 382                dev_err(cl->dev, "%s() currently only supports DT\n", __func__);
 383                return ERR_PTR(-EINVAL);
 384        }
 385
 386        if (!of_get_property(np, "mbox-names", NULL)) {
 387                dev_err(cl->dev,
 388                        "%s() requires an \"mbox-names\" property\n", __func__);
 389                return ERR_PTR(-EINVAL);
 390        }
 391
 392        of_property_for_each_string(np, "mbox-names", prop, mbox_name) {
 393                if (!strncmp(name, mbox_name, strlen(name)))
 394                        break;
 395                index++;
 396        }
 397
 398        return mbox_request_channel(cl, index);
 399}
 400EXPORT_SYMBOL_GPL(mbox_request_channel_byname);
 401
 402/**
 403 * mbox_free_channel - The client relinquishes control of a mailbox
 404 *                      channel by this call.
 405 * @chan: The mailbox channel to be freed.
 406 */
 407void mbox_free_channel(struct mbox_chan *chan)
 408{
 409        unsigned long flags;
 410
 411        if (!chan || !chan->cl)
 412                return;
 413
 414        if (chan->mbox->ops->shutdown)
 415                chan->mbox->ops->shutdown(chan);
 416
 417        /* The queued TX requests are simply aborted, no callbacks are made */
 418        spin_lock_irqsave(&chan->lock, flags);
 419        chan->cl = NULL;
 420        chan->active_req = NULL;
 421        if (chan->txdone_method == TXDONE_BY_ACK)
 422                chan->txdone_method = TXDONE_BY_POLL;
 423
 424        module_put(chan->mbox->dev->driver->owner);
 425        spin_unlock_irqrestore(&chan->lock, flags);
 426}
 427EXPORT_SYMBOL_GPL(mbox_free_channel);
 428
 429static struct mbox_chan *
 430of_mbox_index_xlate(struct mbox_controller *mbox,
 431                    const struct of_phandle_args *sp)
 432{
 433        int ind = sp->args[0];
 434
 435        if (ind >= mbox->num_chans)
 436                return ERR_PTR(-EINVAL);
 437
 438        return &mbox->chans[ind];
 439}
 440
 441/**
 442 * mbox_controller_register - Register the mailbox controller
 443 * @mbox:       Pointer to the mailbox controller.
 444 *
 445 * The controller driver registers its communication channels
 446 */
 447int mbox_controller_register(struct mbox_controller *mbox)
 448{
 449        int i, txdone;
 450
 451        /* Sanity check */
 452        if (!mbox || !mbox->dev || !mbox->ops || !mbox->num_chans)
 453                return -EINVAL;
 454
 455        if (mbox->txdone_irq)
 456                txdone = TXDONE_BY_IRQ;
 457        else if (mbox->txdone_poll)
 458                txdone = TXDONE_BY_POLL;
 459        else /* It has to be ACK then */
 460                txdone = TXDONE_BY_ACK;
 461
 462        if (txdone == TXDONE_BY_POLL) {
 463
 464                if (!mbox->ops->last_tx_done) {
 465                        dev_err(mbox->dev, "last_tx_done method is absent\n");
 466                        return -EINVAL;
 467                }
 468
 469                hrtimer_init(&mbox->poll_hrt, CLOCK_MONOTONIC,
 470                             HRTIMER_MODE_REL);
 471                mbox->poll_hrt.function = txdone_hrtimer;
 472        }
 473
 474        for (i = 0; i < mbox->num_chans; i++) {
 475                struct mbox_chan *chan = &mbox->chans[i];
 476
 477                chan->cl = NULL;
 478                chan->mbox = mbox;
 479                chan->txdone_method = txdone;
 480                spin_lock_init(&chan->lock);
 481        }
 482
 483        if (!mbox->of_xlate)
 484                mbox->of_xlate = of_mbox_index_xlate;
 485
 486        mutex_lock(&con_mutex);
 487        list_add_tail(&mbox->node, &mbox_cons);
 488        mutex_unlock(&con_mutex);
 489
 490        return 0;
 491}
 492EXPORT_SYMBOL_GPL(mbox_controller_register);
 493
 494/**
 495 * mbox_controller_unregister - Unregister the mailbox controller
 496 * @mbox:       Pointer to the mailbox controller.
 497 */
 498void mbox_controller_unregister(struct mbox_controller *mbox)
 499{
 500        int i;
 501
 502        if (!mbox)
 503                return;
 504
 505        mutex_lock(&con_mutex);
 506
 507        list_del(&mbox->node);
 508
 509        for (i = 0; i < mbox->num_chans; i++)
 510                mbox_free_channel(&mbox->chans[i]);
 511
 512        if (mbox->txdone_poll)
 513                hrtimer_cancel(&mbox->poll_hrt);
 514
 515        mutex_unlock(&con_mutex);
 516}
 517EXPORT_SYMBOL_GPL(mbox_controller_unregister);
 518