This patch makes our private I/O buffer allocated such that it's pre-mapped
for DMA.  We then add some logic to make sure that we don't try to re-map
it.

We also make the size of the buffer large enough for other sub-drivers,
which will be converted shortly.

Greg, please apply.

Matt

# This is a BitKeeper generated patch for the following project:
# Project Name: greg k-h's linux 2.5 USB kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#                  ChangeSet    1.721   -> 1.722  
#       drivers/usb/storage/usb.h       1.40    -> 1.41   
#       drivers/usb/storage/transport.c 1.89    -> 1.90   
#       drivers/usb/storage/usb.c       1.80    -> 1.81   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/06/28      [EMAIL PROTECTED]       1.722
# Allocate and map the general-purpose I/O buffer for DMA.
# --------------------------------------------
#
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c   Sat Jun 28 20:31:31 2003
+++ b/drivers/usb/storage/transport.c   Sat Jun 28 20:31:31 2003
@@ -147,8 +147,19 @@
        us->current_urb->context = &urb_done;
        us->current_urb->actual_length = 0;
        us->current_urb->error_count = 0;
-       us->current_urb->transfer_flags = URB_ASYNC_UNLINK;
        us->current_urb->status = 0;
+
+       /* we assume that if transfer_buffer isn't us->iobuf then it
+        * hasn't been mapped for DMA.  Yes, this is clunky, but it's
+        * easier than always having the caller tell us whether the
+        * transfer buffer has already been mapped. */
+       us->current_urb->transfer_flags =
+                       (us->current_urb->transfer_buffer == us->iobuf)
+                       ? URB_ASYNC_UNLINK | URB_NO_SETUP_DMA_MAP
+                               | URB_NO_TRANSFER_DMA_MAP
+                       : URB_ASYNC_UNLINK | URB_NO_SETUP_DMA_MAP;
+       us->current_urb->transfer_dma = us->iobuf_dma;
+       us->current_urb->setup_dma = us->cr_dma;
 
        /* submit the URB */
        status = usb_submit_urb(us->current_urb, GFP_NOIO);
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c Sat Jun 28 20:31:31 2003
+++ b/drivers/usb/storage/usb.c Sat Jun 28 20:31:31 2003
@@ -428,7 +428,7 @@
  ***********************************************************************/
 
 /* Associate our private data with the USB device */
-static void associate_dev(struct us_data *us, struct usb_interface *intf)
+static int associate_dev(struct us_data *us, struct usb_interface *intf)
 {
        US_DEBUGP("-- %s\n", __FUNCTION__);
 
@@ -441,6 +441,22 @@
         * device's reference count */
        usb_set_intfdata(intf, us);
        usb_get_dev(us->pusb_dev);
+
+       /* Allocate the device-related DMA-mapped buffers */
+       us->cr = usb_buffer_alloc(us->pusb_dev, sizeof(*us->cr),
+                       GFP_KERNEL, &us->cr_dma);
+       if (!us->cr) {
+               US_DEBUGP("usb_ctrlrequest allocation failed\n");
+               return -ENOMEM;
+       }
+
+       us->iobuf = usb_buffer_alloc(us->pusb_dev, US_IOBUF_SIZE,
+                       GFP_KERNEL, &us->iobuf_dma);
+       if (!us->iobuf) {
+               US_DEBUGP("I/O buffer allocation failed\n");
+               return -ENOMEM;
+       }
+       return 0;
 }
 
 /* Get the unusual_devs entries and the string descriptors */
@@ -742,25 +758,12 @@
 {
        int p;
 
-       /* Allocate the USB control blocks */
-       us->cr = kmalloc(sizeof(*us->cr), GFP_KERNEL);
-       if (!us->cr) {
-               US_DEBUGP("usb_ctrlrequest allocation failed\n");
-               return -ENOMEM;
-       }
-
        us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!us->current_urb) {
                US_DEBUGP("URB allocation failed\n");
                return -ENOMEM;
        }
 
-       us->iobuf = kmalloc(US_IOBUF_SIZE, GFP_KERNEL);
-       if (!us->iobuf) {
-               US_DEBUGP("I/O buffer allocation failed\n");
-               return -ENOMEM;
-       }
-
        /* Lock the device while we carry out the next two operations */
        down(&us->dev_semaphore);
 
@@ -810,8 +813,24 @@
 {
        US_DEBUGP("-- %s\n", __FUNCTION__);
        down(&us->dev_semaphore);
+
+       /* Free the device-related DMA-mapped buffers */
+       if (us->cr) {
+               usb_buffer_free(us->pusb_dev, sizeof(*us->cr), us->cr,
+                               us->cr_dma);
+               us->cr = NULL;
+       }
+       if (us->iobuf) {
+               usb_buffer_free(us->pusb_dev, US_IOBUF_SIZE, us->iobuf,
+                               us->iobuf_dma);
+               us->iobuf = NULL;
+       }
+
+       /* Remove our private data from the interface and decrement the
+        * device's reference count */
        usb_set_intfdata(us->pusb_intf, NULL);
        usb_put_dev(us->pusb_dev);
+
        us->pusb_dev = NULL;
        us->pusb_intf = NULL;
        up(&us->dev_semaphore);
@@ -850,18 +869,11 @@
                us->extra_destructor(us->extra);
        }
 
-       /* Destroy the extra data */
-       if (us->extra) {
+       /* Free the extra data and the URB */
+       if (us->extra)
                kfree(us->extra);
-       }
-
-       /* Free the USB control blocks */
-       if (us->iobuf)
-               kfree(us->iobuf);
        if (us->current_urb)
                usb_free_urb(us->current_urb);
-       if (us->cr)
-               kfree(us->cr);
 
        /* Free the structure itself */
        kfree(us);
@@ -892,7 +904,9 @@
        init_completion(&(us->notify));
 
        /* Associate the us_data structure with the USB device */
-       associate_dev(us, intf);
+       result = associate_dev(us, intf);
+       if (result)
+               goto BadDevice;
 
        /*
         * Get the unusual_devs entries and the descriptors
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h Sat Jun 28 20:31:31 2003
+++ b/drivers/usb/storage/usb.h Sat Jun 28 20:31:31 2003
@@ -92,7 +92,14 @@
 
 #define USB_STOR_STRING_LEN 32
 
-#define US_IOBUF_SIZE          32      /* Big enough for bulk-only CBW */
+/*
+ * We provide a DMA-mapped I/O buffer for use with small USB transfers.
+ * It turns out that CB[I] needs a 12-byte buffer and Bulk-only needs a
+ * 31-byte buffer.  But Freecom needs a 64-byte buffer, so that's the
+ * size we'll allocate.
+ */
+
+#define US_IOBUF_SIZE          64      /* Size of the DMA-mapped I/O buffer */
 
 typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
 typedef int (*trans_reset)(struct us_data*);
@@ -147,6 +154,8 @@
        struct usb_ctrlrequest  *cr;             /* control requests     */
        struct usb_sg_request   current_sg;      /* scatter-gather req.  */
        unsigned char           *iobuf;          /* I/O buffer           */
+       dma_addr_t              cr_dma;          /* buffer DMA addresses */
+       dma_addr_t              iobuf_dma;
 
        /* mutual exclusion structures */
        struct semaphore        sema;            /* to sleep thread on   */
-- 
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