This patch provides mutiple readers support for a mailbox instance. Signed-off-by: Hari Kanigeri <h-kanigeri2@xxxxxx> --- arch/arm/plat-omap/include/plat/mailbox.h | 6 ++- arch/arm/plat-omap/mailbox.c | 63 ++++++++++++++++------------ 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/arch/arm/plat-omap/include/plat/mailbox.h b/arch/arm/plat-omap/include/plat/mailbox.h index 0486d64..c8e47d8 100644 --- a/arch/arm/plat-omap/include/plat/mailbox.h +++ b/arch/arm/plat-omap/include/plat/mailbox.h @@ -68,13 +68,15 @@ struct omap_mbox { void *priv; void (*err_notify)(void); + atomic_t use_count; + struct blocking_notifier_head notifier; }; int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg); void omap_mbox_init_seq(struct omap_mbox *); -struct omap_mbox *omap_mbox_get(const char *); -void omap_mbox_put(struct omap_mbox *); +struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb); +void omap_mbox_put(struct omap_mbox *, struct notifier_block *nb); int omap_mbox_register(struct device *parent, struct omap_mbox *); int omap_mbox_unregister(struct omap_mbox *); diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index baac315..f9f2af4 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -149,8 +149,8 @@ static void mbox_rx_work(struct work_struct *work) if (unlikely(len != sizeof(msg))) pr_err("%s: kfifo_out anomaly detected\n", __func__); - if (mq->callback) - mq->callback((void *)msg); + blocking_notifier_call_chain(&mq->mbox->notifier, len, + (void *)msg); } } @@ -252,28 +252,30 @@ static int omap_mbox_startup(struct omap_mbox *mbox) } } - ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, - mbox->name, mbox); - if (unlikely(ret)) { - printk(KERN_ERR - "failed to register mailbox interrupt:%d\n", ret); - goto fail_request_irq; - } + if (atomic_inc_return(&mbox->use_count) == 1) { + ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, + mbox->name, mbox); + if (unlikely(ret)) { + printk(KERN_ERR "failed to register mailbox interrupt:" + "%d\n", ret); + goto fail_request_irq; + } - mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); - if (!mq) { - ret = -ENOMEM; - goto fail_alloc_txq; - } - mbox->txq = mq; + mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); + if (!mq) { + ret = -ENOMEM; + goto fail_alloc_txq; + } + mbox->txq = mq; - mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL); - if (!mq) { - ret = -ENOMEM; - goto fail_alloc_rxq; + mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL); + if (!mq) { + ret = -ENOMEM; + goto fail_alloc_rxq; + } + mbox->rxq = mq; + mq->mbox = mbox; } - mbox->rxq = mq; - return 0; fail_alloc_rxq: @@ -281,6 +283,7 @@ static int omap_mbox_startup(struct omap_mbox *mbox) fail_alloc_txq: free_irq(mbox->irq, mbox); fail_request_irq: + atomic_dec(&mbox->use_count); if (likely(mbox->ops->shutdown)) { if (atomic_dec_return(&mbox_refcount) == 0) mbox->ops->shutdown(mbox); @@ -291,10 +294,12 @@ static int omap_mbox_startup(struct omap_mbox *mbox) static void omap_mbox_fini(struct omap_mbox *mbox) { - mbox_queue_free(mbox->txq); - mbox_queue_free(mbox->rxq); - free_irq(mbox->irq, mbox); + if (atomic_dec_return(&mbox->use_count) == 0) { + mbox_queue_free(mbox->txq); + mbox_queue_free(mbox->rxq); + free_irq(mbox->irq, mbox); + } if (likely(mbox->ops->shutdown)) { if (atomic_dec_return(&mbox_refcount) == 0) @@ -314,7 +319,7 @@ static struct omap_mbox **find_mboxes(const char *name) return p; } -struct omap_mbox *omap_mbox_get(const char *name) +struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) { struct omap_mbox *mbox; int ret; @@ -325,19 +330,21 @@ struct omap_mbox *omap_mbox_get(const char *name) spin_unlock(&mboxes_lock); return ERR_PTR(-ENOENT); } - spin_unlock(&mboxes_lock); ret = omap_mbox_startup(mbox); if (ret) return ERR_PTR(-ENODEV); + if (nb) + blocking_notifier_chain_register(&mbox->notifier, nb); return mbox; } EXPORT_SYMBOL(omap_mbox_get); -void omap_mbox_put(struct omap_mbox *mbox) +void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb) { + blocking_notifier_chain_unregister(&mbox->notifier, nb); omap_mbox_fini(mbox); } EXPORT_SYMBOL(omap_mbox_put); @@ -361,6 +368,8 @@ int omap_mbox_register(struct device *parent, struct omap_mbox *mbox) } *tmp = mbox; spin_unlock(&mboxes_lock); + BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier); + atomic_set(&mbox->use_count, 0); return 0; -- 1.7.0 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html