Shouldn't we use pci_alloc_consistent (or indirectly via pci_pool_alloc)
instead of kmalloc?

-ch

> -----Original Message-----
> From: [EMAIL PROTECTED] 
> [mailto:[EMAIL PROTECTED]] On 
> Behalf Of Roland Dreier
> Sent: Friday, June 07, 2002 4:57 PM
> To: [EMAIL PROTECTED]; 
> [EMAIL PROTECTED]
> Subject: [linux-usb-devel] USB on PPC440GP (cache incoherent)
> Importance: High
> 
> 
> I just got USB working on my PPC440GP (IBM Ebony eval board). 
>  I'm using an Opti 82C861 OHCI controller, and so far I've 
> tried an Alcor SD card reader (mass storage) and a Belkin 
> usbnet device.  My kernel is 2.4.19-pre10 from the 
> bk://ppc.bkbits.net/linuxppc_2_4_devel
> BitKeeper tree.
> 
> I had to make some changes to the USB driver to get this 
> working as there are still some places where structures on 
> the stack are being used for DMA.  This causes problems on 
> processors like the 440GP, which are not cache coherent (you 
> can only invalidate a whole cache line, which can corrupt the 
> stack).  I just changed all of these places to use kmalloc to 
> get memory instead.
> 
> Note that this might not work perfectly on all 
> cache-incoherent processors, since kmalloc could potentially 
> allocate a chunk of memory that is smaller than the 
> processor's cache line size.  However it is safe on the 440GP 
> since the 440GP's cache line size is 32 bytes.
> 
> I've included a patch with my changes in this email.  I'm 
> sending it to the linuxppc-embedded list in case someone else 
> is trying to do USB on a 440 or 405 or similar processor.  
> I'm also sending it to linux-usb-devel in the hope that these 
> changes make it into the mainline kernel.
> 
> Best,
>   Roland
> 
> # This is a BitKeeper generated patch for the following 
> project: # Project Name: Linux 2.4 for PowerPC development 
> tree # This patch format is intended for GNU patch command 
> version 2.5 or higher. # This patch includes the following deltas:
> #                ChangeSet    1.1077  -> 1.1078 
> #        drivers/usb/usb.c    1.19    -> 1.20   
> #        drivers/usb/hub.c    1.14    -> 1.15   
> #        drivers/usb/hub.h    1.7     -> 1.8    
> #     drivers/usb/storage/transport.c 1.10    -> 1.11   
> #
> # The following is the BitKeeper ChangeSet Log
> # --------------------------------------------
> # 02/06/07    [EMAIL PROTECTED]      1.1078
> # Fix problems in USB when running on cache-incoherent cpus 
> like PPC440GP # (Don't do DMAs into memory allocated on 
> stack) # --------------------------------------------
> #
> diff -Nru a/drivers/usb/hub.c b/drivers/usb/hub.c
> --- a/drivers/usb/hub.c       Fri Jun  7 16:35:31 2002
> +++ b/drivers/usb/hub.c       Fri Jun  7 16:35:31 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,27 +258,36 @@
>  
>       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);
>       maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
>  
> -     if (maxp > sizeof(hub->buffer))
> -             maxp = sizeof(hub->buffer);
> +     if (maxp > USB_HUB_BUFFER_SIZE)
> +             maxp = USB_HUB_BUFFER_SIZE;
>  
>       hub->urb = usb_alloc_urb(0);
>       if (!hub->urb) {
> @@ -357,6 +366,13 @@
>  
>       memset(hub, 0, sizeof(*hub));
>  
> +        hub->buffer = kmalloc(USB_HUB_BUFFER_SIZE, GFP_KERNEL);
> +        if (!hub->buffer) {
> +                err("couldn't kmalloc hub->buffer");
> +                kfree(hub);
> +                return NULL;
> +        }
> +
>       INIT_LIST_HEAD(&hub->event_list);
>       hub->dev = dev;
>       init_MUTEX(&hub->khubd_sem);
> @@ -383,6 +399,7 @@
>  
>       spin_unlock_irqrestore(&hub_event_lock, flags);
>  
> +        kfree(hub->buffer);
>       kfree(hub);
>  
>       return NULL;
> @@ -417,6 +434,11 @@
>               hub->descriptor = NULL;
>       }
>  
> +        if (hub->buffer) {
> +                kfree(hub->buffer);
> +                hub->buffer = NULL;
> +        }
> +
>       /* Free the memory */
>       kfree(hub);
>  }
> @@ -782,7 +804,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,22 +894,28 @@
>               } /* 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 +1023,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 +1072,19 @@
>        * If nothing changed, we reprogram the configuration and then
>        * the alternate settings.
>        */
> -     ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &descriptor,
> -                     sizeof(descriptor));
> +        descriptor = kmalloc(sizeof *descriptor, GFP_KERNEL);
> +     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 +1113,7 @@
>  
>               return 1;
>       }
> +        kfree(descriptor);
>  
>       ret = usb_set_configuration(dev, 
> dev->actconfig->bConfigurationValue);
>       if (ret < 0) {
> diff -Nru a/drivers/usb/hub.h b/drivers/usb/hub.h
> --- a/drivers/usb/hub.h       Fri Jun  7 16:35:31 2002
> +++ b/drivers/usb/hub.h       Fri Jun  7 16:35:31 2002
> @@ -120,13 +120,15 @@
>  
>  struct usb_device;
>  
> +/* add 1 bit for hub status change and add 7 bits to round 
> up to byte 
> +boundary */ #define USB_HUB_BUFFER_SIZE ((USB_MAXCHILDREN + 
> 1 + 7) / 8)
> +
>  struct usb_hub {
>       struct usb_device *dev;
>  
>       struct urb *urb;                /* Interrupt polling pipe */
>  
> -     char buffer[(USB_MAXCHILDREN + 1 + 7) / 8]; /* add 1 
> bit for hub status change */
> -                                     /* and add 7 bits to 
> round up to byte boundary */
> +        char *buffer;
>       int error;
>       int nerrors;
>  
> diff -Nru a/drivers/usb/storage/transport.c 
> b/drivers/usb/storage/transport.c
> --- a/drivers/usb/storage/transport.c Fri Jun  7 16:35:31 2002
> +++ b/drivers/usb/storage/transport.c Fri Jun  7 16:35:31 2002
> @@ -723,7 +723,7 @@
>  
>               /* use the new buffer we have */
>               old_request_buffer = srb->request_buffer;
> -             srb->request_buffer = srb->sense_buffer;
> +             srb->request_buffer = kmalloc(18, 
> in_interrupt() ? GFP_ATOMIC : 
> +GFP_KERNEL);
>  
>               /* set the buffer length for transfer */
>               old_request_bufflen = srb->request_bufflen;
> @@ -733,8 +733,14 @@
>               old_sg = srb->use_sg;
>               srb->use_sg = 0;
>  
> -             /* issue the auto-sense command */
> -             temp_result = us->transport(us->srb, us);
> +                if (srb->request_buffer) {
> +                        /* issue the auto-sense command */
> +                        temp_result = us->transport(us->srb, us);
> +                        memcpy(srb->sense_buffer, 
> srb->request_buffer, 18);
> +                        kfree(srb->request_buffer);
> +                } else {
> +                        temp_result = USB_STOR_TRANSPORT_ERROR;
> +                }
>  
>               /* let's clean up right away */
>               srb->request_buffer = old_request_buffer;
> @@ -1041,9 +1047,12 @@
>  int usb_stor_Bulk_max_lun(struct us_data *us)
>  {
>       unsigned char data;
> +        unsigned char *buffer;
>       int result;
>       int pipe;
>  
> +        buffer = kmalloc(sizeof data, GFP_KERNEL);
> +
>       /* issue the command -- use usb_control_msg() because
>        *  the state machine is not yet alive */
>       pipe = usb_rcvctrlpipe(us->pusb_dev, 0);
> @@ -1051,7 +1060,9 @@
>                                US_BULK_GET_MAX_LUN, 
>                                USB_DIR_IN | USB_TYPE_CLASS | 
>                                USB_RECIP_INTERFACE,
> -                              0, us->ifnum, &data, sizeof(data), HZ);
> +                              0, us->ifnum, buffer, 
> sizeof(data), HZ);
> +        data = *buffer;
> +        kfree(buffer);
>  
>       US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
>                 result, data);
> @@ -1077,41 +1088,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_KERNEL);
> +        if (!bcb) {
> +                return USB_STOR_TRANSPORT_ERROR;
> +        }
> +        bcs = kmalloc(sizeof *bcs, in_interrupt() ? 
> GFP_ATOMIC : GFP_KERNEL);
> +        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 +1143,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 +1179,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 +1194,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 +1216,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;
> +                                goto out;
> +                        }
> +                     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;
>  }
>  
>  
> /*************************************************************
> **********
> diff -Nru a/drivers/usb/usb.c b/drivers/usb/usb.c
> --- a/drivers/usb/usb.c       Fri Jun  7 16:35:31 2002
> +++ b/drivers/usb/usb.c       Fri Jun  7 16:35:31 2002
> @@ -1787,16 +1787,23 @@
>  {
>       int i = 5;
>       int result;
> +        void *tmp_buf;
>       
> -     memset(buf,0,size);     // Make sure we parse really 
> received data
> +        tmp_buf = kmalloc(size, in_interrupt() ? GFP_ATOMIC 
> : GFP_KERNEL);
> +        if (!tmp_buf) {
> +          return -ENOMEM;
> +        }
> +     memset(tmp_buf,0,size); // Make sure we parse really 
> received data
>  
>       while (i--) {
>               if ((result = usb_control_msg(dev, 
> usb_rcvctrlpipe(dev, 0),
>                       USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
> -                     (type << 8) + index, 0, buf, size, HZ * 
> GET_TIMEOUT)) > 0 ||
> +                     (type << 8) + index, 0, tmp_buf, size, 
> HZ * GET_TIMEOUT)) > 0 ||
>                    result == -EPIPE)
>                       break;  /* retry if the returned length 
> was 0; flaky device */
>       }
> +        memcpy(buf, tmp_buf, size);
> +        kfree(tmp_buf);
>       return result;
>  }
>  
> 
> _______________________________________________________________
> 
> Don't miss the 2002 Sprint PCS Application Developer's 
> Conference August 25-28 in Las Vegas - 
> http://devcon.sprintpcs.com/adp/index.cfm?> source=osdntextlink
> 
> 
> _______________________________________________
> [EMAIL PROTECTED]
> To unsubscribe, use the last form field at: 
> https://lists.sourceforge.net/lists/listinfo/l> inux-usb-devel
> 


_______________________________________________________________

Don't miss the 2002 Sprint PCS Application Developer's Conference
August 25-28 in Las Vegas - 
http://devcon.sprintpcs.com/adp/index.cfm?source=osdntextlink

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

Reply via email to