+ sparc64-add-the-segment-boundary-checking-to-iommus-while-merging-sg-entries.patch added to -mm tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The patch titled
     sparc64: add the segment boundary checking to IOMMUs while merging SG entries
has been added to the -mm tree.  Its filename is
     sparc64-add-the-segment-boundary-checking-to-iommus-while-merging-sg-entries.patch

Before you just go and hit "reply", please:
   a) Consider who else should be cc'ed
   b) Prefer to cc a suitable mailing list as well
   c) Ideally: find the original patch on the mailing list and do a
      reply-to-all to that, adding suitable additional cc's

*** Remember to use Documentation/SubmitChecklist when testing your code ***

See http://www.zip.com.au/~akpm/linux/patches/stuff/added-to-mm.txt to find
out what to do about this

The current -mm tree may be found at http://userweb.kernel.org/~akpm/mmotm/

------------------------------------------------------
Subject: sparc64: add the segment boundary checking to IOMMUs while merging SG entries
From: FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx>

Some IOMMUs allocate memory areas spanning LLD's segment boundary limit.  It
forces low level drivers to have a workaround to adjust scatter lists that the
IOMMU builds.  We are in the process of making all the IOMMUs respect the
segment boundary limits to remove such work around in LLDs.

SPARC64 IOMMUs were rewritten to use the IOMMU helper functions and the commit
89c94f2f70d093f59b55d3ea8042d13889169346 made the IOMMUs not allocate memory
areas spanning the segment boundary limit.

However, SPARC64 IOMMUs allocate memory areas first then try to merge them
(while some IOMMUs walk through all the sg entries to see how they can be
merged first and allocate memory areas).  So SPARC64 IOMMUs also need the
boundary limit checking when they try to merge sg entries.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx>
Cc: David Miller <davem@xxxxxxxxxxxxx>
Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>
---

 arch/sparc64/kernel/iommu.c        |   12 ++++++++++--
 arch/sparc64/kernel/iommu_common.h |   13 +++++++++++++
 arch/sparc64/kernel/pci_sun4v.c    |   12 ++++++++++--
 3 files changed, 33 insertions(+), 4 deletions(-)

diff -puN arch/sparc64/kernel/iommu.c~sparc64-add-the-segment-boundary-checking-to-iommus-while-merging-sg-entries arch/sparc64/kernel/iommu.c
--- a/arch/sparc64/kernel/iommu.c~sparc64-add-the-segment-boundary-checking-to-iommus-while-merging-sg-entries
+++ a/arch/sparc64/kernel/iommu.c
@@ -516,9 +516,11 @@ static int dma_4u_map_sg(struct device *
 	unsigned long flags, handle, prot, ctx;
 	dma_addr_t dma_next = 0, dma_addr;
 	unsigned int max_seg_size;
+	unsigned long seg_boundary_size;
 	int outcount, incount, i;
 	struct strbuf *strbuf;
 	struct iommu *iommu;
+	unsigned long base_shift;
 
 	BUG_ON(direction == DMA_NONE);
 
@@ -549,8 +551,11 @@ static int dma_4u_map_sg(struct device *
 	outs->dma_length = 0;
 
 	max_seg_size = dma_get_max_seg_size(dev);
+	seg_boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+				  IO_PAGE_SIZE) >> IO_PAGE_SHIFT;
+	base_shift = iommu->page_table_map_base >> IO_PAGE_SHIFT;
 	for_each_sg(sglist, s, nelems, i) {
-		unsigned long paddr, npages, entry, slen;
+		unsigned long paddr, npages, entry, out_entry = 0, slen;
 		iopte_t *base;
 
 		slen = s->length;
@@ -593,7 +598,9 @@ static int dma_4u_map_sg(struct device *
 			 * - allocated dma_addr isn't contiguous to previous allocation
 			 */
 			if ((dma_addr != dma_next) ||
-			    (outs->dma_length + s->length > max_seg_size)) {
+			    (outs->dma_length + s->length > max_seg_size) ||
+			    (is_span_boundary(out_entry, base_shift,
+					      seg_boundary_size, outs, s))) {
 				/* Can't merge: create a new segment */
 				segstart = s;
 				outcount++;
@@ -607,6 +614,7 @@ static int dma_4u_map_sg(struct device *
 			/* This is a new segment, fill entries */
 			outs->dma_address = dma_addr;
 			outs->dma_length = slen;
+			out_entry = entry;
 		}
 
 		/* Calculate next page pointer for contiguous check */
diff -puN arch/sparc64/kernel/iommu_common.h~sparc64-add-the-segment-boundary-checking-to-iommus-while-merging-sg-entries arch/sparc64/kernel/iommu_common.h
--- a/arch/sparc64/kernel/iommu_common.h~sparc64-add-the-segment-boundary-checking-to-iommus-while-merging-sg-entries
+++ a/arch/sparc64/kernel/iommu_common.h
@@ -12,6 +12,7 @@
 #include <linux/mm.h>
 #include <linux/scatterlist.h>
 #include <linux/device.h>
+#include <linux/iommu-helper.h>
 
 #include <asm/iommu.h>
 #include <asm/scatterlist.h>
@@ -58,6 +59,18 @@ static inline unsigned long calc_npages(
 	return npages;
 }
 
+static inline int is_span_boundary(unsigned long entry,
+				   unsigned long shift,
+				   unsigned long boundary_size,
+				   struct scatterlist *outs,
+				   struct scatterlist *sg)
+{
+	unsigned long paddr = SG_ENT_PHYS_ADDRESS(outs);
+	int nr = iommu_num_pages(paddr, outs->dma_length + sg->length);
+
+	return iommu_is_span_boundary(entry, nr, shift, boundary_size);
+}
+
 extern unsigned long iommu_range_alloc(struct device *dev,
 				       struct iommu *iommu,
 				       unsigned long npages,
diff -puN arch/sparc64/kernel/pci_sun4v.c~sparc64-add-the-segment-boundary-checking-to-iommus-while-merging-sg-entries arch/sparc64/kernel/pci_sun4v.c
--- a/arch/sparc64/kernel/pci_sun4v.c~sparc64-add-the-segment-boundary-checking-to-iommus-while-merging-sg-entries
+++ a/arch/sparc64/kernel/pci_sun4v.c
@@ -335,8 +335,10 @@ static int dma_4v_map_sg(struct device *
 	unsigned long flags, handle, prot;
 	dma_addr_t dma_next = 0, dma_addr;
 	unsigned int max_seg_size;
+	unsigned long seg_boundary_size;
 	int outcount, incount, i;
 	struct iommu *iommu;
+	unsigned long base_shift;
 	long err;
 
 	BUG_ON(direction == DMA_NONE);
@@ -362,8 +364,11 @@ static int dma_4v_map_sg(struct device *
 	iommu_batch_start(dev, prot, ~0UL);
 
 	max_seg_size = dma_get_max_seg_size(dev);
+	seg_boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+				  IO_PAGE_SIZE) >> IO_PAGE_SHIFT;
+	base_shift = iommu->page_table_map_base >> IO_PAGE_SHIFT;
 	for_each_sg(sglist, s, nelems, i) {
-		unsigned long paddr, npages, entry, slen;
+		unsigned long paddr, npages, entry, out_entry = 0, slen;
 
 		slen = s->length;
 		/* Sanity check */
@@ -406,7 +411,9 @@ static int dma_4v_map_sg(struct device *
 			 * - allocated dma_addr isn't contiguous to previous allocation
 			 */
 			if ((dma_addr != dma_next) ||
-			    (outs->dma_length + s->length > max_seg_size)) {
+			    (outs->dma_length + s->length > max_seg_size) ||
+			    (is_span_boundary(out_entry, base_shift,
+					      seg_boundary_size, outs, s))) {
 				/* Can't merge: create a new segment */
 				segstart = s;
 				outcount++;
@@ -420,6 +427,7 @@ static int dma_4v_map_sg(struct device *
 			/* This is a new segment, fill entries */
 			outs->dma_address = dma_addr;
 			outs->dma_length = slen;
+			out_entry = entry;
 		}
 
 		/* Calculate next page pointer for contiguous check */
_

Patches currently in -mm which might be from fujita.tomonori@xxxxxxxxxxxxx are

alpha-use-iommu_is_span_boundary-helper-function.patch
lib-swiotlbc-avoid-endless-loops.patch
lib-swiotlbc-avoid-endless-loops-fix.patch
ia64-make-iommu-respect-the-segment-boundary-limits.patch
git-scsi-misc.patch
ipsc-fix-build-warning.patch
drivers-scsi-initioc-suppress-compile-warning.patch
drivers-scsi-hptiopc-fix-build-warning.patch
sparc64-add-the-segment-boundary-checking-to-iommus-while-merging-sg-entries.patch
sparc64-remove-unused-calc_npages-in-iommu_commonh.patch
lib-swiotlbc-cleanups.patch

--
To unsubscribe from this list: send the line "unsubscribe mm-commits" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Kernel Newbies FAQ]     [Kernel Archive]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Photo]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]

  Powered by Linux