These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / mailbox / mailbox.c
index 19b491d..6a4811f 100644 (file)
@@ -26,8 +26,6 @@
 static LIST_HEAD(mbox_cons);
 static DEFINE_MUTEX(con_mutex);
 
-static void poll_txdone(unsigned long data);
-
 static int add_to_rbuf(struct mbox_chan *chan, void *mssg)
 {
        int idx;
@@ -88,7 +86,9 @@ exit:
        spin_unlock_irqrestore(&chan->lock, flags);
 
        if (!err && (chan->txdone_method & TXDONE_BY_POLL))
-               poll_txdone((unsigned long)chan->mbox);
+               /* kick start the timer immediately to avoid delays */
+               hrtimer_start(&chan->mbox->poll_hrt, ktime_set(0, 0),
+                             HRTIMER_MODE_REL);
 }
 
 static void tx_tick(struct mbox_chan *chan, int r)
@@ -112,9 +112,10 @@ static void tx_tick(struct mbox_chan *chan, int r)
                complete(&chan->tx_complete);
 }
 
-static void poll_txdone(unsigned long data)
+static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer)
 {
-       struct mbox_controller *mbox = (struct mbox_controller *)data;
+       struct mbox_controller *mbox =
+               container_of(hrtimer, struct mbox_controller, poll_hrt);
        bool txdone, resched = false;
        int i;
 
@@ -130,9 +131,11 @@ static void poll_txdone(unsigned long data)
                }
        }
 
-       if (resched)
-               mod_timer(&mbox->poll, jiffies +
-                               msecs_to_jiffies(mbox->txpoll_period));
+       if (resched) {
+               hrtimer_forward_now(hrtimer, ms_to_ktime(mbox->txpoll_period));
+               return HRTIMER_RESTART;
+       }
+       return HRTIMER_NORESTART;
 }
 
 /**
@@ -318,7 +321,7 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
                return ERR_PTR(-ENODEV);
        }
 
-       chan = NULL;
+       chan = ERR_PTR(-EPROBE_DEFER);
        list_for_each_entry(mbox, &mbox_cons, node)
                if (mbox->dev->of_node == spec.np) {
                        chan = mbox->of_xlate(mbox, &spec);
@@ -327,7 +330,12 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
 
        of_node_put(spec.np);
 
-       if (!chan || chan->cl || !try_module_get(mbox->dev->driver->owner)) {
+       if (IS_ERR(chan)) {
+               mutex_unlock(&con_mutex);
+               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);
@@ -357,6 +365,35 @@ struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
 }
 EXPORT_SYMBOL_GPL(mbox_request_channel);
 
+struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,
+                                             const char *name)
+{
+       struct device_node *np = cl->dev->of_node;
+       struct property *prop;
+       const char *mbox_name;
+       int index = 0;
+
+       if (!np) {
+               dev_err(cl->dev, "%s() currently only supports DT\n", __func__);
+               return ERR_PTR(-ENOSYS);
+       }
+
+       if (!of_get_property(np, "mbox-names", NULL)) {
+               dev_err(cl->dev,
+                       "%s() requires an \"mbox-names\" property\n", __func__);
+               return ERR_PTR(-ENOSYS);
+       }
+
+       of_property_for_each_string(np, "mbox-names", prop, mbox_name) {
+               if (!strncmp(name, mbox_name, strlen(name)))
+                       break;
+               index++;
+       }
+
+       return mbox_request_channel(cl, index);
+}
+EXPORT_SYMBOL_GPL(mbox_request_channel_byname);
+
 /**
  * mbox_free_channel - The client relinquishes control of a mailbox
  *                     channel by this call.
@@ -390,7 +427,7 @@ of_mbox_index_xlate(struct mbox_controller *mbox,
        int ind = sp->args[0];
 
        if (ind >= mbox->num_chans)
-               return NULL;
+               return ERR_PTR(-EINVAL);
 
        return &mbox->chans[ind];
 }
@@ -417,9 +454,9 @@ int mbox_controller_register(struct mbox_controller *mbox)
                txdone = TXDONE_BY_ACK;
 
        if (txdone == TXDONE_BY_POLL) {
-               mbox->poll.function = &poll_txdone;
-               mbox->poll.data = (unsigned long)mbox;
-               init_timer(&mbox->poll);
+               hrtimer_init(&mbox->poll_hrt, CLOCK_MONOTONIC,
+                            HRTIMER_MODE_REL);
+               mbox->poll_hrt.function = txdone_hrtimer;
        }
 
        for (i = 0; i < mbox->num_chans; i++) {
@@ -461,7 +498,7 @@ void mbox_controller_unregister(struct mbox_controller *mbox)
                mbox_free_channel(&mbox->chans[i]);
 
        if (mbox->txdone_poll)
-               del_timer_sync(&mbox->poll);
+               hrtimer_cancel(&mbox->poll_hrt);
 
        mutex_unlock(&con_mutex);
 }