From patchwork Thu Oct 14 01:33:22 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Kanigeri, Hari" X-Patchwork-Id: 251761 X-Patchwork-Delegate: hiroshi.doyu@nokia.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o9E1XqeR008484 for ; Thu, 14 Oct 2010 01:35:32 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754044Ab0JNBdv (ORCPT ); Wed, 13 Oct 2010 21:33:51 -0400 Received: from comal.ext.ti.com ([198.47.26.152]:46061 "EHLO comal.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753993Ab0JNBdu (ORCPT ); Wed, 13 Oct 2010 21:33:50 -0400 Received: from dlep35.itg.ti.com ([157.170.170.118]) by comal.ext.ti.com (8.13.7/8.13.7) with ESMTP id o9E1Xl8G031762 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 13 Oct 2010 20:33:47 -0500 Received: from legion.dal.design.ti.com (localhost [127.0.0.1]) by dlep35.itg.ti.com (8.13.7/8.13.7) with ESMTP id o9E1XkLI013359; Wed, 13 Oct 2010 20:33:46 -0500 (CDT) Received: from localhost (matrix.am.dhcp.ti.com [128.247.75.166]) by legion.dal.design.ti.com (8.11.7p1+Sun/8.11.7) with ESMTP id o9E1Xkf11419; Wed, 13 Oct 2010 20:33:46 -0500 (CDT) From: Hari Kanigeri To: Hiroshi Doyu , linux omap Cc: Tony Lindgren , Ohad Ben-Cohen , Hari Kanigeri , Fernando Guzman Lugo Subject: [PATCH 6/7] omap:mailbox-add notification support for multiple readers Date: Wed, 13 Oct 2010 20:33:22 -0500 Message-Id: <1287020003-19667-7-git-send-email-h-kanigeri2@ti.com> X-Mailer: git-send-email 1.7.0 In-Reply-To: <1287020003-19667-1-git-send-email-h-kanigeri2@ti.com> References: <1287020003-19667-1-git-send-email-h-kanigeri2@ti.com> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Thu, 14 Oct 2010 01:35:33 +0000 (UTC) diff --git a/arch/arm/plat-omap/include/plat/mailbox.h b/arch/arm/plat-omap/include/plat/mailbox.h index 13f2ef3..4c35654 100644 --- a/arch/arm/plat-omap/include/plat/mailbox.h +++ b/arch/arm/plat-omap/include/plat/mailbox.h @@ -8,6 +8,7 @@ #include #include #include +#include typedef u32 mbox_msg_t; struct omap_mbox; @@ -46,7 +47,6 @@ struct omap_mbox_queue { struct kfifo fifo; struct work_struct work; struct tasklet_struct tasklet; - int (*callback)(void *); struct omap_mbox *mbox; bool full; }; @@ -58,13 +58,16 @@ struct omap_mbox { struct omap_mbox_ops *ops; struct device *dev; void *priv; + + int 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 *mbox, struct notifier_block *nb); int omap_mbox_register(struct device *parent, struct omap_mbox **); int omap_mbox_unregister(void); diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 1727548..35956f5 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -150,8 +151,8 @@ static void mbox_rx_work(struct work_struct *work) len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); WARN_ON(len != sizeof(msg)); - if (mq->callback) - mq->callback((void *)msg); + blocking_notifier_call_chain(&mq->mbox->notifier, len, + (void *)msg); if (mq->full) { mq->full = false; omap_mbox_enable_irq(mq->mbox, IRQ_RX); @@ -202,7 +203,7 @@ nomem: static irqreturn_t mbox_interrupt(int irq, void *p) { - struct omap_mbox *mbox = p; + int i; for (i = 0; mboxes[i]; i++) { struct omap_mbox *mbox = mboxes[i]; @@ -252,41 +253,39 @@ static int omap_mbox_startup(struct omap_mbox *mbox) int ret = 0; struct omap_mbox_queue *mq; - if (mbox->ops->startup) { - mutex_lock(&mbox_configured_lock); - if (!mbox_configured) + mutex_lock(&mbox_configured_lock); + if (!mbox_configured++) { + if (likely(mbox->ops->startup)) { ret = mbox->ops->startup(mbox); - - if (ret) { - mutex_unlock(&mbox_configured_lock); - return ret; + if (unlikely(ret)) + goto fail_startup; } - mbox_configured++; - mutex_unlock(&mbox_configured_lock); } - ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, - mbox->name, mbox); - if (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; + if (!mbox->use_count++) { + ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, + mbox->name, mbox); + if (unlikely(ret)) { + pr_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, 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; - + mutex_unlock(&mbox_configured_lock); return 0; fail_alloc_rxq: @@ -296,29 +295,36 @@ fail_alloc_txq: fail_request_irq: if (mbox->ops->shutdown) mbox->ops->shutdown(mbox); - + mbox->use_count--; +fail_startup: + mbox_configured--; + mutex_unlock(&mbox_configured_lock); return ret; } static void omap_mbox_fini(struct omap_mbox *mbox) { - free_irq(mbox->irq, mbox); - tasklet_kill(&mbox->txq->tasklet); - flush_work(&mbox->rxq->work); - mbox_queue_free(mbox->txq); - mbox_queue_free(mbox->rxq); - if (mbox->ops->shutdown) { - mutex_lock(&mbox_configured_lock); - if (mbox_configured > 0) - mbox_configured--; - if (!mbox_configured) + mutex_lock(&mbox_configured_lock); + + if (!--mbox->use_count) { + tasklet_kill(&mbox->txq->tasklet); + flush_work(&mbox->rxq->work); + mbox_queue_free(mbox->txq); + mbox_queue_free(mbox->rxq); + } + + if (likely(mbox->ops->shutdown)) { + if (!--mbox_configured) { + free_irq(mbox->irq, mbox); mbox->ops->shutdown(mbox); - mutex_unlock(&mbox_configured_lock); + } } + + mutex_unlock(&mbox_configured_lock); } -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; @@ -336,13 +342,16 @@ struct omap_mbox *omap_mbox_get(const char *name) 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); @@ -366,6 +375,7 @@ int omap_mbox_register(struct device *parent, struct omap_mbox **list) ret = PTR_ERR(mbox->dev); goto err_out; } + BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier); } return 0;