]> git.sur5r.net Git - u-boot/blobdiff - drivers/usb/host/ehci-hcd.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[u-boot] / drivers / usb / host / ehci-hcd.c
index 41af302e036cf66e2b880240e23ea0ddb507c55b..6323c508375af8ce3b98009a85bfbc2f5e8a5564 100644 (file)
@@ -996,6 +996,7 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
         * Set up periodic list
         * Step 1: Parent QH for all periodic transfers.
         */
+       ehcic[index].periodic_schedules = 0;
        periodic = &ehcic[index].periodic_queue;
        memset(periodic, 0, sizeof(*periodic));
        periodic->qh_link = cpu_to_hc32(QH_LINK_TERMINATE);
@@ -1154,8 +1155,6 @@ disable_periodic(struct ehci_ctrl *ctrl)
        return 0;
 }
 
-static int periodic_schedules;
-
 struct int_queue *
 create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
                 int elementsize, void *buffer)
@@ -1278,7 +1277,7 @@ create_int_queue(struct usb_device *dev, unsigned long pipe, int queuesize,
                debug("FATAL: periodic should never fail, but did");
                goto fail3;
        }
-       periodic_schedules++;
+       ctrl->periodic_schedules++;
 
        debug("Exit create_int_queue\n");
        return result;
@@ -1297,6 +1296,7 @@ fail1:
 void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
 {
        struct QH *cur = queue->current;
+       struct qTD *cur_td;
 
        /* depleted queue */
        if (cur == NULL) {
@@ -1304,20 +1304,21 @@ void *poll_int_queue(struct usb_device *dev, struct int_queue *queue)
                return NULL;
        }
        /* still active */
-       invalidate_dcache_range((uint32_t)cur,
-                               ALIGN_END_ADDR(struct QH, cur, 1));
-       if (cur->qh_overlay.qt_token & cpu_to_hc32(0x80)) {
-               debug("Exit poll_int_queue with no completed intr transfer. "
-                     "token is %x\n", cur->qh_overlay.qt_token);
+       cur_td = &queue->tds[queue->current - queue->first];
+       invalidate_dcache_range((uint32_t)cur_td,
+                               ALIGN_END_ADDR(struct qTD, cur_td, 1));
+       if (QT_TOKEN_GET_STATUS(hc32_to_cpu(cur_td->qt_token)) &
+                       QT_TOKEN_STATUS_ACTIVE) {
+               debug("Exit poll_int_queue with no completed intr transfer. token is %x\n",
+                     hc32_to_cpu(cur_td->qt_token));
                return NULL;
        }
        if (!(cur->qh_link & QH_LINK_TERMINATE))
                queue->current++;
        else
                queue->current = NULL;
-       debug("Exit poll_int_queue with completed intr transfer. "
-             "token is %x at %p (first at %p)\n", cur->qh_overlay.qt_token,
-             &cur->qh_overlay.qt_token, queue->first);
+       debug("Exit poll_int_queue with completed intr transfer. token is %x at %p (first at %p)\n",
+             hc32_to_cpu(cur_td->qt_token), cur, queue->first);
        return cur->buffer;
 }
 
@@ -1333,7 +1334,7 @@ destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
                debug("FATAL: periodic should never fail, but did");
                goto out;
        }
-       periodic_schedules--;
+       ctrl->periodic_schedules--;
 
        struct QH *cur = &ctrl->periodic_queue;
        timeout = get_timer(0) + 500; /* abort after 500ms */
@@ -1342,6 +1343,8 @@ destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
                if (NEXT_QH(cur) == queue->first) {
                        debug("found candidate. removing from chain\n");
                        cur->qh_link = queue->last->qh_link;
+                       flush_dcache_range((uint32_t)cur,
+                                          ALIGN_END_ADDR(struct QH, cur, 1));
                        result = 0;
                        break;
                }
@@ -1353,7 +1356,7 @@ destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
                }
        }
 
-       if (periodic_schedules > 0) {
+       if (ctrl->periodic_schedules > 0) {
                result = enable_periodic(ctrl);
                if (result < 0)
                        debug("FATAL: periodic should never fail, but did");