This patch does some serious cleanup to the sddr09 driver.  It is one of
many that are about to follow over the next couple of days.

This patch removes some very ugly scatter-gather from the card
initialization.  It also starts getting rid of some of the 'magic
constants' that plague this driver.

Greg, please apply.  Note that you need to apply this in order relative to
the other patches you are holding.

Matt

----- Forwarded message from Alan Stern <[EMAIL PROTECTED]> -----

Date: Fri, 21 Nov 2003 13:13:27 -0500 (EST)
From: Alan Stern <[EMAIL PROTECTED]>
Subject: PATCH: (as136) Remove unneeded scatter-gather operations in sddr09
To: Matthew Dharm <[EMAIL PROTECTED]>
cc: [EMAIL PROTECTED], USB Storage List <[EMAIL PROTECTED]>
Return-Path: <[EMAIL PROTECTED]>
X-Spam-Status: No, hits=-4.0 required=5.0 tests=UNIFIED_PATCH,RCVD_IN_ORBZ version=2.11

Matt:

This patch removes some unnecessary scatter-gather code from the sddr09 
driver.  In its place a single smaller buffer is re-used each time through 
an I/O loop, as opposed to transferring all the data at once.

Andries Brouwer kindly tested this and suggested some improvements to get
it working right.

Two more sddr09 patches are forthcoming, plus others to repair the use of 
scatter-gather buffers elsewhere in usb-storage.  Andries, you may want 
to accumulate patches as136 - as140 and test them all together to verify 
that I haven't messed anything else up.

Alan Stern


--- a/drivers/usb/storage/sddr09.c      Fri Nov 21 11:24:31 2003
+++ b/drivers/usb/storage/sddr09.c      Fri Nov 21 10:51:19 2003
@@ -1092,69 +1092,33 @@
 static int
 sddr09_read_map(struct us_data *us) {
 
-       struct scatterlist *sg;
        struct sddr09_card_info *info = (struct sddr09_card_info *) us->extra;
        int numblocks, alloc_len, alloc_blocks;
        int i, j, result;
-       unsigned char *ptr;
+       unsigned char *buffer, *buffer_end, *ptr;
        unsigned int lba, lbact;
 
        if (!info->capacity)
                return -1;
 
-       // read 64 (1<<6) bytes for every block 
-       // ( 1 << ( blockshift + pageshift ) bytes)
-       //       of capacity:
-       // (1<<6)*capacity/(1<<(b+p)) =
-       // ((1<<6)*capacity)>>(b+p) =
-       // capacity>>(b+p-6)
-
-       alloc_len = info->capacity >> 
-               (info->blockshift + info->pageshift - CONTROL_SHIFT);
-
-       // Allocate a number of scatterlist structures according to
-       // the number of 128k blocks in the alloc_len. Adding 128k-1
-       // and then dividing by 128k gives the correct number of blocks.
-       // 128k = 1<<17
-
-       alloc_blocks = (alloc_len + (1<<17) - 1) >> 17;
-       sg = kmalloc(alloc_blocks*sizeof(struct scatterlist),
-                    GFP_NOIO);
-       if (sg == NULL)
-               return 0;
-
-       for (i=0; i<alloc_blocks; i++) {
-               int alloc_req = (i < alloc_blocks-1 ? 1 << 17 : alloc_len);
-               char *vaddr = kmalloc(alloc_req, GFP_NOIO);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,3)
-               sg[i].page = virt_to_page(vaddr);
-               sg[i].offset = offset_in_page(vaddr);
-#else
-               sg[i].address = vaddr;
-#endif
-               sg[i].length = alloc_req;
-               alloc_len -= alloc_req;
-       }
-
-       for (i=0; i<alloc_blocks; i++)
-               if (sg[i].page == NULL) {
-                       for (i=0; i<alloc_blocks; i++)
-                               if (sg[i].page != NULL)
-                                       kfree(sg_address(sg[i]));
-                       kfree(sg);
-                       return 0;
-               }
+       // size of a block is 1 << (blockshift + pageshift) bytes
+       // divide into the total capacity to get the number of blocks
 
        numblocks = info->capacity >> (info->blockshift + info->pageshift);
 
-       result = sddr09_read_control(us, 0, numblocks,
-                                    (unsigned char *)sg, alloc_blocks);
-       if (result != USB_STOR_TRANSPORT_GOOD) {
-               for (i=0; i<alloc_blocks; i++)
-                       kfree(sg_address(sg[i]));
-               kfree(sg);
-               return -1;
-       }
+       // read 64 bytes for every block (actually 1 << CONTROL_SHIFT)
+       // but only use a 64 KB buffer
+       // buffer size used must be a multiple of (1 << CONTROL_SHIFT)
+#define SDDR09_READ_MAP_BUFSZ 65536
+
+       alloc_blocks = min(numblocks, SDDR09_READ_MAP_BUFSZ >> CONTROL_SHIFT);
+       alloc_len = (alloc_blocks << CONTROL_SHIFT);
+       buffer = kmalloc(alloc_len, GFP_NOIO);
+       if (buffer == NULL)
+               return 0;
+       buffer_end = buffer + alloc_len;
+
+#undef SDDR09_READ_MAP_BUFSZ
 
        kfree(info->lba_to_pba);
        kfree(info->pba_to_lba);
@@ -1162,29 +1126,31 @@
        info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO);
 
        if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) {
-               kfree(info->lba_to_pba);
-               kfree(info->pba_to_lba);
-               info->lba_to_pba = NULL;
-               info->pba_to_lba = NULL;
-               for (i=0; i<alloc_blocks; i++)
-                       kfree(sg_address(sg[i]));
-               kfree(sg);
-               return 0;
+               result = -1;
+               goto done;
        }
 
        for (i = 0; i < numblocks; i++)
                info->lba_to_pba[i] = info->pba_to_lba[i] = UNDEF;
 
-       ptr = sg_address(sg[0]);
-
        /*
         * Define lba-pba translation table
         */
-       // Each block is 64 bytes of control data, so block i is located in
-       // scatterlist block i*64/128k = i*(2^6)*(2^-17) = i*(2^-11)
 
-       for (i=0; i<numblocks; i++) {
-               ptr = sg_address(sg[i>>11]) + ((i&0x7ff)<<6);
+       ptr = buffer_end;
+       for (i = 0; i < numblocks; i++) {
+               ptr += (1 << CONTROL_SHIFT);
+               if (ptr >= buffer_end) {
+                       ptr = buffer;
+                       result = sddr09_read_control(
+                               us, i << (info->blockshift + 8),
+                               min(alloc_blocks, numblocks - i),
+                               buffer, 0);
+                       if (result != USB_STOR_TRANSPORT_GOOD) {
+                               result = -1;
+                               goto done;
+                       }
+               }
 
                if (i == 0 || i == 1) {
                        info->pba_to_lba[i] = UNUSABLE;
@@ -1292,11 +1258,17 @@
        }
        info->lbact = lbact;
        US_DEBUGP("Found %d LBA's\n", lbact);
+       result = 0;
 
-       for (i=0; i<alloc_blocks; i++)
-               kfree(sg_address(sg[i]));
-       kfree(sg);
-       return 0;
+ done:
+       if (result != 0) {
+               kfree(info->lba_to_pba);
+               kfree(info->pba_to_lba);
+               info->lba_to_pba = NULL;
+               info->pba_to_lba = NULL;
+       }
+       kfree(buffer);
+       return result;
 }
 
 static void

----- End forwarded message -----

-- 
Matthew Dharm                              Home: [EMAIL PROTECTED] 
Maintainer, Linux USB Mass Storage Driver

A female who groks UNIX?  My universe is collapsing.
                                        -- Mike
User Friendly, 10/11/1998

Attachment: pgp00000.pgp
Description: PGP signature

Reply via email to