From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752907AbdF0QR5 (ORCPT ); Tue, 27 Jun 2017 12:17:57 -0400 Received: from Galois.linutronix.de ([146.0.238.70]:47195 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751695AbdF0QRf (ORCPT ); Tue, 27 Jun 2017 12:17:35 -0400 From: Sebastian Andrzej Siewior To: tglx@linutronix.de Cc: linux-kernel@vger.kernel.org, Sebastian Andrzej Siewior , David Woodhouse , Joerg Roedel , iommu@lists.linux-foundation.org, Andrew Morton Subject: [PATCH 3/3] iommu/vt-d: don't disable preemption while accessing deferred_flush() Date: Tue, 27 Jun 2017 18:16:48 +0200 Message-Id: <20170627161648.30302-3-bigeasy@linutronix.de> X-Mailer: git-send-email 2.13.1 In-Reply-To: <20170627161648.30302-1-bigeasy@linutronix.de> References: <20170627161648.30302-1-bigeasy@linutronix.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org get_cpu() disables preemption and returns the current CPU number. The CPU number is only used once while retrieving the address of the local's CPU deferred_flush pointer. We can instead use raw_cpu_ptr() while we remain preemptible. The worst thing that can happen is that flush_unmaps_timeout() is invoked multiple times: once by taskA after seeing HIGH_WATER_MARK and then preempted to another CPU and then by taskB which saw HIGH_WATER_MARK on the same CPU as taskA. It is also likely that ->size got from HIGH_WATER_MARK to 0 right after its read because another CPU invoked flush_unmaps_timeout() for this CPU. The access to flush_data is protected by a spinlock so even if we get migrated to another CPU or preempted - the data structure is protected. While at it, I marked deferred_flush static since I can't find a reference to it outside of this file. Cc: David Woodhouse Cc: Joerg Roedel Cc: iommu@lists.linux-foundation.org Cc: Andrew Morton Signed-off-by: Sebastian Andrzej Siewior --- drivers/iommu/intel-iommu.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 8500deda9175..1c7118d1525e 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -481,7 +481,7 @@ struct deferred_flush_data { struct deferred_flush_table *tables; }; =20 -DEFINE_PER_CPU(struct deferred_flush_data, deferred_flush); +static DEFINE_PER_CPU(struct deferred_flush_data, deferred_flush); =20 /* bitmap for indexing intel_iommus */ static int g_num_of_iommus; @@ -3725,10 +3725,8 @@ static void add_unmap(struct dmar_domain *dom, unsig= ned long iova_pfn, struct intel_iommu *iommu; struct deferred_flush_entry *entry; struct deferred_flush_data *flush_data; - unsigned int cpuid; =20 - cpuid =3D get_cpu(); - flush_data =3D per_cpu_ptr(&deferred_flush, cpuid); + flush_data =3D raw_cpu_ptr(&deferred_flush); =20 /* Flush all CPUs' entries to avoid deferring too much. If * this becomes a bottleneck, can just flush us, and rely on @@ -3761,8 +3759,6 @@ static void add_unmap(struct dmar_domain *dom, unsign= ed long iova_pfn, } flush_data->size++; spin_unlock_irqrestore(&flush_data->lock, flags); - - put_cpu(); } =20 static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t si= ze) --=20 2.13.1