Thread (15 messages) 15 messages, 4 authors, 2013-12-03

RE: [PATCH 2/3 v2] iommu/fsl: Enable default DMA window for PCIe devices

From: Bhushan Bharat-R65777 <hidden>
Date: 2013-10-16 16:50:11
Also in: linux-iommu, lkml

-----Original Message-----
From: Sethi Varun-B16395
Sent: Wednesday, October 16, 2013 4:53 PM
To: joro@8bytes.org; iommu@lists.linux-foundation.org; linuxppc-
dev@lists.ozlabs.org; linux-kernel@vger.kernel.org; Yoder Stuart-B08248; =
Wood
Scott-B07421; alex.williamson@redhat.com; Bhushan Bharat-R65777
Cc: Sethi Varun-B16395
Subject: [PATCH 2/3 v2] iommu/fsl: Enable default DMA window for PCIe dev=
ices
=20
Once the PCIe device assigned to a guest VM (via VFIO) gets detached from=
 the
iommu domain (when guest terminates), its PAMU table entry is disabled. S=
o, this
would prevent the device from being used once it's assigned back to the h=
ost.
=20
This patch allows for creation of a default DMA window corresponding to t=
he
device and subsequently enabling the PAMU table entry. Before we enable t=
he
entry, we ensure that the device's bus master capability is disabled (dev=
ice
quiesced).
=20
Signed-off-by: Varun Sethi <redacted>
---
 drivers/iommu/fsl_pamu.c        |   43 ++++++++++++++++++++++++++++-----=
---
 drivers/iommu/fsl_pamu.h        |    1 +
 drivers/iommu/fsl_pamu_domain.c |   46 +++++++++++++++++++++++++++++++++=
+++---
quoted hunk ↗ jump to hunk
 3 files changed, 78 insertions(+), 12 deletions(-)
=20
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c index
cba0498..fb4a031 100644
--- a/drivers/iommu/fsl_pamu.c
+++ b/drivers/iommu/fsl_pamu.c
@@ -225,6 +225,21 @@ static struct paace *pamu_get_spaace(struct paace *p=
aace,
u32 wnum)
 	return spaace;
 }
=20
+/*
+ * Defaul PPAACE settings for an LIODN.
+ */
+static void setup_default_ppaace(struct paace *ppaace) {
+	pamu_init_ppaace(ppaace);
+	/* window size is 2^(WSE+1) bytes */
+	set_bf(ppaace->addr_bitfields, PPAACE_AF_WSE, 35);
+	ppaace->wbah =3D 0;
+	set_bf(ppaace->addr_bitfields, PPAACE_AF_WBAL, 0);
+	set_bf(ppaace->impl_attr, PAACE_IA_ATM,
+		PAACE_ATM_NO_XLATE);
+	set_bf(ppaace->addr_bitfields, PAACE_AF_AP,
+		PAACE_AP_PERMS_ALL);
+}
 /**
  * pamu_get_fspi_and_allocate() - Allocates fspi index and reserves subw=
indows
  *                                required for primary PAACE in the seco=
ndary
quoted hunk ↗ jump to hunk
@@ -253,6 +268,24 @@ static unsigned long pamu_get_fspi_and_allocate(u32
subwin_cnt)
 	return (spaace_addr - (unsigned long)spaact) / (sizeof(struct paace)); =
 }
=20
+/* Reset the PAACE entry to the default state */ void
+enable_default_dma_window(int liodn) {
+	struct paace *ppaace;
+
+	ppaace =3D pamu_get_ppaace(liodn);
+	if (!ppaace) {
+		pr_debug("Invalid liodn entry\n");
+		return;
+	}
+
+	memset(ppaace, 0, sizeof(struct paace));
+
+	setup_default_ppaace(ppaace);
+	mb();
+	pamu_enable_liodn(liodn);
+}
+
 /* Release the subwindows reserved for a particular LIODN */  void
pamu_free_subwins(int liodn)  { @@ -752,15 +785,7 @@ static void __init
setup_liodns(void)
 				continue;
 			}
 			ppaace =3D pamu_get_ppaace(liodn);
-			pamu_init_ppaace(ppaace);
-			/* window size is 2^(WSE+1) bytes */
-			set_bf(ppaace->addr_bitfields, PPAACE_AF_WSE, 35);
-			ppaace->wbah =3D 0;
-			set_bf(ppaace->addr_bitfields, PPAACE_AF_WBAL, 0);
-			set_bf(ppaace->impl_attr, PAACE_IA_ATM,
-				PAACE_ATM_NO_XLATE);
-			set_bf(ppaace->addr_bitfields, PAACE_AF_AP,
-				PAACE_AP_PERMS_ALL);
+			setup_default_ppaace(ppaace);
 			if (of_device_is_compatible(node, "fsl,qman-portal"))
 				setup_qbman_paace(ppaace, QMAN_PORTAL_PAACE);
 			if (of_device_is_compatible(node, "fsl,qman")) diff --git
a/drivers/iommu/fsl_pamu.h b/drivers/iommu/fsl_pamu.h index 8fc1a12..0edc=
bbbb
quoted hunk ↗ jump to hunk
100644
--- a/drivers/iommu/fsl_pamu.h
+++ b/drivers/iommu/fsl_pamu.h
@@ -406,5 +406,6 @@ void get_ome_index(u32 *omi_index, struct device *dev=
);  int
quoted hunk ↗ jump to hunk
pamu_update_paace_stash(int liodn, u32 subwin, u32 value);  int
pamu_disable_spaace(int liodn, u32 subwin);
 u32 pamu_get_max_subwin_cnt(void);
+void enable_default_dma_window(int liodn);
=20
 #endif  /* __FSL_PAMU_H */
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_dom=
ain.c
quoted hunk ↗ jump to hunk
index 966ae70..dd6cafc 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -340,17 +340,57 @@ static inline struct device_domain_info
*find_domain(struct device *dev)
 	return dev->archdata.iommu_domain;
 }
=20
+/* Disable device DMA capability and enable default DMA window */
+static void disable_device_dma(struct device_domain_info *info,
+				int enable_dma_window)
+{
+#ifdef CONFIG_PCI
+	if (info->dev->bus =3D=3D &pci_bus_type) {
+		struct pci_dev *pdev =3D NULL;
+		pdev =3D to_pci_dev(info->dev);
+		if (pci_is_enabled(pdev))
+			pci_disable_device(pdev);
+	}
+#endif
+
+	if (enable_dma_window)
+		enable_default_dma_window(info->liodn);
+}
+
+static int check_for_shared_liodn(struct device_domain_info *info) {
+	struct device_domain_info *tmp;
+
+	/*
+	 * Sanity check, to ensure that this is not a
+	 * shared LIODN. In case of a PCIe controller
+	 * it's possible that all PCIe devices share
+	 * the same LIODN.
+	 */
+	list_for_each_entry(tmp, &info->domain->devices, link) {
+		if (info->liodn =3D=3D tmp->liodn)
+			return 1;
+	}
+
+	return 0;
+}
+
 static void remove_device_ref(struct device_domain_info *info, u32 win_c=
nt)  {
 	unsigned long flags;
+	int enable_dma_window =3D 0;
=20
 	list_del(&info->link);
 	spin_lock_irqsave(&iommu_lock, flags);
-	if (win_cnt > 1)
-		pamu_free_subwins(info->liodn);
-	pamu_disable_liodn(info->liodn);
+	if (!check_for_shared_liodn(info)) {
One query; Do we really need to check for this?

Otherwise this patch series looks good to me.

Thanks
-Bharat
+		if (win_cnt > 1)
+			pamu_free_subwins(info->liodn);
+		pamu_disable_liodn(info->liodn);
+		enable_dma_window =3D 1;
+	}
 	spin_unlock_irqrestore(&iommu_lock, flags);
 	spin_lock_irqsave(&device_domain_lock, flags);
+	disable_device_dma(info, enable_dma_window);
 	info->dev->archdata.iommu_domain =3D NULL;
 	kmem_cache_free(iommu_devinfo_cache, info);
 	spin_unlock_irqrestore(&device_domain_lock, flags);
--
1.7.9.5
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help