[RFC PATCH 10/11] ppc/iommu: add routines to pseries iommu to map tces 1-1

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Nishanth Aravamudan
Date: Friday, October 8, 2010 - 10:33 am

Signed-off-by: Milton Miller <miltonm@bga.com>
Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
---
 arch/powerpc/platforms/pseries/iommu.c |   98 ++++++++++++++++++++++++++++++++
 1 files changed, 98 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index 8ec81df..451d2d1 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -270,6 +270,104 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum)
 	return tce_ret;
 }
 
+/* this is compatable with cells for the device tree property */
+struct dynamic_dma_window_prop {
+	__be32	liobn;		/* tce table number */
+	__be32	dma_base[2];	/* address hi,lo */
+	__be32	tce_shift;	/* ilog2(tce_page_size) */
+	__be32	window_shift;	/* ilog2(tce_window_size) */
+};
+
+static int tce_clearrange_multi_pSeriesLP(unsigned long start_pfn,
+					unsigned long num_pfn, void *arg)
+{
+	struct dynamic_dma_window_prop *maprange = arg;
+	int rc;
+	u64 tce_size, num_tce, dma_offset;
+	u32 tce_shift;
+
+	tce_shift = be32_to_cpu(maprange->tce_shift);
+	tce_size = 1ULL << tce_shift;
+	num_tce = num_pfn << PAGE_SHIFT;
+	dma_offset = start_pfn << PAGE_SHIFT;
+
+	/* round back to the beginning of the tce page size */
+	num_tce += dma_offset & (tce_size - 1);
+	dma_offset &= ~(tce_size - 1);
+
+	/* covert to number of tces */
+	num_tce |= tce_size - 1;
+	num_tce >>= tce_shift;
+
+	rc = plpar_tce_stuff(maprange->liobn, dma_offset, 0, num_tce);
+
+	return rc;
+}
+
+static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
+					unsigned long num_pfn, void *arg)
+{
+	struct dynamic_dma_window_prop *maprange = arg;
+	u64 *tcep, tce_size, num_tce, dma_offset, next, proto_tce;
+	u32 tce_shift;
+	long rc = 0;
+	long l, limit;
+
+	local_irq_disable();	/* to protect tcep and the page behind it */
+	tcep = __get_cpu_var(tce_page);
+
+	if (!tcep) {
+		tcep = (u64 *)__get_free_page(GFP_ATOMIC);
+		if (!tcep) {
+			local_irq_enable();
+			return -ENOMEM;
+		}
+		__get_cpu_var(tce_page) = tcep;
+	}
+
+	proto_tce = TCE_PCI_READ | TCE_PCI_WRITE;
+
+	tce_shift = be32_to_cpu(maprange->tce_shift);
+	tce_size = 1ULL << tce_shift;
+	next = start_pfn << PAGE_SHIFT;
+	num_tce = num_pfn << PAGE_SHIFT;
+
+	/* round back to the beginning of the tce page size */
+	num_tce += next & (tce_size - 1);
+	next &= ~(tce_size - 1);
+
+	/* covert to number of tces */
+	num_tce |= tce_size - 1;
+	num_tce >>= maprange->tce_shift;
+
+	/* We can map max one pageful of TCEs at a time */
+	do {
+		/*
+		 * Set up the page with TCE data, looping through and setting
+		 * the values.
+		 */
+		limit = min_t(long, num_tce, 4096/TCE_ENTRY_SIZE);
+		dma_offset = next;
+
+		for (l = 0; l < limit; l++) {
+			tcep[l] = proto_tce | dma_offset;
+			next += tce_size;
+		}
+
+		rc = plpar_tce_put_indirect((u64)maprange->liobn,
+					    (u64)dma_offset,
+					    (u64)virt_to_abs(tcep),
+					    limit);
+
+		num_tce -= limit;
+	} while (num_tce > 0 && !rc);
+
+	/* error cleanup: caller will clear whole range */
+
+	local_irq_enable();
+	return rc;
+}
+
 #ifdef CONFIG_PCI
 static void iommu_table_setparms(struct pci_controller *phb,
 				 struct device_node *dn,
-- 
1.7.1

--
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[RFC PATCH 00/11] ppc: enable dynamic dma window support, Nishanth Aravamudan, (Fri Oct 8, 10:33 am)
[RFC PATCH 01/11] macio: ensure all dma routines get copie ..., Nishanth Aravamudan, (Fri Oct 8, 10:33 am)
[RFC PATCH 02/11] ppc: allow direct and iommu to coexist, Nishanth Aravamudan, (Fri Oct 8, 10:33 am)
[RFC PATCH 03/11] ppc: Create ops to choose between direct ..., Nishanth Aravamudan, (Fri Oct 8, 10:33 am)
[RFC PATCH 04/11] ppc: add memory_hotplug_max, Nishanth Aravamudan, (Fri Oct 8, 10:33 am)
[RFC PATCH 05/11] ppc: do not search for dma-window proper ..., Nishanth Aravamudan, (Fri Oct 8, 10:33 am)
[RFC PATCH 06/11] ppc: checking for pdn-&gt;parent is redundant, Nishanth Aravamudan, (Fri Oct 8, 10:33 am)
[RFC PATCH 07/11] ppc/iommu: do not need to check for dma_ ..., Nishanth Aravamudan, (Fri Oct 8, 10:33 am)
[RFC PATCH 08/11] ppc/iommu: remove unneeded pci_dma_bus_s ..., Nishanth Aravamudan, (Fri Oct 8, 10:33 am)
[RFC PATCH 09/11] ppc/iommu: pass phb only to iommu_table_ ..., Nishanth Aravamudan, (Fri Oct 8, 10:33 am)
[RFC PATCH 10/11] ppc/iommu: add routines to pseries iommu ..., Nishanth Aravamudan, (Fri Oct 8, 10:33 am)
[RFC PATCH 11/11] ppc: add dynamic dma window support, Nishanth Aravamudan, (Fri Oct 8, 10:33 am)
Re: [RFC PATCH 02/11] ppc: allow direct and iommu to coexist, Benjamin Herrenschmidt, (Fri Oct 8, 4:38 pm)
Re: [RFC PATCH 03/11] ppc: Create ops to choose between di ..., Benjamin Herrenschmidt, (Fri Oct 8, 4:43 pm)
Re: [RFC PATCH 03/11] ppc: Create ops to choose between di ..., Benjamin Herrenschmidt, (Fri Oct 8, 4:44 pm)
Re: [RFC PATCH 03/11] ppc: Create ops to choose between di ..., Benjamin Herrenschmidt, (Sun Oct 10, 4:41 pm)