On Thu, Mar 07, 2002 at 04:55:59PM -0800, Greg KH wrote:
> [EMAIL PROTECTED], 2002-03-07 16:46:43-08:00, [EMAIL PROTECTED]
>   USB
>   hcd-0305, periodic and pci fixup
>     
>         - removes the pci dependency you mentioned in the
>           rh_string code (friendlier to non-PCI HCs)
>         - makes code match doc (8859-1 chars, not just ascii)
>         - adds sanity checking for the periodic transfer interval,
>           and forces it to a power-of-two (code can leave HCDs)
>         - facilitates better IRQ sharing
> 
>  drivers/usb/hcd.c |   80 +++++++++++++++++++++++++++++++++++++++++-------------
>  drivers/usb/hcd.h |    2 -
>  2 files changed, 63 insertions(+), 19 deletions(-)


# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#                  ChangeSet    1.483   -> 1.484  
#          drivers/usb/hcd.h    1.2     -> 1.3    
#          drivers/usb/hcd.c    1.10    -> 1.11   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/03/07      [EMAIL PROTECTED]     1.484
# USB
# hcd-0305, periodic and pci fixup
#   
#       - removes the pci dependency you mentioned in the
#         rh_string code (friendlier to non-PCI HCs)
#       - makes code match doc (8859-1 chars, not just ascii)
#       - adds sanity checking for the periodic transfer interval,
#         and forces it to a power-of-two (code can leave HCDs)
#       - facilitates better IRQ sharing
# --------------------------------------------
#
diff -Nru a/drivers/usb/hcd.c b/drivers/usb/hcd.c
--- a/drivers/usb/hcd.c Thu Mar  7 17:02:39 2002
+++ b/drivers/usb/hcd.c Thu Mar  7 17:02:39 2002
@@ -224,12 +224,12 @@
  * helper routine for returning string descriptors in UTF-16LE
  * input can actually be ISO-8859-1; ASCII is its 7-bit subset
  */
-static int ascii2utf (char *ascii, u8 *utf, int utfmax)
+static int ascii2utf (char *s, u8 *utf, int utfmax)
 {
        int retval;
 
-       for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) {
-               *utf++ = *ascii++ & 0x7f;
+       for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) {
+               *utf++ = *s++;
                *utf++ = 0;
        }
        return retval;
@@ -248,8 +248,7 @@
  */
 static int rh_string (
        int             id,
-       struct pci_dev  *pci_desc,
-       char            *type,
+       struct usb_hcd  *hcd,
        u8              *data,
        int             len
 ) {
@@ -263,15 +262,16 @@
 
        // serial number
        } else if (id == 1) {
-               strcpy (buf, pci_desc->slot_name);
+               strcpy (buf, hcd->bus_name);
 
        // product description
        } else if (id == 2) {
-                strcpy (buf, pci_desc->name);
+                strcpy (buf, hcd->product_desc);
 
        // id 3 == vendor description
        } else if (id == 3) {
-                sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE, type);
+                sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE,
+                       hcd->description);
 
        // unsupported IDs --> "protocol stall"
        } else
@@ -338,9 +338,7 @@
                        break;
                case USB_DT_STRING << 8:
                        urb->actual_length = rh_string (
-                               wValue & 0xff,
-                                hcd->pdev,
-                               (char *) hcd->description,
+                               wValue & 0xff, hcd,
                                ubuf, wLength);
                        break;
                default:
@@ -1004,6 +1002,7 @@
        hcd->self.hcpriv = (void *) hcd;
        hcd->bus = &hcd->self;
        hcd->bus_name = dev->slot_name;
+       hcd->product_desc = dev->name;
 
        INIT_LIST_HEAD (&hcd->dev_list);
 
@@ -1266,7 +1265,7 @@
        struct usb_hcd          *hcd;
        struct hcd_dev          *dev;
        unsigned long           flags;
-       int                     pipe;
+       int                     pipe, temp;
 
        if (!urb || urb->hcpriv || !urb->complete)
                return -EINVAL;
@@ -1286,6 +1285,7 @@
        if (hcd->state == USB_STATE_QUIESCING || !HCD_IS_RUNNING (hcd->state))
                return -ESHUTDOWN;
        pipe = urb->pipe;
+       temp = usb_pipetype (urb->pipe);
        if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe),
                        usb_pipeout (pipe)))
                return -EPIPE;
@@ -1298,7 +1298,7 @@
        /* enforce simple/standard policy */
        allowed = USB_ASYNC_UNLINK;     // affects later unlinks
        allowed |= USB_NO_FSBR;         // only affects UHCI
-       switch (usb_pipetype (pipe)) {
+       switch (temp) {
        case PIPE_CONTROL:
                allowed |= USB_DISABLE_SPD;
                break;
@@ -1317,15 +1317,55 @@
 
        /* warn if submitter gave bogus flags */
        if (urb->transfer_flags != orig_flags)
-               warn ("BOGUS urb flags, %x --> %x",
+               err ("BOGUS urb flags, %x --> %x",
                        orig_flags, urb->transfer_flags);
        }
 #endif
        /*
-        * FIXME:  alloc periodic bandwidth here, for interrupt and iso?
-        * Need to look at the ring submit mechanism for iso tds ... they
-        * aren't actually "periodic" in 2.4 kernels.
+        * Force periodic transfer intervals to be legal values that are
+        * a power of two (so HCDs don't need to).
         *
+        * FIXME want bus->{intr,iso}_sched_horizon values here.  Each HC
+        * supports different values... this uses EHCI/UHCI defaults (and
+        * EHCI can use smaller non-default values).
+        */
+       switch (temp) {
+       case PIPE_ISOCHRONOUS:
+       case PIPE_INTERRUPT:
+               /* too small? */
+               if (urb->interval <= 0)
+                       return -EINVAL;
+               /* too big? */
+               switch (urb->dev->speed) {
+               case USB_SPEED_HIGH:    /* units are microframes */
+                       // NOTE usb handles 2^15
+                       if (urb->interval > (1024 * 8))
+                               urb->interval = 1024 * 8;
+                       temp = 1024 * 8;
+                       break;
+               case USB_SPEED_FULL:    /* units are frames/msec */
+               case USB_SPEED_LOW:
+                       if (temp == PIPE_INTERRUPT) {
+                               if (urb->interval > 255)
+                                       return -EINVAL;
+                               // NOTE ohci only handles up to 32
+                               temp = 128;
+                       } else {
+                               if (urb->interval > 1024)
+                                       urb->interval = 1024;
+                               // NOTE usb and ohci handle up to 2^15
+                               temp = 1024;
+                       }
+               default:
+                       return -EINVAL;
+               }
+               /* power of two? */
+               while (temp > urb->interval)
+                       temp >>= 1;
+               urb->interval = temp;
+       }
+
+       /*
         * FIXME:  make urb timeouts be generic, keeping the HCD cores
         * as simple as possible.
         */
@@ -1589,6 +1629,9 @@
        struct usb_hcd          *hcd = __hcd;
        int                     start = hcd->state;
 
+       if (unlikely (hcd->state == USB_STATE_HALT))    /* irq sharing? */
+               return;
+
        hcd->driver->irq (hcd);
        if (hcd->state != start && hcd->state == USB_STATE_HALT)
                hc_died (hcd);
@@ -1642,7 +1685,8 @@
        // hcd_monitor_hook(MONITOR_URB_UPDATE, urb, dev)
 
        if (urb->status)
-               dbg ("giveback urb %p status %d", urb, urb->status);
+               dbg ("giveback urb %p status %d len %d",
+                       urb, urb->status, urb->actual_length);
 
        /* if no error, make sure urb->next progresses */
        else if (urb->next) {
diff -Nru a/drivers/usb/hcd.h b/drivers/usb/hcd.h
--- a/drivers/usb/hcd.h Thu Mar  7 17:02:39 2002
+++ b/drivers/usb/hcd.h Thu Mar  7 17:02:39 2002
@@ -39,7 +39,7 @@
        struct usb_bus          self;           /* hcd is-a bus */
 
        const char              *bus_name;
-
+       const char              *product_desc;  /* product/vendor string */
        const char              *description;   /* "ehci-hcd" etc */
 
        struct timer_list       rh_timer;       /* drives root hub */

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

Reply via email to