From patchwork Mon Feb 27 19:54:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Philippe Brucker X-Patchwork-Id: 9594021 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 A465260453 for ; Mon, 27 Feb 2017 20:24:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 95A2E281F9 for ; Mon, 27 Feb 2017 20:24:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 88D9C283D4; Mon, 27 Feb 2017 20:24:57 +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=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2DD0C281F9 for ; Mon, 27 Feb 2017 20:24:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751842AbdB0UYy (ORCPT ); Mon, 27 Feb 2017 15:24:54 -0500 Received: from foss.arm.com ([217.140.101.70]:58784 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751735AbdB0UYp (ORCPT ); Mon, 27 Feb 2017 15:24:45 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 63F6C174E; Mon, 27 Feb 2017 11:59:19 -0800 (PST) Received: from e106794-lin.cambridge.arm.com (e106794-lin.cambridge.arm.com [10.1.210.60]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id B6BAF3F3E1; Mon, 27 Feb 2017 11:59:16 -0800 (PST) From: Jean-Philippe Brucker Cc: Harv Abdulhamid , Will Deacon , Shanker Donthineni , Bjorn Helgaas , Sinan Kaya , Lorenzo Pieralisi , Catalin Marinas , Robin Murphy , Joerg Roedel , Nate Watterson , Alex Williamson , David Woodhouse , linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org, iommu@lists.linux-foundation.org, kvm@vger.kernel.org Subject: [RFC PATCH 26/30] iommu/arm-smmu-v3: Fix PRI queue overflow acknowledgement Date: Mon, 27 Feb 2017 19:54:37 +0000 Message-Id: <20170227195441.5170-27-jean-philippe.brucker@arm.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170227195441.5170-1-jean-philippe.brucker@arm.com> References: <20170227195441.5170-1-jean-philippe.brucker@arm.com> To: unlisted-recipients:; (no To-header on input) Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When an overflow occurs in the PRI queue, the SMMU toggles the overflow flag in the PROD register. To exit the overflow condition, the PRI thread is supposed to acknowledge it by toggling this flag in the CONS register. Currently with an overflow condition, the flag is toggled in q->cons after clearing the PRI queue, but is never published to the hardware. It would be done next time we execute the thread. However, we never get a chance because the SMMU doesn't append anything to the queue while in overflow condition, and the thread is not scheduled unless the queue transitions from empty to non-empty. To fix it, synchronize the hardware CONS register before leaving the PRIQ thread. This bug doesn't affect the event queue, since the SMMU still adds elements to that queue when the overflow condition is active. Even missing an overflow condition because one is already active doesn't matter. We won't miss fault records for stalled transactions. But it feels nicer to keep the SMMU in sync when possible, so do it there as well. Signed-off-by: Jean-Philippe Brucker --- drivers/iommu/arm-smmu-v3.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 2f1ec09aeaec..b5d45c1e14d1 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -932,6 +932,16 @@ static void queue_inc_cons(struct arm_smmu_queue *q) writel(q->cons, q->cons_reg); } +static void queue_sync_cons_ovf(struct arm_smmu_queue *q) +{ + /* Acknowledge overflow condition if any */ + if (Q_OVF(q, q->prod) == Q_OVF(q, q->cons)) + return; + + q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons); + writel(q->cons, q->cons_reg); +} + static int queue_sync_prod(struct arm_smmu_queue *q) { int ret = 0; @@ -1782,7 +1792,7 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev) } while (!queue_empty(q)); /* Sync our overflow flag, as we believe we're up to speed */ - q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons); + queue_sync_cons_ovf(q); return IRQ_HANDLED; } @@ -1846,7 +1856,7 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev) } while (!queue_empty(q)); /* Sync our overflow flag, as we believe we're up to speed */ - q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons); + queue_sync_cons_ovf(q); smmu->priq.batch++; wake_up_locked(&smmu->priq.wq);