Module Name:    src
Committed By:   jakllsch
Date:           Wed Jun  2 18:53:40 UTC 2010

Modified Files:
        src/sys/dev/usb: ehci.c ehcireg.h

Log Message:
Improve EHCI isochronous code, fix scheduling.

 - Create and use symbolic constants.

 - Convert some switch statements to functionally-similar caculations.

 - Correct scheduling interval of high-speed isochronous transactions.
   Previous calculation produced half the intended rate.


To generate a diff of this commit:
cvs rdiff -u -r1.167 -r1.168 src/sys/dev/usb/ehci.c
cvs rdiff -u -r1.30 -r1.31 src/sys/dev/usb/ehcireg.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/ehci.c
diff -u src/sys/dev/usb/ehci.c:1.167 src/sys/dev/usb/ehci.c:1.168
--- src/sys/dev/usb/ehci.c:1.167	Sat May 29 16:52:33 2010
+++ src/sys/dev/usb/ehci.c	Wed Jun  2 18:53:39 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ehci.c,v 1.167 2010/05/29 16:52:33 jakllsch Exp $ */
+/*	$NetBSD: ehci.c,v 1.168 2010/06/02 18:53:39 jakllsch Exp $ */
 
 /*
  * Copyright (c) 2004-2008 The NetBSD Foundation, Inc.
@@ -52,7 +52,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.167 2010/05/29 16:52:33 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.168 2010/06/02 18:53:39 jakllsch Exp $");
 
 #include "ohci.h"
 #include "uhci.h"
@@ -811,12 +811,12 @@
 		    sizeof(itd->itd.itd_ctl), BUS_DMASYNC_POSTWRITE |
 		    BUS_DMASYNC_POSTREAD);
 
-	for (i = 0; i < 8; i++) {
+	for (i = 0; i < EHCI_ITD_NUFRAMES; i++) {
 		if (le32toh(itd->itd.itd_ctl[i]) & EHCI_ITD_ACTIVE)
 			break;
 	}
 
-	if (i == 8) {
+	if (i == EHCI_ITD_NUFRAMES) {
 		goto done; /* All 8 descriptors inactive, it's done */
 	}
 
@@ -879,21 +879,15 @@
 		nframes = 0;
 		actlen = 0;
 
-		switch (xfer->pipe->endpoint->edesc->bInterval) {
-		case 0:
-			panic("ehci: isoc xfer suddenly has 0 bInterval, invalid\n");
-		case 1: uframes = 1; break;
-		case 2: uframes = 2; break;
-		case 3: uframes = 4; break;
-		default: uframes = 8; break;
-		}
+		i = xfer->pipe->endpoint->edesc->bInterval;
+		uframes = min(1 << (i - 1), USB_UFRAMES_PER_FRAME);
 
 		for (itd = ex->itdstart; itd != NULL; itd = itd->xfer_next) {
 			usb_syncmem(&itd->dma,itd->offs + offsetof(ehci_itd_t,itd_ctl),
 			    sizeof(itd->itd.itd_ctl), BUS_DMASYNC_POSTWRITE |
 			    BUS_DMASYNC_POSTREAD);
 
-			for (i = 0; i < 8; i += uframes) {
+			for (i = 0; i < EHCI_ITD_NUFRAMES; i += uframes) {
 				/* XXX - driver didn't fill in the frame full
 				 *   of uframes. This leads to scheduling
 				 *   inefficiencies, but working around
@@ -1483,7 +1477,7 @@
 
 	printf("ITD: next phys=%X\n", itd->itd.itd_next);
 
-	for (i = 0; i < 8;i++) {
+	for (i = 0; i < EHCI_ITD_NUFRAMES; i++) {
 		t = le32toh(itd->itd.itd_ctl[i]);
 		printf("ITDctl %d: stat=%X len=%X ioc=%X pg=%X offs=%X\n", i,
 		    EHCI_ITD_GET_STATUS(t), EHCI_ITD_GET_LEN(t),
@@ -1491,7 +1485,7 @@
 		    EHCI_ITD_GET_OFFS(t));
 	}
 	printf("ITDbufr: ");
-	for (i = 0; i < 7; i++)
+	for (i = 0; i < EHCI_ITD_NBUFFERS; i++)
 		printf("%X,", EHCI_ITD_GET_BPTR(le32toh(itd->itd.itd_bufr[i])));
 
 	b = le32toh(itd->itd.itd_bufr[0]);
@@ -3857,22 +3851,9 @@
 		return USBD_INVAL;
 	}
 
-	switch (i) {
-	case 1:
-		ufrperframe = 8;
-		break;
-	case 2:
-		ufrperframe = 4;
-		break;
-	case 3:
-		ufrperframe = 2;
-		break;
-	default:
-		ufrperframe = 1;
-		break;
-	}
+	ufrperframe = max(1, USB_UFRAMES_PER_FRAME / (1 << (i - 1)));
 	frames = (xfer->nframes + (ufrperframe - 1)) / ufrperframe;
-	uframes = 8 / ufrperframe;
+	uframes = USB_UFRAMES_PER_FRAME / ufrperframe;
 
 	if (frames == 0) {
 		DPRINTF(("ehci_device_isoc_start: frames == 0\n"));
@@ -3901,7 +3882,7 @@
 		/*
 		 * Step 1.5, initialize uframes
 		 */
-		for (j = 0; j < 8; j += uframes) {
+		for (j = 0; j < EHCI_ITD_NUFRAMES; j += uframes) {
 			/* Calculate which page in the list this starts in */
 			int addr = DMAADDR(dma_buf, froffs);
 			addr = EHCI_PAGE_OFFSET(addr);
@@ -3935,7 +3916,7 @@
 		 * and what to not.
 		 */
 
-		for (j=0; j < 7; j++) {
+		for (j = 0; j < EHCI_ITD_NBUFFERS; j++) {
 			/*
 			 * Don't try to lookup a page that's past the end
 			 * of buffer
@@ -4006,12 +3987,12 @@
 	if (frindex >= sc->sc_flsize)
 		frindex &= (sc->sc_flsize - 1);
 
-	/* Whats the frame interval? */
-	i = (1 << epipe->pipe.endpoint->edesc->bInterval);
-	if (i / 8 == 0)
+	/* What's the frame interval? */
+	i = (1 << (epipe->pipe.endpoint->edesc->bInterval - 1));
+	if (i / USB_UFRAMES_PER_FRAME == 0)
 		i = 1;
 	else
-		i /= 8;
+		i /= USB_UFRAMES_PER_FRAME;
 
 	itd = start;
 	for (j = 0; j < frames; j++) {

Index: src/sys/dev/usb/ehcireg.h
diff -u src/sys/dev/usb/ehcireg.h:1.30 src/sys/dev/usb/ehcireg.h:1.31
--- src/sys/dev/usb/ehcireg.h:1.30	Sat May 15 20:47:23 2010
+++ src/sys/dev/usb/ehcireg.h	Wed Jun  2 18:53:39 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ehcireg.h,v 1.30 2010/05/15 20:47:23 jakllsch Exp $	*/
+/*	$NetBSD: ehcireg.h,v 1.31 2010/06/02 18:53:39 jakllsch Exp $	*/
 
 /*
  * Copyright (c) 2001, 2004 The NetBSD Foundation, Inc.
@@ -192,9 +192,11 @@
 typedef u_int32_t ehci_isoc_bufr_ptr_t;
 
 /* Isochronous Transfer Descriptor */
+#define EHCI_ITD_NUFRAMES USB_UFRAMES_PER_FRAME
+#define EHCI_ITD_NBUFFERS 7
 typedef struct {
 	volatile ehci_link_t		itd_next;
-	volatile ehci_isoc_trans_t	itd_ctl[8];
+	volatile ehci_isoc_trans_t	itd_ctl[EHCI_ITD_NUFRAMES];
 #define EHCI_ITD_GET_STATUS(x) (((x) >> 28) & 0xf)
 #define EHCI_ITD_SET_STATUS(x) (((x) & 0xf) << 28)
 #define EHCI_ITD_ACTIVE		0x80000000
@@ -210,7 +212,7 @@
 #define EHCI_ITD_SET_PG(x) (((x) & 0x7) << 12)
 #define EHCI_ITD_GET_OFFS(x) (((x) >> 0) & 0xfff)
 #define EHCI_ITD_SET_OFFS(x) (((x) & 0xfff) << 0)
-	volatile ehci_isoc_bufr_ptr_t	itd_bufr[7];
+	volatile ehci_isoc_bufr_ptr_t	itd_bufr[EHCI_ITD_NBUFFERS];
 #define EHCI_ITD_GET_BPTR(x) ((x) & 0xfffff000)
 #define EHCI_ITD_SET_BPTR(x) ((x) & 0xfffff000)
 #define EHCI_ITD_GET_EP(x) (((x) >> 8) & 0xf)
@@ -223,7 +225,7 @@
 #define EHCI_ITD_SET_MAXPKT(x) ((x) & 0x7ff)
 #define EHCI_ITD_GET_MULTI(x) ((x) & 0x3)
 #define EHCI_ITD_SET_MULTI(x) ((x) & 0x3)
-	volatile ehci_isoc_bufr_ptr_t	itd_bufr_hi[7];
+	volatile ehci_isoc_bufr_ptr_t	itd_bufr_hi[EHCI_ITD_NBUFFERS];
 } ehci_itd_t;
 #define EHCI_ITD_ALIGN 32
 

Reply via email to