Here is the non-controversial part of the patch I posted last week.
It just gets rid of a few places where DMA is done to variables on the
stack.  After discussion on lkml, I think we agreed that DMA into the
middle of kmalloc()'ed structs is wrong and should be fixed with
alignment macros.  I'll send out a separate patch to do that.

Patch is against 2.5.19-pre10.

Thanks,
  Roland

diff -Naur linux-2.4.19-pre10.orig/drivers/usb/hub.c 
linux-2.4.19-pre10/drivers/usb/hub.c
--- linux-2.4.19-pre10.orig/drivers/usb/hub.c   Wed Jun 12 15:08:56 2002
+++ linux-2.4.19-pre10/drivers/usb/hub.c        Wed Jun 12 15:16:28 2002
@@ -155,7 +155,7 @@
 static int usb_hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor 
*endpoint)
 {
        struct usb_device *dev = hub->dev;
-       struct usb_hub_status hubstatus;
+       struct usb_hub_status *hubstatus;
        char portstr[USB_MAXCHILDREN + 1];
        unsigned int pipe;
        int i, maxp, ret;
@@ -258,20 +258,29 @@
 
        dbg("port removable status: %s", portstr);
 
-       ret = usb_get_hub_status(dev, &hubstatus);
+       hubstatus = kmalloc(sizeof *hubstatus, GFP_KERNEL);
+       if (!hubstatus) {
+               err("Unable to allocate hubstatus");
+               kfree(hub->descriptor);
+               return -1;
+       }
+       ret = usb_get_hub_status(dev, hubstatus);
        if (ret < 0) {
                err("Unable to get hub status (err = %d)", ret);
+               kfree(hubstatus);
                kfree(hub->descriptor);
                return -1;
        }
 
-       le16_to_cpus(&hubstatus.wHubStatus);
+       le16_to_cpus(&hubstatus->wHubStatus);
 
        dbg("local power source is %s",
-               (hubstatus.wHubStatus & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : 
"good");
+               (hubstatus->wHubStatus & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : 
+"good");
 
        dbg("%sover-current condition exists",
-               (hubstatus.wHubStatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
+               (hubstatus->wHubStatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
+
+       kfree(hubstatus);
 
        /* Start the interrupt endpoint */
        pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
@@ -782,7 +791,7 @@
        struct list_head *tmp;
        struct usb_device *dev;
        struct usb_hub *hub;
-       struct usb_hub_status hubsts;
+       struct usb_hub_status *hubsts;
        u16 hubstatus;
        u16 hubchange;
        u16 portstatus;
@@ -872,21 +881,27 @@
                } /* end for i */
 
                /* deal with hub status changes */
-               if (usb_get_hub_status(dev, &hubsts) < 0)
-                       err("get_hub_status failed");
-               else {
-                       hubstatus = le16_to_cpup(&hubsts.wHubStatus);
-                       hubchange = le16_to_cpup(&hubsts.wHubChange);
-                       if (hubchange & HUB_CHANGE_LOCAL_POWER) {
-                               dbg("hub power change");
-                               usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
-                       }
-                       if (hubchange & HUB_CHANGE_OVERCURRENT) {
-                               dbg("hub overcurrent change");
-                               wait_ms(500);   /* Cool down */
-                               usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT);
-                               usb_hub_power_on(hub);
+               hubsts = kmalloc(sizeof *hubsts, GFP_KERNEL);
+               if (!hubsts) {
+                       err("couldn't allocate hubsts");
+               } else {
+                       if (usb_get_hub_status(dev, hubsts) < 0)
+                               err("get_hub_status failed");
+                       else {
+                               hubstatus = le16_to_cpup(&hubsts->wHubStatus);
+                               hubchange = le16_to_cpup(&hubsts->wHubChange);
+                               if (hubchange & HUB_CHANGE_LOCAL_POWER) {
+                                       dbg("hub power change");
+                                       usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
+                               }
+                               if (hubchange & HUB_CHANGE_OVERCURRENT) {
+                                       dbg("hub overcurrent change");
+                                       wait_ms(500);   /* Cool down */
+                                       usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT);
+                                       usb_hub_power_on(hub);
+                               }
                        }
+                       kfree(hubsts);
                }
                up(&hub->khubd_sem);
         } /* end while (1) */
@@ -995,7 +1010,7 @@
 int usb_reset_device(struct usb_device *dev)
 {
        struct usb_device *parent = dev->parent;
-       struct usb_device_descriptor descriptor;
+       struct usb_device_descriptor *descriptor;
        int i, ret, port = -1;
 
        if (!parent) {
@@ -1044,17 +1059,22 @@
         * If nothing changed, we reprogram the configuration and then
         * the alternate settings.
         */
+       descriptor = kmalloc(sizeof *descriptor, GFP_NOIO);
+       if (!descriptor) {
+               return -ENOMEM;
+       }
        ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &descriptor,
                        sizeof(descriptor));
        if (ret < 0)
                return ret;
 
-       le16_to_cpus(&descriptor.bcdUSB);
-       le16_to_cpus(&descriptor.idVendor);
-       le16_to_cpus(&descriptor.idProduct);
-       le16_to_cpus(&descriptor.bcdDevice);
+       le16_to_cpus(&descriptor->bcdUSB);
+       le16_to_cpus(&descriptor->idVendor);
+       le16_to_cpus(&descriptor->idProduct);
+       le16_to_cpus(&descriptor->bcdDevice);
 
-       if (memcmp(&dev->descriptor, &descriptor, sizeof(descriptor))) {
+       if (memcmp(&dev->descriptor, descriptor, sizeof(descriptor))) {
+               kfree(descriptor);
                usb_destroy_configuration(dev);
 
                ret = usb_get_device_descriptor(dev);
@@ -1083,6 +1103,8 @@
 
                return 1;
        }
+
+       kfree(descriptor);
 
        ret = usb_set_configuration(dev, dev->actconfig->bConfigurationValue);
        if (ret < 0) {
diff -Naur linux-2.4.19-pre10.orig/drivers/usb/storage/transport.c 
linux-2.4.19-pre10/drivers/usb/storage/transport.c
--- linux-2.4.19-pre10.orig/drivers/usb/storage/transport.c     Wed Jun 12 15:08:56 
2002
+++ linux-2.4.19-pre10/drivers/usb/storage/transport.c  Wed Jun 12 16:22:39 2002
@@ -1040,10 +1040,15 @@
 /* Determine what the maximum LUN supported is */
 int usb_stor_Bulk_max_lun(struct us_data *us)
 {
-       unsigned char data;
+       unsigned char *data;
        int result;
        int pipe;
 
+       data = kmalloc(sizeof *data, GFP_KERNEL);
+       if (!data) {
+               return 0;
+       }
+
        /* issue the command -- use usb_control_msg() because
         *  the state machine is not yet alive */
        pipe = usb_rcvctrlpipe(us->pusb_dev, 0);
@@ -1051,14 +1056,19 @@
                                 US_BULK_GET_MAX_LUN, 
                                 USB_DIR_IN | USB_TYPE_CLASS | 
                                 USB_RECIP_INTERFACE,
-                                0, us->ifnum, &data, sizeof(data), HZ);
+                                0, us->ifnum, data, sizeof(data), HZ);
 
        US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
-                 result, data);
+                 result, *data);
 
        /* if we have a successful request, return the result */
-       if (result == 1)
-               return data;
+       if (result == 1) {
+               result = *data;
+               kfree(data);
+               return result;
+       } else {
+               kfree(data);
+       }
 
        /* if we get a STALL, clear the stall */
        if (result == -EPIPE) {
@@ -1077,41 +1087,54 @@
 
 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_cs_wrap *bcs;
        int result;
        int pipe;
        int partial;
+       int ret = USB_STOR_TRANSPORT_ERROR;
+
+       bcb = kmalloc(sizeof *bcb, in_interrupt() ? GFP_ATOMIC : GFP_NOIO);
+       if (!bcb) {
+               return USB_STOR_TRANSPORT_ERROR;
+       }
+       bcs = kmalloc(sizeof *bcs, in_interrupt() ? GFP_ATOMIC : GFP_NOIO);
+       if (!bcs) {
+               kfree(bcb);
+               return USB_STOR_TRANSPORT_ERROR;
+       }
 
        /* set up the command wrapper */
-       bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN);
-       bcb.DataTransferLength = cpu_to_le32(usb_stor_transfer_length(srb));
-       bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
-       bcb.Tag = srb->serial_number;
-       bcb.Lun = srb->cmnd[1] >> 5;
+       bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
+       bcb->DataTransferLength = cpu_to_le32(usb_stor_transfer_length(srb));
+       bcb->Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
+       bcb->Tag = srb->serial_number;
+       bcb->Lun = srb->cmnd[1] >> 5;
        if (us->flags & US_FL_SCM_MULT_TARG)
-               bcb.Lun |= srb->target << 4;
-       bcb.Length = srb->cmd_len;
+               bcb->Lun |= srb->target << 4;
+       bcb->Length = srb->cmd_len;
 
        /* construct the pipe handle */
        pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
 
        /* 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), 
-                 bcb.DataTransferLength, bcb.Flags, bcb.Length);
-       result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN, 
+                 le32_to_cpu(bcb->Signature), bcb->Tag,
+                 (bcb->Lun >> 4), (bcb->Lun & 0x0F), 
+                 bcb->DataTransferLength, bcb->Flags, bcb->Length);
+       result = usb_stor_bulk_msg(us, bcb, pipe, US_BULK_CB_WRAP_LEN, 
                                   &partial);
        US_DEBUGP("Bulk command transfer result=%d\n", result);
 
        /* if the command was aborted, indicate that */
-       if (result == -ENOENT)
-               return USB_STOR_TRANSPORT_ABORTED;
+       if (result == -ENOENT) {
+               ret = USB_STOR_TRANSPORT_ABORTED;
+               goto out;
+       }
 
        /* if we stall, we need to clear it before we go on */
        if (result == -EPIPE) {
@@ -1119,25 +1142,30 @@
                result = usb_stor_clear_halt(us, pipe);
 
                /* if the command was aborted, indicate that */
-               if (result == -ENOENT)
-                       return USB_STOR_TRANSPORT_ABORTED;
+               if (result == -ENOENT) {
+                       ret = USB_STOR_TRANSPORT_ABORTED;
+                       goto out;
+               }
                result = -EPIPE;
        } else if (result) {
                /* unknown error -- we've got a problem */
-               return USB_STOR_TRANSPORT_ERROR;
+               ret = USB_STOR_TRANSPORT_ERROR;
+               goto out;
        }
 
        /* if the command transfered well, then we go to the data stage */
        if (result == 0) {
                /* send/receive data payload, if there is any */
-               if (bcb.DataTransferLength) {
+               if (bcb->DataTransferLength) {
                        usb_stor_transfer(srb, us);
                        result = srb->result;
                        US_DEBUGP("Bulk data transfer result 0x%x\n", result);
 
                        /* if it was aborted, we need to indicate that */
-                       if (result == US_BULK_TRANSFER_ABORTED)
-                               return USB_STOR_TRANSPORT_ABORTED;
+                       if (result == US_BULK_TRANSFER_ABORTED) {
+                               ret = USB_STOR_TRANSPORT_ABORTED;
+                               goto out;
+                       }
                }
        }
 
@@ -1150,12 +1178,14 @@
 
        /* get CSW for device status */
        US_DEBUGP("Attempting to get CSW...\n");
-       result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN, 
+       result = usb_stor_bulk_msg(us, bcs, pipe, US_BULK_CS_WRAP_LEN, 
                                   &partial);
 
        /* if the command was aborted, indicate that */
-       if (result == -ENOENT)
-               return USB_STOR_TRANSPORT_ABORTED;
+       if (result == -ENOENT) {
+               ret = USB_STOR_TRANSPORT_ABORTED;
+               goto out;
+       }
 
        /* did the attempt to read the CSW fail? */
        if (result == -EPIPE) {
@@ -1163,17 +1193,21 @@
                result = usb_stor_clear_halt(us, pipe);
 
                /* if the command was aborted, indicate that */
-               if (result == -ENOENT)
-                       return USB_STOR_TRANSPORT_ABORTED;
+               if (result == -ENOENT) {
+                       ret = USB_STOR_TRANSPORT_ABORTED;
+                       goto out;
+               }
 
                /* get the status again */
                US_DEBUGP("Attempting to get CSW (2nd try)...\n");
-               result = usb_stor_bulk_msg(us, &bcs, pipe,
+               result = usb_stor_bulk_msg(us, bcs, pipe,
                                           US_BULK_CS_WRAP_LEN, &partial);
 
                /* if the command was aborted, indicate that */
-               if (result == -ENOENT)
-                       return USB_STOR_TRANSPORT_ABORTED;
+               if (result == -ENOENT) {
+                       ret = USB_STOR_TRANSPORT_ABORTED;
+                       goto out;
+               }
 
                /* if it fails again, we need a reset and return an error*/
                if (result == -EPIPE) {
@@ -1181,48 +1215,60 @@
                        result = usb_stor_clear_halt(us, pipe);
 
                        /* if the command was aborted, indicate that */
-                       if (result == -ENOENT)
-                               return USB_STOR_TRANSPORT_ABORTED;
-                       return USB_STOR_TRANSPORT_ERROR;
+                       if (result == -ENOENT) {
+                               ret = USB_STOR_TRANSPORT_ABORTED;
+                       } else {
+                               ret = USB_STOR_TRANSPORT_ERROR;
+                       }
+                       goto out;
                }
        }
 
        /* if we still have a failure at this point, we're in trouble */
        US_DEBUGP("Bulk status result = %d\n", result);
        if (result) {
-               return USB_STOR_TRANSPORT_ERROR;
+               ret = USB_STOR_TRANSPORT_ERROR;
+               goto out;
        }
 
        /* 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.Tag != bcb.Tag || 
-           bcs.Status > US_BULK_STAT_PHASE || partial != 13) {
+                 le32_to_cpu(bcs->Signature), bcs->Tag, 
+                 bcs->Residue, bcs->Status);
+       if (bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) || 
+           bcs->Tag != bcb->Tag || 
+           bcs->Status > US_BULK_STAT_PHASE || partial != 13) {
                US_DEBUGP("Bulk logical error\n");
-               return USB_STOR_TRANSPORT_ERROR;
+               ret = USB_STOR_TRANSPORT_ERROR;
+               goto out;
        }
 
        /* based on the status code, we report good or bad */
-       switch (bcs.Status) {
+       switch (bcs->Status) {
                case US_BULK_STAT_OK:
                        /* command good -- note that data could be short */
-                       return USB_STOR_TRANSPORT_GOOD;
+                       ret = USB_STOR_TRANSPORT_GOOD;
+                       goto out;
 
                case US_BULK_STAT_FAIL:
                        /* command failed */
-                       return USB_STOR_TRANSPORT_FAILED;
+                       ret = USB_STOR_TRANSPORT_FAILED;
+                       goto out;
 
                case US_BULK_STAT_PHASE:
                        /* phase error -- note that a transport reset will be
                         * invoked by the invoke_transport() function
                         */
-                       return USB_STOR_TRANSPORT_ERROR;
+                       ret = USB_STOR_TRANSPORT_ERROR;
+                       goto out;
        }
 
        /* we should never get here, but if we do, we're in trouble */
-       return USB_STOR_TRANSPORT_ERROR;
+
+ out:
+       kfree(bcb);
+       kfree(bcs);
+       return ret;
 }
 
 /***********************************************************************

_______________________________________________________________

Sponsored by:
ThinkGeek at http://www.ThinkGeek.com/
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to