This patch creates a private I/O buffer for the 'core' subdrivers.  This
allows us to fix all cases of DMAing to/from the stacks, statics, or other
bad places.

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.719   -> 1.720  
#       drivers/usb/storage/usb.h       1.38    -> 1.39   
#       drivers/usb/storage/transport.c 1.87    -> 1.88   
#       drivers/usb/storage/usb.c       1.78    -> 1.79   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/06/28      [EMAIL PROTECTED]       1.720
# Switch to private I/O buffer for the 'core' subdrivers.  This fixes the
# problem of DMAing to/from the stack and other otherwise improper places.
# --------------------------------------------
#
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c   Sat Jun 28 20:32:11 2003
+++ b/drivers/usb/storage/transport.c   Sat Jun 28 20:32:11 2003
@@ -786,9 +786,9 @@
        }
 
        /* STATUS STAGE */
-       result = usb_stor_intr_transfer(us, us->irqdata, sizeof(us->irqdata));
+       result = usb_stor_intr_transfer(us, us->iobuf, 2);
        US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", 
-                       us->irqdata[0], us->irqdata[1]);
+                       us->iobuf[0], us->iobuf[1]);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
 
@@ -804,7 +804,7 @@
                    srb->cmnd[0] == INQUIRY)
                        return USB_STOR_TRANSPORT_GOOD;
                else {
-                       if (us->irqdata[0])
+                       if (us->iobuf[0])
                                return USB_STOR_TRANSPORT_FAILED;
                        else
                                return USB_STOR_TRANSPORT_GOOD;
@@ -815,13 +815,13 @@
         * The first byte should always be a 0x0
         * The second byte & 0x0F should be 0x0 for good, otherwise error 
         */
-       if (us->irqdata[0]) {
+       if (us->iobuf[0]) {
                US_DEBUGP("CBI IRQ data showed reserved bType %d\n",
-                               us->irqdata[0]);
+                               us->iobuf[0]);
                return USB_STOR_TRANSPORT_ERROR;
        }
 
-       switch (us->irqdata[1] & 0x0F) {
+       switch (us->iobuf[1] & 0x0F) {
                case 0x00: 
                        return USB_STOR_TRANSPORT_GOOD;
                case 0x01: 
@@ -889,7 +889,6 @@
 /* Determine what the maximum LUN supported is */
 int usb_stor_Bulk_max_lun(struct us_data *us)
 {
-       unsigned char data;
        int result;
 
        /* issue the command */
@@ -897,14 +896,14 @@
                                 US_BULK_GET_MAX_LUN, 
                                 USB_DIR_IN | USB_TYPE_CLASS | 
                                 USB_RECIP_INTERFACE,
-                                0, us->ifnum, &data, sizeof(data), HZ);
+                                0, us->ifnum, us->iobuf, 1, HZ);
 
        US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
-                 result, data);
+                 result, us->iobuf[0]);
 
        /* if we have a successful request, return the result */
        if (result == 1)
-               return data;
+               return us->iobuf[0];
 
        /* return the default -- no LUNs */
        return 0;
@@ -912,33 +911,34 @@
 
 int usb_stor_Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
 {
-       struct bulk_cb_wrap bcb;
-       struct bulk_cs_wrap bcs;
+       struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
+       struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
        unsigned int transfer_length = srb->request_bufflen;
        int result;
        int fake_sense = 0;
 
        /* set up the command wrapper */
-       bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
-       bcb.DataTransferLength = cpu_to_le32(transfer_length);
-       bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
-       bcb.Tag = srb->serial_number;
-       bcb.Lun = srb->device->lun;
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = cpu_to_le32(transfer_length);
+       bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
+       bcb->Tag = srb->serial_number;
+       bcb->Lun = srb->device->lun;
        if (us->flags & US_FL_SCM_MULT_TARG)
-               bcb.Lun |= srb->device->id << 4;
-       bcb.Length = srb->cmd_len;
+               bcb->Lun |= srb->device->id << 4;
+       bcb->Length = srb->cmd_len;
 
        /* copy the command payload */
-       memset(bcb.CDB, 0, sizeof(bcb.CDB));
-       memcpy(bcb.CDB, srb->cmnd, bcb.Length);
+       memset(bcb->CDB, 0, sizeof(bcb->CDB));
+       memcpy(bcb->CDB, srb->cmnd, bcb->Length);
 
        /* send it to out endpoint */
        US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
-                 le32_to_cpu(bcb.Signature), bcb.Tag,
-                 (bcb.Lun >> 4), (bcb.Lun & 0x0F), 
-                 le32_to_cpu(bcb.DataTransferLength), bcb.Flags, bcb.Length);
+                       le32_to_cpu(bcb->Signature), bcb->Tag,
+                       (bcb->Lun >> 4), (bcb->Lun & 0x0F), 
+                       le32_to_cpu(bcb->DataTransferLength),
+                       bcb->Flags, bcb->Length);
        result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
-                               &bcb, US_BULK_CB_WRAP_LEN, NULL);
+                               bcb, US_BULK_CB_WRAP_LEN, NULL);
        US_DEBUGP("Bulk command transfer result=%d\n", result);
        if (result != USB_STOR_XFER_GOOD)
                return USB_STOR_TRANSPORT_ERROR;
@@ -972,7 +972,7 @@
        /* get CSW for device status */
        US_DEBUGP("Attempting to get CSW...\n");
        result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-                               &bcs, US_BULK_CS_WRAP_LEN, NULL);
+                               bcs, US_BULK_CS_WRAP_LEN, NULL);
 
        /* did the attempt to read the CSW fail? */
        if (result == USB_STOR_XFER_STALLED) {
@@ -980,7 +980,7 @@
                /* get the status again */
                US_DEBUGP("Attempting to get CSW (2nd try)...\n");
                result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
-                               &bcs, US_BULK_CS_WRAP_LEN, NULL);
+                               bcs, US_BULK_CS_WRAP_LEN, NULL);
        }
 
        /* if we still have a failure at this point, we're in trouble */
@@ -990,17 +990,18 @@
 
        /* check bulk status */
        US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
-                 le32_to_cpu(bcs.Signature), bcs.Tag, 
-                 bcs.Residue, bcs.Status);
-       if ((bcs.Signature != cpu_to_le32(US_BULK_CS_SIGN) && bcs.Signature != 
cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) || 
-           bcs.Tag != bcb.Tag || 
-           bcs.Status > US_BULK_STAT_PHASE) {
+                       le32_to_cpu(bcs->Signature), bcs->Tag, 
+                       bcs->Residue, bcs->Status);
+       if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) &&
+                   bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) ||
+                       bcs->Tag != srb->serial_number || 
+                       bcs->Status > US_BULK_STAT_PHASE) {
                US_DEBUGP("Bulk logical error\n");
                return USB_STOR_TRANSPORT_ERROR;
        }
 
        /* based on the status code, we report good or bad */
-       switch (bcs.Status) {
+       switch (bcs->Status) {
                case US_BULK_STAT_OK:
                        /* device babbled -- return fake sense data */
                        if (fake_sense) {
@@ -1087,18 +1088,18 @@
 
 /* This issues a CB[I] Reset to the device in question
  */
+#define CB_RESET_CMD_SIZE      12
+
 int usb_stor_CB_reset(struct us_data *us)
 {
-       unsigned char cmd[12];
-
-       US_DEBUGP("CB_reset() called\n");
+       US_DEBUGP("%s called\n", __FUNCTION__);
 
-       memset(cmd, 0xFF, sizeof(cmd));
-       cmd[0] = SEND_DIAGNOSTIC;
-       cmd[1] = 4;
+       memset(us->iobuf, 0xFF, CB_RESET_CMD_SIZE);
+       us->iobuf[0] = SEND_DIAGNOSTIC;
+       us->iobuf[1] = 4;
        return usb_stor_reset_common(us, US_CBI_ADSC, 
                                 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-                                0, us->ifnum, cmd, sizeof(cmd));
+                                0, us->ifnum, us->iobuf, CB_RESET_CMD_SIZE);
 }
 
 /* This issues a Bulk-only Reset to the device in question, including
@@ -1106,7 +1107,7 @@
  */
 int usb_stor_Bulk_reset(struct us_data *us)
 {
-       US_DEBUGP("Bulk reset requested\n");
+       US_DEBUGP("%s called\n", __FUNCTION__);
 
        return usb_stor_reset_common(us, US_BULK_RESET_REQUEST, 
                                 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c Sat Jun 28 20:32:11 2003
+++ b/drivers/usb/storage/usb.c Sat Jun 28 20:32:11 2003
@@ -743,17 +743,21 @@
        int p;
 
        /* Allocate the USB control blocks */
-       US_DEBUGP("Allocating usb_ctrlrequest\n");
        us->dr = kmalloc(sizeof(*us->dr), GFP_KERNEL);
        if (!us->dr) {
-               US_DEBUGP("allocation failed\n");
+               US_DEBUGP("usb_ctrlrequest allocation failed\n");
                return -ENOMEM;
        }
 
-       US_DEBUGP("Allocating URB\n");
        us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!us->current_urb) {
-               US_DEBUGP("allocation failed\n");
+               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;
        }
 
@@ -852,6 +856,8 @@
        }
 
        /* Free the USB control blocks */
+       if (us->iobuf)
+               kfree(us->iobuf);
        if (us->current_urb)
                usb_free_urb(us->current_urb);
        if (us->dr)
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h Sat Jun 28 20:32:11 2003
+++ b/drivers/usb/storage/usb.h Sat Jun 28 20:32:11 2003
@@ -92,6 +92,8 @@
 
 #define USB_STOR_STRING_LEN 32
 
+#define US_IOBUF_SIZE          32      /* Big enough for bulk-only CBW */
+
 typedef int (*trans_cmnd)(Scsi_Cmnd*, struct us_data*);
 typedef int (*trans_reset)(struct us_data*);
 typedef void (*proto_cmnd)(Scsi_Cmnd*, struct us_data*);
@@ -139,13 +141,11 @@
        int                     pid;             /* control thread       */
        int                     sm_state;        /* what we are doing    */
 
-       /* interrupt communications data */
-       unsigned char           irqdata[2];      /* data from USB IRQ    */
-
        /* control and bulk communications data */
        struct urb              *current_urb;    /* non-int USB requests */
        struct usb_ctrlrequest  *dr;             /* control requests     */
        struct usb_sg_request   current_sg;      /* scatter-gather USB   */
+       unsigned char           *iobuf;          /* I/O buffer           */
 
        /* the semaphore for sleeping the control thread */
        struct semaphore        sema;            /* to sleep thread on   */
-- 
Matthew Dharm                              Home: [EMAIL PROTECTED] 
Maintainer, Linux USB Mass Storage Driver

You suck Stef.
                                        -- Greg 
User Friendly, 11/29/97

Attachment: pgp00000.pgp
Description: PGP signature

Reply via email to