# 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.643   -> 1.644  
#       drivers/usb/host/ohci-hcd.c     1.18    -> 1.19   
#       drivers/usb/host/ohci-sa1111.c  1.1     -> 1.2    
#       drivers/usb/host/ohci-dbg.c     1.7     -> 1.8    
#       drivers/usb/host/ohci-q.c       1.12    -> 1.13   
#       drivers/usb/host/ohci.h 1.8     -> 1.9    
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/07/15      [EMAIL PROTECTED]     1.644
# [PATCH] ohci misc
# 
# This patch  includes the innocuous bits from a larger one that
# I'm still working on (mostly unlink fixes):
# 
# - updates comments
# - flags TDs that were seen in the donelist
# - removes some bogus whitespace (at EOL etc) and tabs
# - checks for an enumeration issue that might cause trouble
# - delays IRQs a bit more aggressively
# - shortens TD submit paths a smidgeon (smaller ".o")
# - updates some of the debug output
# - sanitizes usb_make_path() output on the SA-1111
# --------------------------------------------
#
diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
--- a/drivers/usb/host/ohci-dbg.c       Mon Jul 15 18:05:00 2002
+++ b/drivers/usb/host/ohci-dbg.c       Mon Jul 15 18:05:00 2002
@@ -12,13 +12,14 @@
  
 #ifdef DEBUG
 
-#define pipestring(pipe) ({ char *temp; \
-       switch (usb_pipetype (pipe)) { \
+#define edstring(ed_type) ({ char *temp; \
+       switch (ed_type) { \
        case PIPE_CONTROL:      temp = "CTRL"; break; \
        case PIPE_BULK:         temp = "BULK"; break; \
        case PIPE_INTERRUPT:    temp = "INTR"; break; \
        default:                temp = "ISOC"; break; \
        }; temp;})
+#define pipestring(pipe) edstring(usb_pipetype(pipe))
 
 /* debug| print the main components of an URB     
  * small: 0) header + data packets 1) just header
@@ -35,9 +36,9 @@
 #ifndef        OHCI_VERBOSE_DEBUG
        if (urb->status != 0)
 #endif
-       dbg("%s:[%4x] dev:%d,ep=%d-%c,%s,flags:%4x,len:%d/%d,stat:%d", 
+       dbg("%s %p dev:%d,ep=%d-%c,%s,flags:%x,len:%d/%d,stat:%d", 
                    str,
-                   usb_get_current_frame_number (urb->dev), 
+                   urb,
                    usb_pipedevice (pipe),
                    usb_pipeendpoint (pipe), 
                    usb_pipeout (pipe)? 'O': 'I',
@@ -242,21 +243,25 @@
        ohci_dump_roothub (controller, 1);
 }
 
+static const char data0 [] = "DATA0";
+static const char data1 [] = "DATA1";
+
 static void ohci_dump_td (char *label, struct td *td)
 {
        u32     tmp = le32_to_cpup (&td->hwINFO);
 
-       dbg ("%s td %p; urb %p index %d; hw next td %08x",
+       dbg ("%s td %p%s; urb %p index %d; hw next td %08x",
                label, td,
+               (tmp & TD_DONE) ? " (DONE)" : "",
                td->urb, td->index,
                le32_to_cpup (&td->hwNextTD));
        if ((tmp & TD_ISO) == 0) {
-               char    *toggle, *pid;
+               const char      *toggle, *pid;
                u32     cbp, be;
 
                switch (tmp & TD_T) {
-               case TD_T_DATA0: toggle = "DATA0"; break;
-               case TD_T_DATA1: toggle = "DATA1"; break;
+               case TD_T_DATA0: toggle = data0; break;
+               case TD_T_DATA1: toggle = data1; break;
                case TD_T_TOGGLE: toggle = "(CARRY)"; break;
                default: toggle = "(?)"; break;
                }
@@ -297,9 +302,9 @@
        u32     tmp = ed->hwINFO;
        char    *type = "";
 
-       dbg ("%s: %s, ed %p state 0x%x type %d; next ed %08x",
+       dbg ("%s: %s, ed %p state 0x%x type %s; next ed %08x",
                ohci->hcd.self.bus_name, label,
-               ed, ed->state, ed->type,
+               ed, ed->state, edstring (ed->type),
                le32_to_cpup (&ed->hwNextED));
        switch (tmp & (ED_IN|ED_OUT)) {
        case ED_OUT: type = "-OUT"; break;
@@ -314,10 +319,10 @@
                0x000f & (le32_to_cpu (tmp) >> 7),
                type,
                0x007f & le32_to_cpu (tmp));
-       dbg ("  tds: head %08x%s%s tail %08x%s",
+       dbg ("  tds: head %08x %s%s tail %08x%s",
                tmp = le32_to_cpup (&ed->hwHeadP),
+               (ed->hwHeadP & ED_C) ? data1 : data0,
                (ed->hwHeadP & ED_H) ? " HALT" : "",
-               (ed->hwHeadP & ED_C) ? " CARRY" : "",
                le32_to_cpup (&ed->hwTailP),
                verbose ? "" : " (not listing)");
        if (verbose) {
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c       Mon Jul 15 18:05:00 2002
+++ b/drivers/usb/host/ohci-hcd.c       Mon Jul 15 18:05:00 2002
@@ -197,7 +197,7 @@
 
        /* allocate the TDs (updating hash chains) */
        spin_lock_irqsave (&ohci->lock, flags);
-       for (i = 0; i < size; i++) { 
+       for (i = 0; i < size; i++) {
                urb_priv->td [i] = td_alloc (ohci, SLAB_ATOMIC);
                if (!urb_priv->td [i]) {
                        urb_priv->length = i;
@@ -208,6 +208,8 @@
        }       
 
 // FIXME:  much of this switch should be generic, move to hcd code ...
+// ... and what's not generic can't really be handled this way.
+// need to consider periodicity for both types!
 
        /* allocate and claim bandwidth if needed; ISO
         * needs start frame index if it was't provided.
@@ -247,14 +249,14 @@
 
        spin_unlock_irqrestore (&ohci->lock, flags);
 
-       return 0;       
+       return 0;
 }
 
 /*
  * decouple the URB from the HC queues (TDs, urb_priv); it's
- * already marked for deletion.  reporting is always done
+ * already marked using urb->status.  reporting is always done
  * asynchronously, and we might be dealing with an urb that's
- * almost completed anyway...
+ * partially transferred, or an ED with other urbs being unlinked.
  */
 static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
 {
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c Mon Jul 15 18:05:00 2002
+++ b/drivers/usb/host/ohci-q.c Mon Jul 15 18:05:00 2002
@@ -465,6 +465,25 @@
                 * we know it's already a power of 2
                 */
                ed->interval = interval;
+#ifdef DEBUG
+       /*
+        * There are two other cases we ought to change hwINFO, both during
+        * enumeration.  There, the control request completes, unlinks, and
+        * the next request gets queued before the unlink completes, so it
+        * uses old/wrong hwINFO.  How much of a problem is this?  khubd is
+        * already retrying after such failures...
+        */
+       } else if (type == PIPE_CONTROL) {
+               u32     info = le32_to_cpup (&ed->hwINFO);
+
+               if (!(info & 0x7f))
+                       dbg ("RETRY ctrl: address != 0");
+               info >>= 16;
+               if (info != udev->epmaxpacketin [0])
+                       dbg ("RETRY ctrl: maxpacket %d != 8",
+                               udev->epmaxpacketin [0]);
+
+#endif /* DEBUG */
        }
 
 done:
@@ -539,12 +558,15 @@
 
        /* aim for only one interrupt per urb.  mostly applies to control
         * and iso; other urbs rarely need more than one TD per urb.
+        * this way, only final tds (or ones with an error) cause IRQs.
         *
         * NOTE: could delay interrupts even for the last TD, and get fewer
         * interrupts ... increasing per-urb latency by sharing interrupts.
+        * Drivers that queue bulk urbs may request that behavior.
         */
-       if (index != (urb_priv->length - 1))
-               info |= is_iso ? TD_DI_SET (7) : TD_DI_SET (1);
+       if (index != (urb_priv->length - 1)
+                       || (urb->transfer_flags & URB_NO_INTERRUPT))
+               info |= TD_DI_SET (7);
 
        /* use this td as the next dummy */
        td_pt = urb_priv->td [index];
@@ -565,6 +587,7 @@
        td->hwINFO = cpu_to_le32 (info);
        if (is_iso) {
                td->hwCBP = cpu_to_le32 (data & 0xFFFFF000);
+               td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000);
                td->ed->intriso.last_iso = info & 0xffff;
        } else {
                td->hwCBP = cpu_to_le32 (data); 
@@ -574,7 +597,6 @@
        else
                td->hwBE = 0;
        td->hwNextTD = cpu_to_le32 (td_pt->td_dma);
-       td->hwPSW [0] = cpu_to_le16 ((data & 0x0FFF) | 0xE000);
 
        /* HC might read the TD right after we link it ... */
        wmb ();
@@ -596,17 +618,17 @@
        int             cnt = 0; 
        __u32           info = 0;
        unsigned int    toggle = 0;
+       int             is_out = usb_pipeout (urb->pipe);
 
        /* OHCI handles the DATA-toggles itself, we just use the
         * USB-toggle bits for resetting
         */
-       if (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-                       usb_pipeout (urb->pipe))) {
+       if (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe), is_out)) {
                toggle = TD_T_TOGGLE;
        } else {
                toggle = TD_T_DATA0;
                usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-                       usb_pipeout (urb->pipe), 1);
+                       is_out, 1);
        }
 
        urb_priv->td_cnt = 0;
@@ -614,9 +636,9 @@
        if (data_len) {
                data = pci_map_single (ohci->hcd.pdev,
                                       urb->transfer_buffer, data_len,
-                                      usb_pipeout (urb->pipe)
-                                      ? PCI_DMA_TODEVICE
-                                      : PCI_DMA_FROMDEVICE);
+                                      is_out
+                                              ? PCI_DMA_TODEVICE
+                                              : PCI_DMA_FROMDEVICE);
        } else
                data = 0;
 
@@ -625,18 +647,20 @@
         */
        switch (usb_pipetype (urb->pipe)) {
                case PIPE_BULK:
-                       info = usb_pipeout (urb->pipe)
+                       info = is_out
                                ? TD_CC | TD_DP_OUT
                                : TD_CC | TD_DP_IN ;
+                       /* TDs _could_ transfer up to 8K each */
                        while (data_len > 4096) {               
                                td_fill (ohci,
                                        info | (cnt? TD_T_TOGGLE:toggle),
                                        data, 4096, urb, cnt);
                                data += 4096; data_len -= 4096; cnt++;
                        }
-                       info = usb_pipeout (urb->pipe)?
-                               TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
-                       td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle),
+                       /* maybe avoid ED halt on final TD short read */
+                       if (!(urb->transfer_flags & USB_DISABLE_SPD))
+                               info |= TD_R;
+                       td_fill (ohci, info | (cnt ? TD_T_TOGGLE : toggle),
                                data, data_len, urb, cnt);
                        cnt++;
                        if ((urb->transfer_flags & USB_ZERO_PACKET)
@@ -653,8 +677,11 @@
                        break;
 
                case PIPE_INTERRUPT:
+                       /* current policy:  only one TD per request.
+                        * otherwise identical to bulk, except for BLF
+                        */
                        info = TD_CC | toggle;
-                       info |= usb_pipeout (urb->pipe) 
+                       info |= is_out
                                ?  TD_DP_OUT
                                :  TD_R | TD_DP_IN;
                        td_fill (ohci, info, data, data_len, urb, cnt++);
@@ -670,14 +697,12 @@
                                 8, urb, cnt++); 
                        if (data_len > 0) {  
                                info = TD_CC | TD_R | TD_T_DATA1;
-                               info |= usb_pipeout (urb->pipe)
-                                   ? TD_DP_OUT
-                                   : TD_DP_IN;
+                               info |= is_out ? TD_DP_OUT : TD_DP_IN;
                                /* NOTE:  mishandles transfers >8K, some >4K */
                                td_fill (ohci, info, data, data_len,
                                                urb, cnt++);  
                        } 
-                       info = usb_pipeout (urb->pipe)
+                       info = is_out
                                ? TD_CC | TD_DP_IN | TD_T_DATA1
                                : TD_CC | TD_DP_OUT | TD_T_DATA1;
                        td_fill (ohci, info, data, 0, urb, cnt++);
@@ -806,10 +831,13 @@
        while (td_list_hc) {            
                td_list = dma_to_td (ohci, td_list_hc);
 
+               td_list->hwINFO |= cpu_to_le32 (TD_DONE);
+
                if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) {
                        urb_priv = (urb_priv_t *) td_list->urb->hcpriv;
-                       /* typically the endpoint halts on error; un-halt,
-                        * and maybe dequeue other TDs from this urb
+                       /* Non-iso endpoints can halt on error; un-halt,
+                        * and dequeue any other TDs from this urb.
+                        * No other TD could have caused the halt.
                         */
                        if (td_list->ed->hwHeadP & ED_H) {
                                if (urb_priv && ((td_list->index + 1)
diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
--- a/drivers/usb/host/ohci-sa1111.c    Mon Jul 15 18:05:00 2002
+++ b/drivers/usb/host/ohci-sa1111.c    Mon Jul 15 18:05:00 2002
@@ -175,7 +175,7 @@
        usb_bus_init (&hcd->self);
        hcd->self.op = &usb_hcd_operations;
        hcd->self.hcpriv = (void *) hcd;
-       hcd->self.bus_name = "SA-1111";
+       hcd->self.bus_name = "sa1111";
        hcd->product_desc = "SA-1111 OHCI";
 
        INIT_LIST_HEAD (&hcd->dev_list);
diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
--- a/drivers/usb/host/ohci.h   Mon Jul 15 18:05:00 2002
+++ b/drivers/usb/host/ohci.h   Mon Jul 15 18:05:00 2002
@@ -11,6 +11,9 @@
 /*
  * OHCI Endpoint Descriptor (ED) ... holds TD queue
  * See OHCI spec, section 4.2
+ *
+ * This is a "Queue Head" for those transfers, which is why
+ * both EHCI and UHCI call similar structures a "QH".
  */
 struct ed {
        /* first fields are hardware-specified, le32 */
@@ -74,8 +77,8 @@
        /* these two bits are available for definition/use by HCDs in both
         * general and iso tds ... others are available for only one type
         */
-//#define TD____           0x00020000
-#define TD_ISO     0x00010000                  /* copy of ED_ISO */
+#define TD_DONE     0x00020000                 /* retired to donelist */
+#define TD_ISO      0x00010000                 /* copy of ED_ISO */
 
        /* hwINFO bits for general tds: */
 #define TD_EC       0x0C000000                 /* error count */
@@ -349,12 +352,14 @@
         struct device          *parent_dev;
 
        /*
-        * I/O memory used to communicate with the HC (uncached);
+        * I/O memory used to communicate with the HC (dma-consistent)
         */
        struct ohci_regs        *regs;
 
        /*
-        * main memory used to communicate with the HC (uncached)
+        * main memory used to communicate with the HC (dma-consistent).
+        * hcd adds to schedule for a live hc any time, but removals finish
+        * only at the start of the next frame.
         */
        struct ohci_hcca        *hcca;
        dma_addr_t              hcca_dma;
@@ -365,6 +370,9 @@
        struct ed               *ed_controltail;        /* last in ctrl list */
        struct ed               *ed_isotail;            /* last in iso list */
 
+       /*
+        * memory management for queue data structures
+        */
        struct pci_pool         *td_cache;
        struct pci_pool         *ed_cache;
        struct hash_list_t      td_hash [TD_HASH_SIZE];
@@ -380,6 +388,7 @@
 
        unsigned long           flags;          /* for HC bugs */
 #define        OHCI_QUIRK_AMD756       0x01                    /* erratum #4 */
+       // there are also chip quirks/bugs in init logic
 
        /*
         * framework state


-------------------------------------------------------
This sf.net email is sponsored by: Jabber - The world's fastest growing 
real-time communications platform! Don't just IM. Build it in! 
http://www.jabber.com/osdn/xim
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to