This is all done to work around a bug in the kernel dealing with
ZONE_DMA. I applaud the fix, but so many drivers need to be rewritten to
first try taking memory from the general pool, then dropping back to the
DMA pool if not matching the dma_mask.

Sincerely -- Mark Salyzyn

-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Matt Domsch
Sent: Friday, March 18, 2005 2:19 PM
To: linux-scsi@vger.kernel.org
Subject: [PATCH 2.4.30-pre3] scsi_mod: add max_dma_memory and
use_zone_normal params

For review and comment.
Patch adds two new module parameters to scsi_mod:

max_dma_memory=, maximum DMA pool size, in MB (default=32 -> 32MB)
makes the hard-coded limit for the DMA pool size be adjustable.  This

Signed-off-by: Matt Domsch <[EMAIL PROTECTED]>
is necessary for systems with large numbers of disks seen (i.e. ~112
LUNs on a SAN as seen by a FC controller), where the size of the
scsi_malloc() pool would consume all of ZONE_DMA, leaving none for
other users.  This lets a system admin set a limit on how much memory
to use for the scsi_malloc() pool.  If set too low, fewer outstanding
commands can be issued at once, so it's only a performance issue.

use_zone_normal=, 1 if scsi_malloc() can safely use ZONE_NORMAL
instead of ZONE_DMA By default, scsi_malloc() uses ZONE_DMA memory.
On x86 and x86_64, ZONE_DMA is only 16MB, though if you've got a lot
of disks, it could try to consume all of that.  This lets
scsi_malloc() use ZONE_NORMAL instead of ZONE_DMA, which of course is
only safe if all your SCSI controllers are 64-bit-address-capable
(most high-end cards today are).  This flag lets you have lots more
memory available to scsi_malloc() than would be available if it were
forced to use only ZONE_DMA, and frees up the space it would otherwise
have consumed from ZONE_DMA for other users.

Tested lightly on x86_64 on EM64T systems with 8GB RAM and up to 112
LUNs visible (14x8 paths, 28x4 paths, ...)

Thanks,
Matt


-- 
Matt Domsch
Software Architect
Dell Linux Solutions linux.dell.com & www.dell.com/linux
Linux on Dell mailing lists @ http://lists.us.dell.com

===== drivers/scsi/scsi_dma.c 1.2 vs edited =====
--- 1.2/drivers/scsi/scsi_dma.c 2002-02-05 08:10:27 -06:00
+++ edited/drivers/scsi/scsi_dma.c      2005-03-18 11:31:11 -06:00
@@ -46,6 +46,29 @@ unsigned int scsi_dma_free_sectors = 0;
 unsigned int scsi_need_isa_buffer = 0;
 static unsigned char **dma_malloc_pages = NULL;
 
+static unsigned int max_dma_memory = 32; /* 32MB */
+MODULE_PARM(max_dma_memory, "l");
+MODULE_PARM_DESC(max_dma_memory, "maximum DMA pool size, in MB
(default=32 -> 32MB)");
+
+
+/* This flag is unsafe under these conditions:
+ * - you've got a <64-bit addressable SCSI controller, >4GB RAM, and an
architecture where ZONE_NORMAL
+ *   extends above 4GB (any 64-bit architecture)
+ * or
+ * - you've got an old ISA card with host->unchecked_isa_dma=1
+ *
+ * This implies that it is really safe only with 64-bit addressable
SCSI controllers
+ */
+static unsigned int use_zone_normal;
+MODULE_PARM(use_zone_normal, "i");
+MODULE_PARM_DESC(use_zone_normal, "1 if scsi_malloc() can safely use
ZONE_NORMAL instead of ZONE_DMA");
+
+static inline unsigned int dma_gfp_flags()
+{
+       return use_zone_normal ? GFP_ATOMIC : GFP_ATOMIC | GFP_DMA;
+}
+
+
 /*
  * Function:    scsi_malloc
  *
@@ -287,7 +310,7 @@ void scsi_resize_dma_pool(void)
 #endif
 
        /* limit DMA memory to 32MB: */
-       new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
+       new_dma_sectors = min(new_dma_sectors + 15, (max_dma_memory *
1024 * 2)) & 0xfffffff0;
 
        /*
         * We never shrink the buffers - this leads to
@@ -330,7 +353,7 @@ void scsi_resize_dma_pool(void)
                        for (i = dma_sectors / SECTORS_PER_PAGE;
                           i < new_dma_sectors / SECTORS_PER_PAGE; i++)
{
                                new_dma_malloc_pages[i] = (unsigned char
*)
-                                   __get_free_pages(GFP_ATOMIC |
GFP_DMA, 0);
+                                   __get_free_pages(dma_gfp_flags(),
0);
                                if (!new_dma_malloc_pages[i])
                                        break;
                        }
@@ -430,7 +453,7 @@ int scsi_init_minimal_dma_pool(void)
                if (dma_malloc_pages) {
                         memset(dma_malloc_pages, 0, size);
                        dma_malloc_pages[0] = (unsigned char *)
-                           __get_free_pages(GFP_ATOMIC | GFP_DMA, 0);
+                           __get_free_pages(dma_gfp_flags(), 0);
                        if (dma_malloc_pages[0])
                                has_space = 1;
                }
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to