From patchwork Wed Oct 12 13:22:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Auger X-Patchwork-Id: 9373003 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 0D50D60772 for ; Wed, 12 Oct 2016 13:25:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F107728B6F for ; Wed, 12 Oct 2016 13:25:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E56A6295CF; Wed, 12 Oct 2016 13:25:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 67B7128B6F for ; Wed, 12 Oct 2016 13:25:49 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1buJW8-0006P7-V6; Wed, 12 Oct 2016 13:24:20 +0000 Received: from mx1.redhat.com ([209.132.183.28]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1buJUz-0005ot-GM for linux-arm-kernel@lists.infradead.org; Wed, 12 Oct 2016 13:23:11 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BAF567EA8A; Wed, 12 Oct 2016 13:22:51 +0000 (UTC) Received: from localhost.redhat.com (vpn1-6-235.ams2.redhat.com [10.36.6.235]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u9CDMQCi010906; Wed, 12 Oct 2016 09:22:47 -0400 From: Eric Auger To: eric.auger@redhat.com, eric.auger.pro@gmail.com, christoffer.dall@linaro.org, marc.zyngier@arm.com, robin.murphy@arm.com, alex.williamson@redhat.com, will.deacon@arm.com, joro@8bytes.org, tglx@linutronix.de, jason@lakedaemon.net, linux-arm-kernel@lists.infradead.org Subject: [PATCH v14 04/16] iommu/dma: MSI doorbell alloc/free Date: Wed, 12 Oct 2016 13:22:12 +0000 Message-Id: <1476278544-3397-5-git-send-email-eric.auger@redhat.com> In-Reply-To: <1476278544-3397-1-git-send-email-eric.auger@redhat.com> References: <1476278544-3397-1-git-send-email-eric.auger@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Wed, 12 Oct 2016 13:22:51 +0000 (UTC) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20161012_062309_667539_D46CB432 X-CRM114-Status: GOOD ( 14.31 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: drjones@redhat.com, kvm@vger.kernel.org, Jean-Philippe.Brucker@arm.com, Manish.Jaggi@caviumnetworks.com, p.fedin@samsung.com, linux-kernel@vger.kernel.org, Bharat.Bhushan@freescale.com, iommu@lists.linux-foundation.org, pranav.sawargaonkar@gmail.com, yehuday@marvell.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP We introduce the capability to (un)register MSI doorbells. A doorbell region is characterized by its physical address base, size, and whether it its safe (ie. it implements IRQ remapping). A doorbell can be per-cpu or global. We currently only care about global doorbells. A function returns whether all registered doorbells are safe. MSI controllers likely to work along with IOMMU that translate MSI transaction must register their doorbells to allow device assignment with MSI support. Otherwise the MSI transactions will cause IOMMU faults. Signed-off-by: Eric Auger --- v13 -> v14: - previously in msi-doorbell.h/c --- drivers/iommu/dma-iommu.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/dma-iommu.h | 41 ++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index d45f9a0..d8a7d86 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -43,6 +43,38 @@ struct iommu_dma_cookie { spinlock_t msi_lock; }; +/** + * struct iommu_msi_doorbell_info - MSI doorbell region descriptor + * @percpu_doorbells: per cpu doorbell base address + * @global_doorbell: base address of the doorbell + * @doorbell_is_percpu: is the doorbell per cpu or global? + * @safe: true if irq remapping is implemented + * @size: size of the doorbell + */ +struct iommu_msi_doorbell_info { + union { + phys_addr_t __percpu *percpu_doorbells; + phys_addr_t global_doorbell; + }; + bool doorbell_is_percpu; + bool safe; + size_t size; +}; + +struct iommu_msi_doorbell { + struct iommu_msi_doorbell_info info; + struct list_head next; +}; + +/* list of registered MSI doorbells */ +static LIST_HEAD(iommu_msi_doorbell_list); + +/* counts the number of unsafe registered doorbells */ +static uint nb_unsafe_doorbells; + +/* protects the list and nb_unsafe_doorbells */ +static DEFINE_MUTEX(iommu_msi_doorbell_mutex); + static inline struct iova_domain *cookie_iovad(struct iommu_domain *domain) { return &((struct iommu_dma_cookie *)domain->iova_cookie)->iovad; @@ -755,3 +787,46 @@ int iommu_get_dma_msi_region_cookie(struct iommu_domain *domain, return 0; } EXPORT_SYMBOL(iommu_get_dma_msi_region_cookie); + +struct iommu_msi_doorbell_info * +iommu_msi_doorbell_alloc(phys_addr_t base, size_t size, bool safe) +{ + struct iommu_msi_doorbell *db; + + db = kzalloc(sizeof(*db), GFP_KERNEL); + if (!db) + return ERR_PTR(-ENOMEM); + + db->info.global_doorbell = base; + db->info.size = size; + db->info.safe = safe; + + mutex_lock(&iommu_msi_doorbell_mutex); + list_add(&db->next, &iommu_msi_doorbell_list); + if (!db->info.safe) + nb_unsafe_doorbells++; + mutex_unlock(&iommu_msi_doorbell_mutex); + return &db->info; +} +EXPORT_SYMBOL_GPL(iommu_msi_doorbell_alloc); + +void iommu_msi_doorbell_free(struct iommu_msi_doorbell_info *dbinfo) +{ + struct iommu_msi_doorbell *db; + + db = container_of(dbinfo, struct iommu_msi_doorbell, info); + + mutex_lock(&iommu_msi_doorbell_mutex); + list_del(&db->next); + if (!db->info.safe) + nb_unsafe_doorbells--; + mutex_unlock(&iommu_msi_doorbell_mutex); + kfree(db); +} +EXPORT_SYMBOL_GPL(iommu_msi_doorbell_free); + +bool iommu_msi_doorbell_safe(void) +{ + return !nb_unsafe_doorbells; +} +EXPORT_SYMBOL_GPL(iommu_msi_doorbell_safe); diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h index 05ab5b4..9640a27 100644 --- a/include/linux/dma-iommu.h +++ b/include/linux/dma-iommu.h @@ -19,6 +19,8 @@ #ifdef __KERNEL__ #include +struct iommu_msi_doorbell_info; + #ifdef CONFIG_IOMMU_DMA #include #include @@ -70,6 +72,31 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg); int iommu_get_dma_msi_region_cookie(struct iommu_domain *domain, dma_addr_t base, u64 size); +/** + * iommu_msi_doorbell_alloc - allocate a global doorbell + * @base: physical base address of the doorbell + * @size: size of the doorbell + * @safe: true is irq_remapping implemented for this doorbell + * + * Return: the newly allocated doorbell info or a pointer converted error + */ +struct iommu_msi_doorbell_info * +iommu_msi_doorbell_alloc(phys_addr_t base, size_t size, bool safe); + +/** + * iommu_msi_doorbell_free - free a global doorbell + * @db: doorbell info to free + */ +void iommu_msi_doorbell_free(struct iommu_msi_doorbell_info *db); + +/** + * iommu_msi_doorbell_safe - return whether all registered doorbells are safe + * + * Safe doorbells are those which implement irq remapping + * Return: true if all doorbells are safe, false otherwise + */ +bool iommu_msi_doorbell_safe(void); + #else struct iommu_domain; @@ -99,6 +126,20 @@ static inline int iommu_get_dma_msi_region_cookie(struct iommu_domain *domain, return -ENODEV; } +static inline struct iommu_msi_doorbell_info * +iommu_msi_doorbell_alloc(phys_addr_t base, size_t size, bool safe) +{ + return NULL; +} + +static inline void +iommu_msi_doorbell_free(struct msi_doorbell_info *db) {} + +static inline bool iommu_msi_doorbell_safe(void) +{ + return false; +} + #endif /* CONFIG_IOMMU_DMA */ #endif /* __KERNEL__ */ #endif /* __DMA_IOMMU_H */