Michael:

In the absence of any suggestions, we might as well try to verify my 
idea about what's going wrong.  The patch below adds a little more 
debugging information; please try repeating the last test with this 
patch in place of the previous one.

Alan Stern



Index: usb-4.3/drivers/usb/core/devio.c
===================================================================
--- usb-4.3.orig/drivers/usb/core/devio.c
+++ usb-4.3/drivers/usb/core/devio.c
@@ -100,6 +100,11 @@ static bool usbfs_snoop;
 module_param(usbfs_snoop, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic");
 
+static unsigned usbfs_snoop_max = 65536;
+module_param(usbfs_snoop_max, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(usbfs_snoop_max,
+               "maximum number of bytes to print while snooping");
+
 #define snoop(dev, format, arg...)                             \
        do {                                                    \
                if (usbfs_snoop)                                \
@@ -392,6 +397,7 @@ static void snoop_urb(struct usb_device
                                        ep, t, d, length, timeout_or_status);
        }
 
+       data_len = min(data_len, usbfs_snoop_max);
        if (data && data_len > 0) {
                print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, 32, 1,
                        data, data_len, 1);
@@ -402,7 +408,8 @@ static void snoop_urb_data(struct urb *u
 {
        int i, size;
 
-       if (!usbfs_snoop)
+       len = min(len, usbfs_snoop_max);
+       if (!usbfs_snoop || len == 0)
                return;
 
        if (urb->num_sgs == 0) {
@@ -510,7 +517,9 @@ static void async_completed(struct urb *
                cred = get_cred(as->cred);
                secid = as->secid;
        }
-       snoop(&urb->dev->dev, "urb complete\n");
+       if (urb->actual_length == 0 && urb->transfer_buffer_length == 16384)
+               urb->actual_length = 16;
+       snoop(&urb->dev->dev, "urb complete %p\n", as->urb);
        snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length,
                        as->status, COMPLETE, NULL, 0);
        if ((urb->transfer_flags & URB_DIR_MASK) == URB_DIR_IN)
@@ -1372,9 +1381,9 @@ static int proc_do_submiturb(struct usb_
                        uurb->type = USBDEVFS_URB_TYPE_INTERRUPT;
                        goto interrupt_urb;
                }
-               num_sgs = DIV_ROUND_UP(uurb->buffer_length, USB_SG_SIZE);
-               if (num_sgs == 1 || num_sgs > ps->dev->bus->sg_tablesize)
-                       num_sgs = 0;
+//             num_sgs = DIV_ROUND_UP(uurb->buffer_length, USB_SG_SIZE);
+//             if (num_sgs == 1 || num_sgs > ps->dev->bus->sg_tablesize)
+//                     num_sgs = 0;
                if (ep->streams)
                        stream_id = uurb->stream_id;
                break;
@@ -1490,14 +1499,15 @@ static int proc_do_submiturb(struct usb_
                                ret = -EFAULT;
                                goto error;
                        }
-               } else if (uurb->type == USBDEVFS_URB_TYPE_ISO) {
+//             } else if (uurb->type == USBDEVFS_URB_TYPE_ISO) {
+               } else {
                        /*
                         * Isochronous input data may end up being
                         * discontiguous if some of the packets are short.
                         * Clear the buffer so that the gaps don't leak
                         * kernel data to userspace.
                         */
-                       memset(as->urb->transfer_buffer, 0,
+                       memset(as->urb->transfer_buffer, 0x55,
                                        uurb->buffer_length);
                }
        }
@@ -1554,6 +1564,7 @@ static int proc_do_submiturb(struct usb_
        as->pid = get_pid(task_pid(current));
        as->cred = get_current_cred();
        security_task_getsecid(current, &as->secid);
+       snoop(&ps->dev->dev, "urb submit %p\n", as->urb);
        snoop_urb(ps->dev, as->userurb, as->urb->pipe,
                        as->urb->transfer_buffer_length, 0, SUBMIT,
                        NULL, 0);
@@ -1709,8 +1720,12 @@ static struct async *reap_as(struct usb_
 static int proc_reapurb(struct usb_dev_state *ps, void __user *arg)
 {
        struct async *as = reap_as(ps);
+
        if (as) {
-               int retval = processcompl(as, (void __user * __user *)arg);
+               int retval;
+
+               snoop(&ps->dev->dev, "%s: REAP %p\n", __func__, as->userurb);
+               retval = processcompl(as, (void __user * __user *)arg);
                free_async(as);
                return retval;
        }
@@ -1726,6 +1741,7 @@ static int proc_reapurbnonblock(struct u
 
        as = async_getcompleted(ps);
        if (as) {
+               snoop(&ps->dev->dev, "%s: REAP %p\n", __func__, as->userurb);
                retval = processcompl(as, (void __user * __user *)arg);
                free_async(as);
        } else {
@@ -1852,8 +1868,12 @@ static int processcompl_compat(struct as
 static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg)
 {
        struct async *as = reap_as(ps);
+
        if (as) {
-               int retval = processcompl_compat(as, (void __user * __user 
*)arg);
+               int retval;
+
+               snoop(&ps->dev->dev, "%s: REAP %p\n", __func__, as->userurb);
+               retval = processcompl_compat(as, (void __user * __user *)arg);
                free_async(as);
                return retval;
        }
@@ -1869,6 +1889,7 @@ static int proc_reapurbnonblock_compat(s
 
        as = async_getcompleted(ps);
        if (as) {
+               snoop(&ps->dev->dev, "%s: REAP %p\n", __func__, as->userurb);
                retval = processcompl_compat(as, (void __user * __user *)arg);
                free_async(as);
        } else {
@@ -2273,7 +2294,7 @@ static long usbdev_do_ioctl(struct file
 #endif
 
        case USBDEVFS_DISCARDURB:
-               snoop(&dev->dev, "%s: DISCARDURB\n", __func__);
+               snoop(&dev->dev, "%s: DISCARDURB %p\n", __func__, p);
                ret = proc_unlinkurb(ps, p);
                break;
 
Index: usb-4.3/drivers/usb/host/ehci-dbg.c
===================================================================
--- usb-4.3.orig/drivers/usb/host/ehci-dbg.c
+++ usb-4.3/drivers/usb/host/ehci-dbg.c
@@ -436,7 +436,8 @@ static void qh_lines (
        scratch = hc32_to_cpup(ehci, &hw->hw_info1);
        hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &hw->hw_current) : 0;
        temp = scnprintf (next, size,
-                       "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)",
+                       "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)"
+                       " [cur %08x next %08x buf %08x]",
                        qh, scratch & 0x007f,
                        speed_char (scratch),
                        (scratch >> 8) & 0x000f,
@@ -444,7 +445,10 @@ static void qh_lines (
                        hc32_to_cpup(ehci, &hw->hw_token), mark,
                        (cpu_to_hc32(ehci, QTD_TOGGLE) & hw->hw_token)
                                ? "data1" : "data0",
-                       (hc32_to_cpup(ehci, &hw->hw_alt_next) >> 1) & 0x0f);
+                       (hc32_to_cpup(ehci, &hw->hw_alt_next) >> 1) & 0x0f,
+                       hc32_to_cpup(ehci, &hw->hw_current),
+                       hc32_to_cpup(ehci, &hw->hw_qtd_next),
+                       hc32_to_cpup(ehci, &hw->hw_buf[0]));
        size -= temp;
        next += temp;
 
@@ -464,7 +468,8 @@ static void qh_lines (
                                mark = '/';
                }
                temp = snprintf (next, size,
-                               "\n\t%p%c%s len=%d %08x urb %p",
+                               "\n\t%p%c%s len=%d %08x urb %p"
+                               " [td %08x buf %08x]",
                                td, mark, ({ char *tmp;
                                 switch ((scratch>>8)&0x03) {
                                 case 0: tmp = "out"; break;
@@ -474,7 +479,9 @@ static void qh_lines (
                                 } tmp;}),
                                (scratch >> 16) & 0x7fff,
                                scratch,
-                               td->urb);
+                               td->urb,
+                               (u32) td->qtd_dma,
+                               hc32_to_cpup(ehci, &td->hw_buf[0]));
                if (size < temp)
                        temp = size;
                size -= temp;
Index: usb-4.3/drivers/usb/host/ehci-q.c
===================================================================
--- usb-4.3.orig/drivers/usb/host/ehci-q.c
+++ usb-4.3/drivers/usb/host/ehci-q.c
@@ -132,10 +132,14 @@ qh_refresh (struct ehci_hcd *ehci, struc
         * qtd is updated in qh_completions(). Update the QH
         * overlay here.
         */
-       if (qh->hw->hw_token & ACTIVE_BIT(ehci))
+       if (qh->hw->hw_token & ACTIVE_BIT(ehci)) {
                qh->hw->hw_qtd_next = qtd->hw_next;
+               if (qh->should_be_inactive)
+                       ehci_info(ehci, "qh %p should be inactive!\n", qh);
+       }
        else
                qh_update(ehci, qh, qtd);
+       qh->should_be_inactive = 0;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -438,6 +442,7 @@ qh_completions (struct ehci_hcd *ehci, s
                                        (hw->hw_token & ACTIVE_BIT(ehci))) {
                                token = hc32_to_cpu(ehci, hw->hw_token);
                                hw->hw_token &= ~ACTIVE_BIT(ehci);
+                               qh->should_be_inactive = 1;
 
                                /* An unlink may leave an incomplete
                                 * async transaction in the TT buffer.
Index: usb-4.3/drivers/usb/host/ehci.h
===================================================================
--- usb-4.3.orig/drivers/usb/host/ehci.h
+++ usb-4.3/drivers/usb/host/ehci.h
@@ -439,6 +439,7 @@ struct ehci_qh {
        unsigned                dequeue_during_giveback:1;
        unsigned                exception:1;    /* got a fault, or an unlink
                                                   was requested */
+       unsigned                should_be_inactive:1;
 };
 
 /*-------------------------------------------------------------------------*/

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to