summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorn_hibma <n_hibma@FreeBSD.org>1999-11-11 22:32:55 +0000
committern_hibma <n_hibma@FreeBSD.org>1999-11-11 22:32:55 +0000
commit9a30e94971558bbe2bf2f4450cfeb7f8dc8b5e89 (patch)
treeb3ab74a1b33ef1270f0e31907ae7f10ca42cdfe7 /sys
parent2df28cd3feb4dc03f845eeb69c859b61fe887418 (diff)
downloadFreeBSD-src-9a30e94971558bbe2bf2f4450cfeb7f8dc8b5e89.zip
FreeBSD-src-9a30e94971558bbe2bf2f4450cfeb7f8dc8b5e89.tar.gz
Fix the computation of the status of the transfers. It never saw a STALLED
condition for Short transfers. Change the scheduling to Depth first. We now transfer as many TD's as possible from QH before moving to the next queue (Breadth first). It should still be verified that this does not lead to starvation in a busy system (in the case were transfers are added to the beginning of the control or bulk queues).
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/uhci.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c
index 81a6534..ba8b15e 100644
--- a/sys/dev/usb/uhci.c
+++ b/sys/dev/usb/uhci.c
@@ -967,12 +967,13 @@ uhci_idone(ii)
/* The transfer is done, compute actual length and status. */
/* XXX Is this correct for control xfers? */
actlen = 0;
+ status = 0;
for (std = ii->stdstart; std; std = std->link.std) {
- status = LE(std->td.td_status);
- if (status & UHCI_TD_ACTIVE)
+ if (LE(std->td.td_status) & UHCI_TD_ACTIVE)
break;
- if (UHCI_TD_GET_PID(LE(std->td.td_token)) !=
- UHCI_TD_PID_SETUP)
+
+ status = LE(std->td.td_status);
+ if (UHCI_TD_GET_PID(LE(std->td.td_token)) != UHCI_TD_PID_SETUP)
actlen += UHCI_TD_GET_ACTLEN(status);
}
/* If there are left over TDs we need to update the toggle. */
@@ -984,7 +985,7 @@ uhci_idone(ii)
actlen, status));
reqh->actlen = actlen;
if (status != 0) {
- DPRINTFN(-1+((status&UHCI_TD_STALLED)!=0),
+ DPRINTFN((status&UHCI_TD_STALLED)*10,
("uhci_idone: error, addr=%d, endpt=0x%02x, "
"status 0x%b\n",
reqh->pipe->device->address,
@@ -1286,7 +1287,15 @@ uhci_alloc_std_chain(upipe, sc, len, rd, shortok, dma, sp, ep)
return (USBD_NOMEM);
}
p->link.std = lastp;
- p->td.td_link = LE(lastlink);
+ /* The if statement might be necessary to avoid confusing the
+ * VIA chipset. It doesn't like extra bits when UHCI_PTR_T
+ * is set.
+ */
+ if (lastlink != UHCI_PTR_T)
+ p->td.td_link = LE(lastlink|UHCI_PTR_VF);
+ else
+ p->td.td_link = LE(lastlink);
+
lastp = p;
lastlink = p->physaddr;
p->td.td_status = LE(status);
@@ -1713,7 +1722,7 @@ uhci_device_request(reqh)
return (r);
next = xfer;
xferend->link.std = stat;
- xferend->td.td_link = LE(stat->physaddr);
+ xferend->td.td_link = LE(stat->physaddr|UHCI_PTR_VF);
} else {
next = stat;
}
@@ -1722,7 +1731,7 @@ uhci_device_request(reqh)
memcpy(KERNADDR(&upipe->u.ctl.reqdma), req, sizeof *req);
setup->link.std = next;
- setup->td.td_link = LE(next->physaddr);
+ setup->td.td_link = LE(next->physaddr|UHCI_PTR_VF);
setup->td.td_status = LE(UHCI_TD_SET_ERRCNT(3) | ls | UHCI_TD_ACTIVE);
setup->td.td_token = LE(UHCI_TD_SETUP(sizeof *req, endpt, addr));
setup->td.td_buffer = LE(DMAADDR(&upipe->u.ctl.reqdma));
OpenPOWER on IntegriCloud