~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/scsi/scsi_dma.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  scsi_dma.c Copyright (C) 2000 Eric Youngdale
  3  *
  4  *  mid-level SCSI DMA bounce buffer allocator
  5  *
  6  */
  7 
  8 #define __NO_VERSION__
  9 #include <linux/config.h>
 10 #include <linux/module.h>
 11 #include <linux/blk.h>
 12 
 13 
 14 #include "scsi.h"
 15 #include "hosts.h"
 16 #include "constants.h"
 17 
 18 #ifdef CONFIG_KMOD
 19 #include <linux/kmod.h>
 20 #endif
 21 
 22 /*
 23  * PAGE_SIZE must be a multiple of the sector size (512).  True
 24  * for all reasonably recent architectures (even the VAX...).
 25  */
 26 #define SECTOR_SIZE             512
 27 #define SECTORS_PER_PAGE        (PAGE_SIZE/SECTOR_SIZE)
 28 
 29 #if SECTORS_PER_PAGE <= 8
 30 typedef unsigned char FreeSectorBitmap;
 31 #elif SECTORS_PER_PAGE <= 32
 32 typedef unsigned int FreeSectorBitmap;
 33 #else
 34 #error You lose.
 35 #endif
 36 
 37 /*
 38  * Used for access to internal allocator used for DMA safe buffers.
 39  */
 40 static spinlock_t allocator_request_lock = SPIN_LOCK_UNLOCKED;
 41 
 42 static FreeSectorBitmap *dma_malloc_freelist = NULL;
 43 static int need_isa_bounce_buffers;
 44 static unsigned int dma_sectors = 0;
 45 unsigned int scsi_dma_free_sectors = 0;
 46 unsigned int scsi_need_isa_buffer = 0;
 47 static unsigned char **dma_malloc_pages = NULL;
 48 
 49 /*
 50  * Function:    scsi_malloc
 51  *
 52  * Purpose:     Allocate memory from the DMA-safe pool.
 53  *
 54  * Arguments:   len       - amount of memory we need.
 55  *
 56  * Lock status: No locks assumed to be held.  This function is SMP-safe.
 57  *
 58  * Returns:     Pointer to memory block.
 59  *
 60  * Notes:       Prior to the new queue code, this function was not SMP-safe.
 61  *              This function can only allocate in units of sectors
 62  *              (i.e. 512 bytes).
 63  *
 64  *              We cannot use the normal system allocator becuase we need
 65  *              to be able to guarantee that we can process a complete disk
 66  *              I/O request without touching the system allocator.  Think
 67  *              about it - if the system were heavily swapping, and tried to
 68  *              write out a block of memory to disk, and the SCSI code needed
 69  *              to allocate more memory in order to be able to write the
 70  *              data to disk, you would wedge the system.
 71  */
 72 void *scsi_malloc(unsigned int len)
 73 {
 74         unsigned int nbits, mask;
 75         unsigned long flags;
 76 
 77         int i, j;
 78         if (len % SECTOR_SIZE != 0 || len > PAGE_SIZE)
 79                 return NULL;
 80 
 81         nbits = len >> 9;
 82         mask = (1 << nbits) - 1;
 83 
 84         spin_lock_irqsave(&allocator_request_lock, flags);
 85 
 86         for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++)
 87                 for (j = 0; j <= SECTORS_PER_PAGE - nbits; j++) {
 88                         if ((dma_malloc_freelist[i] & (mask << j)) == 0) {
 89                                 dma_malloc_freelist[i] |= (mask << j);
 90                                 scsi_dma_free_sectors -= nbits;
 91 #ifdef DEBUG
 92                                 SCSI_LOG_MLQUEUE(3, printk("SMalloc: %d %p [From:%p]\n", len, dma_malloc_pages[i] + (j << 9)));
 93                                 printk("SMalloc: %d %p [From:%p]\n", len, dma_malloc_pages[i] + (j << 9));
 94 #endif
 95                                 spin_unlock_irqrestore(&allocator_request_lock, flags);
 96                                 return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9));
 97                         }
 98                 }
 99         spin_unlock_irqrestore(&allocator_request_lock, flags);
100         return NULL;            /* Nope.  No more */
101 }
102 
103 /*
104  * Function:    scsi_free
105  *
106  * Purpose:     Free memory into the DMA-safe pool.
107  *
108  * Arguments:   ptr       - data block we are freeing.
109  *              len       - size of block we are freeing.
110  *
111  * Lock status: No locks assumed to be held.  This function is SMP-safe.
112  *
113  * Returns:     Nothing
114  *
115  * Notes:       This function *must* only be used to free memory
116  *              allocated from scsi_malloc().
117  *
118  *              Prior to the new queue code, this function was not SMP-safe.
119  *              This function can only allocate in units of sectors
120  *              (i.e. 512 bytes).
121  */
122 int scsi_free(void *obj, unsigned int len)
123 {
124         unsigned int page, sector, nbits, mask;
125         unsigned long flags;
126 
127 #ifdef DEBUG
128         unsigned long ret = 0;
129 
130 #ifdef __mips__
131         __asm__ __volatile__("move\t%0,$31":"=r"(ret));
132 #else
133         ret = __builtin_return_address(0);
134 #endif
135         printk("scsi_free %p %d\n", obj, len);
136         SCSI_LOG_MLQUEUE(3, printk("SFree: %p %d\n", obj, len));
137 #endif
138 
139         spin_lock_irqsave(&allocator_request_lock, flags);
140 
141         for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) {
142                 unsigned long page_addr = (unsigned long) dma_malloc_pages[page];
143                 if ((unsigned long) obj >= page_addr &&
144                     (unsigned long) obj < page_addr + PAGE_SIZE) {
145                         sector = (((unsigned long) obj) - page_addr) >> 9;
146 
147                         nbits = len >> 9;
148                         mask = (1 << nbits) - 1;
149 
150                         if (sector + nbits > SECTORS_PER_PAGE)
151                                 panic("scsi_free:Bad memory alignment");
152 
153                         if ((dma_malloc_freelist[page] &
154                              (mask << sector)) != (mask << sector)) {
155 #ifdef DEBUG
156                                 printk("scsi_free(obj=%p, len=%d) called from %08lx\n",
157                                        obj, len, ret);
158 #endif
159                                 panic("scsi_free:Trying to free unused memory");
160                         }
161                         scsi_dma_free_sectors += nbits;
162                         dma_malloc_freelist[page] &= ~(mask << sector);
163                         spin_unlock_irqrestore(&allocator_request_lock, flags);
164                         return 0;
165                 }
166         }
167         panic("scsi_free:Bad offset");
168 }
169 
170 
171 /*
172  * Function:    scsi_resize_dma_pool
173  *
174  * Purpose:     Ensure that the DMA pool is sufficiently large to be
175  *              able to guarantee that we can always process I/O requests
176  *              without calling the system allocator.
177  *
178  * Arguments:   None.
179  *
180  * Lock status: No locks assumed to be held.  This function is SMP-safe.
181  *
182  * Returns:     Nothing
183  *
184  * Notes:       Prior to the new queue code, this function was not SMP-safe.
185  *              Go through the device list and recompute the most appropriate
186  *              size for the dma pool.  Then grab more memory (as required).
187  */
188 void scsi_resize_dma_pool(void)
189 {
190         int i, k;
191         unsigned long size;
192         unsigned long flags;
193         struct Scsi_Host *shpnt;
194         struct Scsi_Host *host = NULL;
195         Scsi_Device *SDpnt;
196         FreeSectorBitmap *new_dma_malloc_freelist = NULL;
197         unsigned int new_dma_sectors = 0;
198         unsigned int new_need_isa_buffer = 0;
199         unsigned char **new_dma_malloc_pages = NULL;
200         int out_of_space = 0;
201 
202         spin_lock_irqsave(&allocator_request_lock, flags);
203 
204         if (!scsi_hostlist) {
205                 /*
206                  * Free up the DMA pool.
207                  */
208                 if (scsi_dma_free_sectors != dma_sectors)
209                         panic("SCSI DMA pool memory leak %d %d\n", scsi_dma_free_sectors, dma_sectors);
210 
211                 for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++)
212                         free_pages((unsigned long) dma_malloc_pages[i], 0);
213                 if (dma_malloc_pages)
214                         kfree((char *) dma_malloc_pages);
215                 dma_malloc_pages = NULL;
216                 if (dma_malloc_freelist)
217                         kfree((char *) dma_malloc_freelist);
218                 dma_malloc_freelist = NULL;
219                 dma_sectors = 0;
220                 scsi_dma_free_sectors = 0;
221                 spin_unlock_irqrestore(&allocator_request_lock, flags);
222                 return;
223         }
224         /* Next, check to see if we need to extend the DMA buffer pool */
225 
226         new_dma_sectors = 2 * SECTORS_PER_PAGE;         /* Base value we use */
227 
228         if (__pa(high_memory) - 1 > ISA_DMA_THRESHOLD)
229                 need_isa_bounce_buffers = 1;
230         else
231                 need_isa_bounce_buffers = 0;
232 
233         if (scsi_devicelist)
234                 for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next)
235                         new_dma_sectors += SECTORS_PER_PAGE;    /* Increment for each host */
236 
237         for (host = scsi_hostlist; host; host = host->next) {
238                 for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
239                         /*
240                          * sd and sr drivers allocate scatterlists.
241                          * sr drivers may allocate for each command 1x2048 or 2x1024 extra
242                          * buffers for 2k sector size and 1k fs.
243                          * sg driver allocates buffers < 4k.
244                          * st driver does not need buffers from the dma pool.
245                          * estimate 4k buffer/command for devices of unknown type (should panic).
246                          */
247                         if (SDpnt->type == TYPE_WORM || SDpnt->type == TYPE_ROM ||
248                             SDpnt->type == TYPE_DISK || SDpnt->type == TYPE_MOD) {
249                                 int nents = host->sg_tablesize;
250 #ifdef DMA_CHUNK_SIZE
251                                 /* If the architecture does DMA sg merging, make sure
252                                    we count with at least 64 entries even for HBAs
253                                    which handle very few sg entries.  */
254                                 if (nents < 64) nents = 64;
255 #endif
256                                 new_dma_sectors += ((nents *
257                                 sizeof(struct scatterlist) + 511) >> 9) *
258                                  SDpnt->queue_depth;
259                                 if (SDpnt->type == TYPE_WORM || SDpnt->type == TYPE_ROM)
260                                         new_dma_sectors += (2048 >> 9) * SDpnt->queue_depth;
261                         } else if (SDpnt->type == TYPE_SCANNER ||
262                                    SDpnt->type == TYPE_PROCESSOR ||
263                                    SDpnt->type == TYPE_COMM ||
264                                    SDpnt->type == TYPE_MEDIUM_CHANGER ||
265                                    SDpnt->type == TYPE_ENCLOSURE) {
266                                 new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth;
267                         } else {
268                                 if (SDpnt->type != TYPE_TAPE) {
269                                         printk("resize_dma_pool: unknown device type %d\n", SDpnt->type);
270                                         new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth;
271                                 }
272                         }
273 
274                         if (host->unchecked_isa_dma &&
275                             need_isa_bounce_buffers &&
276                             SDpnt->type != TYPE_TAPE) {
277                                 new_dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize *
278                                     SDpnt->queue_depth;
279                                 new_need_isa_buffer++;
280                         }
281                 }
282         }
283 
284 #ifdef DEBUG_INIT
285         printk("resize_dma_pool: needed dma sectors = %d\n", new_dma_sectors);
286 #endif
287 
288         /* limit DMA memory to 32MB: */
289         new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
290 
291         /*
292          * We never shrink the buffers - this leads to
293          * race conditions that I would rather not even think
294          * about right now.
295          */
296 #if 0                           /* Why do this? No gain and risks out_of_space */
297         if (new_dma_sectors < dma_sectors)
298                 new_dma_sectors = dma_sectors;
299 #endif
300         if (new_dma_sectors <= dma_sectors) {
301                 spin_unlock_irqrestore(&allocator_request_lock, flags);
302                 return;         /* best to quit while we are in front */
303         }
304 
305         for (k = 0; k < 20; ++k) {      /* just in case */
306                 out_of_space = 0;
307                 size = (new_dma_sectors / SECTORS_PER_PAGE) *
308                     sizeof(FreeSectorBitmap);
309                 new_dma_malloc_freelist = (FreeSectorBitmap *)
310                     kmalloc(size, GFP_ATOMIC);
311                 if (new_dma_malloc_freelist) {
312                         memset(new_dma_malloc_freelist, 0, size);
313                         size = (new_dma_sectors / SECTORS_PER_PAGE) *
314                             sizeof(*new_dma_malloc_pages);
315                         new_dma_malloc_pages = (unsigned char **)
316                             kmalloc(size, GFP_ATOMIC);
317                         if (!new_dma_malloc_pages) {
318                                 size = (new_dma_sectors / SECTORS_PER_PAGE) *
319                                     sizeof(FreeSectorBitmap);
320                                 kfree((char *) new_dma_malloc_freelist);
321                                 out_of_space = 1;
322                         } else {
323                                 memset(new_dma_malloc_pages, 0, size);
324                         }
325                 } else
326                         out_of_space = 1;
327 
328                 if ((!out_of_space) && (new_dma_sectors > dma_sectors)) {
329                         for (i = dma_sectors / SECTORS_PER_PAGE;
330                            i < new_dma_sectors / SECTORS_PER_PAGE; i++) {
331                                 new_dma_malloc_pages[i] = (unsigned char *)
332                                     __get_free_pages(GFP_ATOMIC | GFP_DMA, 0);
333                                 if (!new_dma_malloc_pages[i])
334                                         break;
335                         }
336                         if (i != new_dma_sectors / SECTORS_PER_PAGE) {  /* clean up */
337                                 int k = i;
338 
339                                 out_of_space = 1;
340                                 for (i = 0; i < k; ++i)
341                                         free_pages((unsigned long) new_dma_malloc_pages[i], 0);
342                         }
343                 }
344                 if (out_of_space) {     /* try scaling down new_dma_sectors request */
345                         printk("scsi::resize_dma_pool: WARNING, dma_sectors=%u, "
346                                "wanted=%u, scaling\n", dma_sectors, new_dma_sectors);
347                         if (new_dma_sectors < (8 * SECTORS_PER_PAGE))
348                                 break;  /* pretty well hopeless ... */
349                         new_dma_sectors = (new_dma_sectors * 3) / 4;
350                         new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
351                         if (new_dma_sectors <= dma_sectors)
352                                 break;  /* stick with what we have got */
353                 } else
354                         break;  /* found space ... */
355         }                       /* end of for loop */
356         if (out_of_space) {
357                 spin_unlock_irqrestore(&allocator_request_lock, flags);
358                 scsi_need_isa_buffer = new_need_isa_buffer;     /* some useful info */
359                 printk("      WARNING, not enough memory, pool not expanded\n");
360                 return;
361         }
362         /* When we dick with the actual DMA list, we need to
363          * protect things
364          */
365         if (dma_malloc_freelist) {
366                 size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(FreeSectorBitmap);
367                 memcpy(new_dma_malloc_freelist, dma_malloc_freelist, size);
368                 kfree((char *) dma_malloc_freelist);
369         }
370         dma_malloc_freelist = new_dma_malloc_freelist;
371 
372         if (dma_malloc_pages) {
373                 size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages);
374                 memcpy(new_dma_malloc_pages, dma_malloc_pages, size);
375                 kfree((char *) dma_malloc_pages);
376         }
377         scsi_dma_free_sectors += new_dma_sectors - dma_sectors;
378         dma_malloc_pages = new_dma_malloc_pages;
379         dma_sectors = new_dma_sectors;
380         scsi_need_isa_buffer = new_need_isa_buffer;
381 
382         spin_unlock_irqrestore(&allocator_request_lock, flags);
383 
384 #ifdef DEBUG_INIT
385         printk("resize_dma_pool: dma free sectors   = %d\n", scsi_dma_free_sectors);
386         printk("resize_dma_pool: dma sectors        = %d\n", dma_sectors);
387         printk("resize_dma_pool: need isa buffers   = %d\n", scsi_need_isa_buffer);
388 #endif
389 }
390 
391 /*
392  * Function:    scsi_init_minimal_dma_pool
393  *
394  * Purpose:     Allocate a minimal (1-page) DMA pool.
395  *
396  * Arguments:   None.
397  *
398  * Lock status: No locks assumed to be held.  This function is SMP-safe.
399  *
400  * Returns:     Nothing
401  *
402  * Notes:       
403  */
404 int scsi_init_minimal_dma_pool(void)
405 {
406         unsigned long size;
407         unsigned long flags;
408         int has_space = 0;
409 
410         spin_lock_irqsave(&allocator_request_lock, flags);
411 
412         dma_sectors = PAGE_SIZE / SECTOR_SIZE;
413         scsi_dma_free_sectors = dma_sectors;
414         /*
415          * Set up a minimal DMA buffer list - this will be used during scan_scsis
416          * in some cases.
417          */
418 
419         /* One bit per sector to indicate free/busy */
420         size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(FreeSectorBitmap);
421         dma_malloc_freelist = (FreeSectorBitmap *)
422             kmalloc(size, GFP_ATOMIC);
423         if (dma_malloc_freelist) {
424                 memset(dma_malloc_freelist, 0, size);
425                 /* One pointer per page for the page list */
426                 dma_malloc_pages = (unsigned char **) kmalloc(
427                         (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages),
428                                                              GFP_ATOMIC);
429                 if (dma_malloc_pages) {
430                         memset(dma_malloc_pages, 0, size);
431                         dma_malloc_pages[0] = (unsigned char *)
432                             __get_free_pages(GFP_ATOMIC | GFP_DMA, 0);
433                         if (dma_malloc_pages[0])
434                                 has_space = 1;
435                 }
436         }
437         if (!has_space) {
438                 if (dma_malloc_freelist) {
439                         kfree((char *) dma_malloc_freelist);
440                         if (dma_malloc_pages)
441                                 kfree((char *) dma_malloc_pages);
442                 }
443                 spin_unlock_irqrestore(&allocator_request_lock, flags);
444                 printk("scsi::init_module: failed, out of memory\n");
445                 return 1;
446         }
447 
448         spin_unlock_irqrestore(&allocator_request_lock, flags);
449         return 0;
450 }
451 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.