This patch updates the datafab driver to the new scatter-gather handling,
which makes it safe for systems with >1GByte of memory.

Greg, please apply.

Matt

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

Date: Mon, 1 Dec 2003 10:53:00 -0500 (EST)
From: Alan Stern <[EMAIL PROTECTED]>
Subject: PATCH: (as143) Convert datafab to use the new s-g routines
To: Matthew Dharm <[EMAIL PROTECTED]>
cc: USB Storage List <[EMAIL PROTECTED]>
X-Spam-Status: No, hits=0.4 required=5.0
        tests=AWL,PATCH_UNIFIED_DIFF,RCVD_IN_OSIRUSOFT_COM,
              SPAM_PHRASE_00_01,USER_AGENT_PINE,X_OSIRU_OPEN_RELAY
        version=2.44

Matt:

This patch changes the datafab driver to make it use the new 
scatter-gather routines.  It has been tested by Eduard Hasenleithner.

Alan Stern


===== datafab.c 1.19 vs edited =====
--- 1.19/drivers/usb/storage/datafab.c  Mon Jul 14 00:43:20 2003
+++ edited/drivers/usb/storage/datafab.c        Mon Nov 24 10:21:47 2003
@@ -51,7 +51,6 @@
  */
 
 #include "transport.h"
-#include "raw_bulk.h"
 #include "protocol.h"
 #include "usb.h"
 #include "debug.h"
@@ -91,16 +90,14 @@
                             struct datafab_info *info,
                             u32 sector,
                             u32 sectors, 
-                            unsigned char *dest, 
+                            unsigned char *buffer, 
                             int use_sg)
 {
        unsigned char *command = us->iobuf;
-       unsigned char *buffer = NULL;
-       unsigned char *ptr;
        unsigned char  thistime;
-       int totallen, len, result;
-       int sg_idx = 0, sg_offset = 0;
-       int rc;
+       unsigned int totallen, alloclen;
+       int len, result;
+       unsigned int sg_idx = 0, sg_offset = 0;
 
        // we're working in LBA mode.  according to the ATA spec, 
        // we can support up to 28-bit addressing.  I don't know if Datafab
@@ -111,23 +108,28 @@
                return USB_STOR_TRANSPORT_ERROR;
 
        if (info->lun == -1) {
-               rc = datafab_determine_lun(us, info);
-               if (rc != USB_STOR_TRANSPORT_GOOD)
-                       return rc;
+               result = datafab_determine_lun(us, info);
+               if (result != USB_STOR_TRANSPORT_GOOD)
+                       return result;
        }
 
        totallen = sectors * info->ssize;
 
-       do {
-               // loop, never allocate or transfer more than 64k at once
-               // (min(128k, 255*info->ssize) is the real limit)
-
-               len = min_t(int, totallen, 65536);
+       // Since we don't read more than 64 KB at a time, we have to create
+       // a bounce buffer if the transfer uses scatter-gather.
 
-               ptr = buffer = (use_sg ? kmalloc(len, GFP_NOIO) : dest);
+       alloclen = min(totallen, 65536u);
+       if (use_sg) {
+               buffer = kmalloc(alloclen, GFP_NOIO);
                if (buffer == NULL)
                        return USB_STOR_TRANSPORT_ERROR;
+       }
 
+       do {
+               // loop, never allocate or transfer more than 64k at once
+               // (min(128k, 255*info->ssize) is the real limit)
+
+               len = min(totallen, alloclen);
                thistime = (len / info->ssize) & 0xff;
 
                command[0] = 0;
@@ -135,7 +137,7 @@
                command[2] = sector & 0xFF;
                command[3] = (sector >> 8) & 0xFF;
                command[4] = (sector >> 16) & 0xFF;
-       
+
                command[5] = 0xE0 + (info->lun << 4);
                command[5] |= (sector >> 24) & 0x0F;
                command[6] = 0x20;
@@ -147,24 +149,22 @@
                        goto leave;
 
                // read the result
-               result = datafab_bulk_read(us, ptr, len);
+               result = datafab_bulk_read(us, buffer, len);
                if (result != USB_STOR_XFER_GOOD)
                        goto leave;
 
-               sectors -= thistime;
-               sector  += thistime;
-
-               if (use_sg) {
-                       us_copy_to_sgbuf(buffer, len, dest,
-                                        &sg_idx, &sg_offset, use_sg);
-                       kfree(buffer);
-               } else {
-                       dest += len;
-               }
+               if (use_sg)
+                       usb_stor_access_xfer_buf(buffer, len, us->srb,
+                                        &sg_idx, &sg_offset, TO_XFER_BUF);
+               else
+                       buffer += len;
 
+               sector += thistime;
                totallen -= len;
        } while (totallen > 0);
 
+       if (use_sg)
+               kfree(buffer);
        return USB_STOR_TRANSPORT_GOOD;
 
  leave:
@@ -178,16 +178,15 @@
                              struct datafab_info *info,
                              u32 sector,
                              u32 sectors, 
-                             unsigned char *src, 
+                             unsigned char *buffer, 
                              int use_sg)
 {
        unsigned char *command = us->iobuf;
        unsigned char *reply = us->iobuf;
-       unsigned char *buffer = NULL;
-       unsigned char *ptr;
        unsigned char thistime;
-       int totallen, len, result, rc;
-       int sg_idx = 0, sg_offset = 0;
+       unsigned int totallen, alloclen;
+       int len, result;
+       unsigned int sg_idx = 0, sg_offset = 0;
 
        // we're working in LBA mode.  according to the ATA spec, 
        // we can support up to 28-bit addressing.  I don't know if Datafab
@@ -198,38 +197,34 @@
                return USB_STOR_TRANSPORT_ERROR;
 
        if (info->lun == -1) {
-               rc = datafab_determine_lun(us, info);
-               if (rc != USB_STOR_TRANSPORT_GOOD)
-                       return rc;
+               result = datafab_determine_lun(us, info);
+               if (result != USB_STOR_TRANSPORT_GOOD)
+                       return result;
        }
 
-       // If we're using scatter-gather, we have to create a new
-       // buffer to read all of the data in first, since a
-       // scatter-gather buffer could in theory start in the middle
-       // of a page, which would be bad. A developer who wants a
-       // challenge might want to write a limited-buffer
-       // version of this code.
-
        totallen = sectors * info->ssize;
 
-       do {
-               // loop, never allocate or transfer more than 64k at once
-               // (min(128k, 255*info->ssize) is the real limit)
-
-               len = min_t(int, totallen, 65536);
-
-               // if we are using scatter-gather,
-               // first copy all to one big buffer
+       // Since we don't write more than 64 KB at a time, we have to create
+       // a bounce buffer if the transfer uses scatter-gather.
 
-               buffer = us_copy_from_sgbuf(src, len, &sg_idx,
-                                           &sg_offset, use_sg);
+       alloclen = min(totallen, 65536u);
+       if (use_sg) {
+               buffer = kmalloc(alloclen, GFP_NOIO);
                if (buffer == NULL)
                        return USB_STOR_TRANSPORT_ERROR;
+       }
 
-               ptr = buffer;
+       do {
+               // loop, never allocate or transfer more than 64k at once
+               // (min(128k, 255*info->ssize) is the real limit)
 
+               len = min(totallen, alloclen);
                thistime = (len / info->ssize) & 0xff;
 
+               if (use_sg)
+                       usb_stor_access_xfer_buf(buffer, len, us->srb,
+                                       &sg_idx, &sg_offset, FROM_XFER_BUF);
+
                command[0] = 0;
                command[1] = thistime;
                command[2] = sector & 0xFF;
@@ -247,7 +242,7 @@
                        goto leave;
 
                // send the data
-               result = datafab_bulk_write(us, ptr, len);
+               result = datafab_bulk_write(us, buffer, len);
                if (result != USB_STOR_XFER_GOOD)
                        goto leave;
 
@@ -264,17 +259,15 @@
                        goto leave;
                }
 
-               sectors -= thistime;
-               sector  += thistime;
-
-               if (use_sg)
-                       kfree(buffer);
-               else
-                       src += len;
+               if (!use_sg)
+                       buffer += len;
 
+               sector += thistime;
                totallen -= len;
        } while (totallen > 0);
 
+       if (use_sg)
+               kfree(buffer);
        return USB_STOR_TRANSPORT_GOOD;
 
  leave:
@@ -435,7 +428,7 @@
        // datafab reader doesn't present a SCSI interface so we
        // fudge the SCSI commands...
        //
-       
+
        if (sense_6)
                param_len = srb->cmnd[4];
        else

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

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

Somebody call an exorcist!
                                        -- Dust Puppy
User Friendly, 5/16/1998

Attachment: pgp00000.pgp
Description: PGP signature

Reply via email to