Skip to contentSkip to conversation

PATCH] dma_get_required_mask()

PATCH James Bottomley 2 participants 4 messages Jun 28, 2004

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

This patch implements dma_get_required_mask() which may be used by drivers to probe the optimal DMA descriptor type they should be implementing on the platform.

I've also tested it this time with the sym_2 driver...making it chose the correct descriptors for the platform. (although I don't have a 64 bit platform with >4GB memory, so I only confirmed it selects the 32 bit descriptors all the time...)

It should be ready for inclusion.

James

===== Documentation/DMA-API.txt 1.7 vs edited =====

Documentation/DMA-API.txt +14 -0
@@ -162,6 +162,20 @@
 
 Returns: 1 if successful and 0 if not
 
+u64
+dma_get_required_mask(struct device *dev)
+
+After setting the mask with dma_set_mask(), this API returns the
+actual mask (within that already set) that the platform actually
+requires to operate efficiently.  Usually this means the returned mask
+is the minimum required to cover all of memory.  Examining the
+required mask gives drivers with variable descriptor sizes the
+opportunity to use smaller descriptors as necessary.
+
+Requesting the required mask does not alter the current mask.  If you
+wish to take advantage of it, you should issue another dma_set_mask()
+call to lower the mask again.
+
 
 Part Id - Streaming DMA mappings
 --------------------------------

===== include/linux/dma-mapping.h 1.3 vs edited =====

include/linux/dma-mapping.h +23 -0
@@ -19,6 +19,29 @@
 #define dma_sync_single		dma_sync_single_for_cpu
 #define dma_sync_sg		dma_sync_sg_for_cpu
 
+#ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK
+static inline u64 dma_get_required_mask(struct device *dev)
+{
+	extern unsigned long max_pfn; /* defined in bootmem.h but may
+					 not be included */
+	u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT);
+	u32 high_totalram = ((max_pfn - 1) >> (32 - PAGE_SHIFT));
+	u64 mask;
+
+	if (!high_totalram) {
+		/* convert to mask just covering totalram */
+		low_totalram = (1 << (fls(low_totalram) - 1));
+		low_totalram += low_totalram - 1;
+		mask = low_totalram;
+	} else {
+		high_totalram = (1 << (fls(high_totalram) - 1));
+		high_totalram += high_totalram - 1;
+		mask = (((u64)high_totalram) << 32) + 0xffffffff;
+	}
+	return mask & *dev->dma_mask;
+}
+#endif
+		
 #endif
 
 

===== mm/bootmem.c 1.26 vs edited =====

mm/bootmem.c +5 -0
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/mmzone.h>
+#include <linux/module.h>
 #include <asm/dma.h>
 #include <asm/io.h>
 
@@ -26,6 +27,10 @@
 unsigned long max_low_pfn;
 unsigned long min_low_pfn;
 unsigned long max_pfn;
+
+EXPORT_SYMBOL(max_pfn);		/* This is exported so
+				 * dma_get_required_mask(), which uses
+				 * it, can be an inline function */
 
 /* return the number of _pages_ that will be allocated for the boot bitmap */
 unsigned long __init bootmem_bootmap_pages (unsigned long pages)
#1 lore raw
Quoted 3 lines · On 28 Jun 2004 16:10:43 -0500 James Bottomley <[email protected]>…

This patch implements dma_get_required_mask() which may be used by drivers to probe the optimal DMA descriptor type they should be implementing on the platform.

Maybe you should tweak the default implementation such that something reasonable happens on 64-bit platforms that define dma_addr_t as a 32-bit quantity. :-)

Of course, you've provided ARCH_HAS_DMA_GET_REQUIRED_MASK in order to deal with these cases, so it's not mandatory.

#2 lore raw
Quoted 3 lines · David S. Miller

Maybe you should tweak the default implementation such that something reasonable happens on 64-bit platforms that define dma_addr_t as a 32-bit quantity. :-)

Actually, the default implementation should work on these platforms too. Since it's impossible to set a mask over 32 bits, then the best dma_get_required_mask() will do is return a full spread of 32 bits, since the memory mask is anded with the current dma mask.

James

#3 lore raw
Quoted 9 lines · On 28 Jun 2004 17:40:06 -0500 James Bottomley <[email protected]>…
Quoted 3 lines · David S. Miller

Maybe you should tweak the default implementation such that something reasonable happens on 64-bit platforms that define dma_addr_t as a 32-bit quantity. :-)

Actually, the default implementation should work on these platforms too. Since it's impossible to set a mask over 32 bits, then the best dma_get_required_mask() will do is return a full spread of 32 bits, since the memory mask is anded with the current dma mask.

Perfect, I didn't notice that.