~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to arch/arm/plat-omap/mailbox.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
 
33
33
#include <plat/mailbox.h>
34
34
 
35
 
static struct workqueue_struct *mboxd;
36
35
static struct omap_mbox **mboxes;
37
 
static DEFINE_MUTEX(mboxes_lock);
38
36
 
39
37
static int mbox_configured;
40
38
static DEFINE_MUTEX(mbox_configured_lock);
153
151
                WARN_ON(len != sizeof(msg));
154
152
 
155
153
                blocking_notifier_call_chain(&mq->mbox->notifier, len,
156
 
                                                        (void *)msg);
 
154
                                                                (void *)msg);
157
155
                spin_lock_irq(&mq->lock);
158
156
                if (mq->full) {
159
157
                        mq->full = false;
168
166
 */
169
167
static void __mbox_tx_interrupt(struct omap_mbox *mbox)
170
168
{
171
 
        struct omap_mbox *mbox_curr;
172
 
        int i =0;
173
 
 
174
 
        while (mboxes[i]) {
175
 
                mbox_curr = mboxes[i];
176
 
                if (!mbox_fifo_full(mbox_curr)) {
177
 
                        omap_mbox_disable_irq(mbox_curr, IRQ_TX);
178
 
                        ack_mbox_irq(mbox_curr, IRQ_TX);
179
 
                        tasklet_schedule(&mbox_curr->txq->tasklet);
180
 
                }
181
 
                i++;
182
 
        }
 
169
        omap_mbox_disable_irq(mbox, IRQ_TX);
 
170
        ack_mbox_irq(mbox, IRQ_TX);
 
171
        tasklet_schedule(&mbox->txq->tasklet);
183
172
}
184
173
 
185
174
static void __mbox_rx_interrupt(struct omap_mbox *mbox)
186
175
{
187
 
        struct omap_mbox_queue *mq;
 
176
        struct omap_mbox_queue *mq = mbox->rxq;
188
177
        mbox_msg_t msg;
189
178
        int len;
190
 
        int i = 0;
191
 
        struct omap_mbox *mbox_curr;
192
 
        bool msg_rx;
193
 
 
194
 
        while (mboxes[i]) {
195
 
                mbox_curr = mboxes[i];
196
 
                mq = mbox_curr->rxq;
197
 
                msg_rx = false;
198
 
                while (!mbox_fifo_empty(mbox_curr)) {
199
 
                        msg_rx = true;
200
 
                        if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) {
201
 
                                omap_mbox_disable_irq(mbox_curr, IRQ_RX);
202
 
                                mq->full = true;
203
 
                                goto nomem;
204
 
                        }
205
 
 
206
 
                        msg = mbox_fifo_read(mbox_curr);
207
 
 
208
 
                        len = kfifo_in(&mq->fifo, (unsigned char *)&msg,
209
 
                                                                sizeof(msg));
210
 
                        if (unlikely(len != sizeof(msg)))
211
 
                                pr_err("%s: kfifo_in anomaly detected\n",
212
 
                                                                __func__);
213
 
                        if (mbox->ops->type == OMAP_MBOX_TYPE1)
214
 
                                break;
 
179
 
 
180
        while (!mbox_fifo_empty(mbox)) {
 
181
                if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) {
 
182
                        omap_mbox_disable_irq(mbox, IRQ_RX);
 
183
                        mq->full = true;
 
184
                        goto nomem;
215
185
                }
216
 
                /* no more messages in the fifo. clear IRQ source. */
217
 
                if (msg_rx)
218
 
                        ack_mbox_irq(mbox_curr, IRQ_RX);
 
186
 
 
187
                msg = mbox_fifo_read(mbox);
 
188
 
 
189
                len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
 
190
                WARN_ON(len != sizeof(msg));
 
191
 
 
192
                if (mbox->ops->type == OMAP_MBOX_TYPE1)
 
193
                        break;
 
194
        }
 
195
 
 
196
        /* no more messages in the fifo. clear IRQ source. */
 
197
        ack_mbox_irq(mbox, IRQ_RX);
219
198
nomem:
220
 
                queue_work(mboxd, &mbox->rxq->work);
221
 
 
222
 
                i++;
223
 
        }
 
199
        schedule_work(&mbox->rxq->work);
224
200
}
225
201
 
226
202
static irqreturn_t mbox_interrupt(int irq, void *p)
314
290
fail_alloc_txq:
315
291
        free_irq(mbox->irq, mbox);
316
292
fail_request_irq:
317
 
        if (likely(mbox->ops->shutdown))
 
293
        if (mbox->ops->shutdown)
318
294
                mbox->ops->shutdown(mbox);
319
295
        mbox->use_count--;
320
296
fail_startup:
330
306
        if (!--mbox->use_count) {
331
307
                free_irq(mbox->irq, mbox);
332
308
                tasklet_kill(&mbox->txq->tasklet);
333
 
                flush_work(&mbox->rxq->work);
 
309
        flush_work_sync(&mbox->rxq->work);
334
310
                mbox_queue_free(mbox->txq);
335
311
                mbox_queue_free(mbox->rxq);
336
312
        }
358
334
                }
359
335
        }
360
336
 
361
 
        if (!mbox) {
362
 
                mutex_unlock(&mboxes_lock);
 
337
        if (!mbox)
363
338
                return ERR_PTR(-ENOENT);
364
 
        }
365
 
        mutex_unlock(&mboxes_lock);
366
339
 
367
340
        ret = omap_mbox_startup(mbox);
368
341
        if (ret)
377
350
 
378
351
void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb)
379
352
{
380
 
        if (nb)
381
 
                blocking_notifier_chain_unregister(&mbox->notifier, nb);
 
353
        blocking_notifier_chain_unregister(&mbox->notifier, nb);
382
354
        omap_mbox_fini(mbox);
383
355
}
384
356
EXPORT_SYMBOL(omap_mbox_put);
393
365
        mboxes = list;
394
366
        if (!mboxes)
395
367
                return -EINVAL;
396
 
        mutex_lock(&mboxes_lock);
397
368
 
398
369
        for (i = 0; mboxes[i]; i++) {
399
370
                struct omap_mbox *mbox = mboxes[i];
406
377
 
407
378
                BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
408
379
        }
409
 
        mutex_unlock(&mboxes_lock);
410
380
        return 0;
411
381
 
412
382
err_out:
413
383
        while (i--)
414
384
                device_unregister(mboxes[i]->dev);
415
 
        mutex_unlock(&mboxes_lock);
416
385
        return ret;
417
386
}
418
387
EXPORT_SYMBOL(omap_mbox_register);
424
393
        if (!mboxes)
425
394
                return -EINVAL;
426
395
 
427
 
        mutex_lock(&mboxes_lock);
428
396
        for (i = 0; mboxes[i]; i++)
429
397
                device_unregister(mboxes[i]->dev);
430
398
        mboxes = NULL;
431
 
        mutex_unlock(&mboxes_lock);
432
399
        return 0;
433
400
}
434
401
EXPORT_SYMBOL(omap_mbox_unregister);
441
408
        if (err)
442
409
                return err;
443
410
 
444
 
        mboxd = create_workqueue("mboxd");
445
 
        if (!mboxd)
446
 
                return -ENOMEM;
447
 
 
448
411
        /* kfifo size sanity check: alignment and minimal size */
449
412
        mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t));
450
413
        mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
456
419
 
457
420
static void __exit omap_mbox_exit(void)
458
421
{
459
 
        destroy_workqueue(mboxd);
460
422
        class_unregister(&omap_mbox_class);
461
423
}
462
424
module_exit(omap_mbox_exit);