[PATCH 2/2] omap:mailbox-provide multiple reader support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux