Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Dec 2012 13:58:50 +0100
From:      Hans Petter Selasky <hselasky@c2i.net>
To:        Warner Losh <imp@bsdimp.com>
Cc:        Oleksandr Tymoshenko <gonzo@freebsd.org>, Andrew Turner <andrew@fubar.geek.nz>, freebsd-usb@freebsd.org
Subject:   Re: EHCI on armv6 with Write-Back caches
Message-ID:  <201212201358.50067.hselasky@c2i.net>
In-Reply-To: <4A66C6C9-22EC-45AA-987D-49F958D7A8F9@bsdimp.com>
References:  <20121218204931.5322922d@fubar.geek.nz> <201212190956.28609.hselasky@c2i.net> <4A66C6C9-22EC-45AA-987D-49F958D7A8F9@bsdimp.com>

next in thread | previous in thread | raw e-mail | index | archive | help
--Boundary-00=_Kuw0QlgeVxE9A/+
Content-Type: Text/Plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Hi,

Please try the attached patch for 10-current. The patch is not tested yet, 
only compiles. I will try to test more later today. Let me know if you see any 
issues.

--HPS

--Boundary-00=_Kuw0QlgeVxE9A/+
Content-Type: text/x-patch;
  charset="iso-8859-1";
  name="usb_patches_multiple.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
	filename="usb_patches_multiple.diff"

=== dev/usb/serial/usb_serial.c
==================================================================
--- dev/usb/serial/usb_serial.c	(revision 244051)
+++ dev/usb/serial/usb_serial.c	(local)
@@ -797,10 +797,14 @@
 	DPRINTF("tp=%p\n", tp);
 
 	if (ttydisc_can_bypass(tp) != 0 || 
-	    (sc->sc_flag & UCOM_FLAG_HL_READY) == 0) {
+	    (sc->sc_flag & UCOM_FLAG_HL_READY) == 0 ||
+	    (sc->sc_flag & UCOM_FLAG_INWAKEUP) != 0) {
 		return;
 	}
 
+	/* prevent recursion */
+	sc->sc_flag |= UCOM_FLAG_INWAKEUP;
+
 	pos = sc->sc_jitterbuf_out;
 
 	while (sc->sc_jitterbuf_in != pos) {
@@ -821,6 +825,8 @@
 	if ((sc->sc_jitterbuf_in == pos) && 
 	    (sc->sc_flag & UCOM_FLAG_RTS_IFLOW))
 		ucom_rts(sc, 0);
+
+	sc->sc_flag &= ~UCOM_FLAG_INWAKEUP;
 }
 
 static int
=== dev/usb/serial/usb_serial.h
==================================================================
--- dev/usb/serial/usb_serial.h	(revision 244051)
+++ dev/usb/serial/usb_serial.h	(local)
@@ -183,6 +183,7 @@
 #define	UCOM_FLAG_CONSOLE	0x80	/* set if device is a console */
 #define	UCOM_FLAG_WAIT_REFS   0x0100	/* set if we must wait for refs */
 #define	UCOM_FLAG_FREE_UNIT   0x0200	/* set if we must free the unit */
+#define	UCOM_FLAG_INWAKEUP    0x0400	/* set if we are in the tty_inwakeup callback */
 	uint8_t	sc_lsr;
 	uint8_t	sc_msr;
 	uint8_t	sc_mcr;
=== dev/usb/storage/ustorage_fs.c
==================================================================
--- dev/usb/storage/ustorage_fs.c	(revision 244051)
+++ dev/usb/storage/ustorage_fs.c	(local)
@@ -74,7 +74,7 @@
 /* Define some limits */
 
 #ifndef USTORAGE_FS_BULK_SIZE 
-#define	USTORAGE_FS_BULK_SIZE (1UL << 17)	/* bytes */
+#define	USTORAGE_FS_BULK_SIZE	(1U << 17)	/* bytes */
 #endif
 
 #ifndef	USTORAGE_FS_MAX_LUN
@@ -85,8 +85,6 @@
 #define	USTORAGE_QDATA_MAX	40	/* bytes */
 #endif
 
-#define sc_cmd_data sc_cbw.CBWCDB
-
 /*
  * The SCSI ID string must be exactly 28 characters long
  * exluding the terminating zero.
@@ -176,8 +174,9 @@
 
 struct ustorage_fs_softc {
 
-	ustorage_fs_bbb_cbw_t sc_cbw;	/* Command Wrapper Block */
-	ustorage_fs_bbb_csw_t sc_csw;	/* Command Status Block */
+	ustorage_fs_bbb_cbw_t *sc_cbw;	/* Command Wrapper Block */
+	ustorage_fs_bbb_csw_t *sc_csw;	/* Command Status Block */
+	void *sc_dma_ptr;		/* Main data buffer */
 
 	struct mtx sc_mtx;
 
@@ -275,7 +274,6 @@
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
 		.bufsize = sizeof(ustorage_fs_bbb_cbw_t),
-		.flags = {.ext_buffer = 1,},
 		.callback = &ustorage_fs_t_bbb_command_callback,
 		.usb_mode = USB_MODE_DEVICE,
 	},
@@ -295,7 +293,7 @@
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
 		.bufsize = USTORAGE_FS_BULK_SIZE,
-		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer = 1},
+		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1},
 		.callback = &ustorage_fs_t_bbb_data_read_callback,
 		.usb_mode = USB_MODE_DEVICE,
 	},
@@ -315,7 +313,7 @@
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
 		.bufsize = sizeof(ustorage_fs_bbb_csw_t),
-		.flags = {.short_xfer_ok = 1,.ext_buffer = 1,},
+		.flags = {.short_xfer_ok = 1},
 		.callback = &ustorage_fs_t_bbb_status_callback,
 		.usb_mode = USB_MODE_DEVICE,
 	},
@@ -409,6 +407,14 @@
 		    "transfers, %s\n", usbd_errstr(err));
 		goto detach;
 	}
+
+	sc->sc_cbw = usbd_xfer_get_frame_buffer(sc->sc_xfer[
+	    USTORAGE_FS_T_BBB_COMMAND], 0);
+	sc->sc_csw = usbd_xfer_get_frame_buffer(sc->sc_xfer[
+	    USTORAGE_FS_T_BBB_STATUS], 0);
+ 	sc->sc_dma_ptr = usbd_xfer_get_frame_buffer(sc->sc_xfer[
+	    USTORAGE_FS_T_BBB_DATA_READ], 0);
+
 	/* start Mass Storage State Machine */
 
 	mtx_lock(&sc->sc_mtx);
@@ -518,44 +524,44 @@
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
 
-		tag = UGETDW(sc->sc_cbw.dCBWSignature);
+		tag = UGETDW(sc->sc_cbw->dCBWSignature);
 
 		if (tag != CBWSIGNATURE) {
 			/* do nothing */
 			DPRINTF("invalid signature 0x%08x\n", tag);
 			break;
 		}
-		tag = UGETDW(sc->sc_cbw.dCBWTag);
+		tag = UGETDW(sc->sc_cbw->dCBWTag);
 
 		/* echo back tag */
-		USETDW(sc->sc_csw.dCSWTag, tag);
+		USETDW(sc->sc_csw->dCSWTag, tag);
 
 		/* reset status */
-		sc->sc_csw.bCSWStatus = 0;
+		sc->sc_csw->bCSWStatus = 0;
 
 		/* reset data offset, data length and data remainder */
 		sc->sc_transfer.offset = 0;
 		sc->sc_transfer.data_rem =
-		    UGETDW(sc->sc_cbw.dCBWDataTransferLength);
+		    UGETDW(sc->sc_cbw->dCBWDataTransferLength);
 
 		/* reset data flags */
 		sc->sc_transfer.data_short = 0;
 
 		/* extract LUN */
-		sc->sc_transfer.lun = sc->sc_cbw.bCBWLUN;
+		sc->sc_transfer.lun = sc->sc_cbw->bCBWLUN;
 
 		if (sc->sc_transfer.data_rem == 0) {
 			sc->sc_transfer.cbw_dir = DIR_NONE;
 		} else {
-			if (sc->sc_cbw.bCBWFlags & CBWFLAGS_IN) {
+			if (sc->sc_cbw->bCBWFlags & CBWFLAGS_IN) {
 				sc->sc_transfer.cbw_dir = DIR_WRITE;
 			} else {
 				sc->sc_transfer.cbw_dir = DIR_READ;
 			}
 		}
 
-		sc->sc_transfer.cmd_len = sc->sc_cbw.bCDBLength;
-		if ((sc->sc_transfer.cmd_len > sizeof(sc->sc_cbw.CBWCDB)) ||
+		sc->sc_transfer.cmd_len = sc->sc_cbw->bCDBLength;
+		if ((sc->sc_transfer.cmd_len > sizeof(sc->sc_cbw->CBWCDB)) ||
 		    (sc->sc_transfer.cmd_len == 0)) {
 			/* just halt - this is invalid */
 			DPRINTF("invalid command length %d bytes\n",
@@ -597,9 +603,6 @@
 			usbd_xfer_set_stall(xfer);
 			DPRINTF("stall pipe\n");
 		}
-
-		usbd_xfer_set_frame_data(xfer, 0, &sc->sc_cbw,
-		    sizeof(sc->sc_cbw));
 		usbd_transfer_submit(xfer);
 		break;
 
@@ -616,9 +619,9 @@
 		goto tr_setup;
 	}
 	if (err) {
-		if (sc->sc_csw.bCSWStatus == 0) {
+		if (sc->sc_csw->bCSWStatus == 0) {
 			/* set some default error code */
-			sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
+			sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
 		}
 		if (sc->sc_transfer.cbw_dir == DIR_READ) {
 			/* dump all data */
@@ -699,6 +702,9 @@
 
 	switch (USB_GET_STATE(xfer)) {
 	case USB_ST_TRANSFERRED:
+		/* XXX copy data from DMA buffer */
+		memcpy(sc->sc_transfer.data_ptr, sc->sc_dma_ptr, actlen);
+
 		sc->sc_transfer.data_rem -= actlen;
 		sc->sc_transfer.data_ptr += actlen;
 		sc->sc_transfer.offset += actlen;
@@ -721,8 +727,7 @@
 			usbd_xfer_set_stall(xfer);
 		}
 
-		usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
-		    max_bulk);
+		usbd_xfer_set_frame_data(xfer, 0, sc->sc_dma_ptr, max_bulk);
 		usbd_transfer_submit(xfer);
 		break;
 
@@ -778,8 +783,10 @@
 			usbd_xfer_set_stall(xfer);
 		}
 
-		usbd_xfer_set_frame_data(xfer, 0, sc->sc_transfer.data_ptr,
-		    max_bulk);
+		/* XXX copy data to DMA buffer */
+		memcpy(sc->sc_dma_ptr, sc->sc_transfer.data_ptr, max_bulk);
+
+		usbd_xfer_set_frame_data(xfer, 0, sc->sc_dma_ptr, max_bulk);
 		usbd_transfer_submit(xfer);
 		break;
 
@@ -813,16 +820,13 @@
 
 	case USB_ST_SETUP:
 tr_setup:
-		USETDW(sc->sc_csw.dCSWSignature, CSWSIGNATURE);
-		USETDW(sc->sc_csw.dCSWDataResidue, sc->sc_transfer.data_rem);
+		USETDW(sc->sc_csw->dCSWSignature, CSWSIGNATURE);
+		USETDW(sc->sc_csw->dCSWDataResidue, sc->sc_transfer.data_rem);
 
 		if (sc->sc_transfer.data_error) {
 			sc->sc_transfer.data_error = 0;
 			usbd_xfer_set_stall(xfer);
 		}
-
-		usbd_xfer_set_frame_data(xfer, 0, &sc->sc_csw,
-		    sizeof(sc->sc_csw));
 		usbd_transfer_submit(xfer);
 		break;
 
@@ -934,17 +938,17 @@
 	/*
 	 * Get the starting Logical Block Address
 	 */
-	lba = get_be32(&sc->sc_cmd_data[2]);
+	lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
 
 	/*
 	 * We allow DPO (Disable Page Out = don't save data in the cache)
 	 * but we don't implement it.
 	 */
-	if ((sc->sc_cmd_data[1] & ~0x10) != 0) {
+	if ((sc->sc_cbw->CBWCDB[1] & ~0x10) != 0) {
 		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 		return (1);
 	}
-	vlen = get_be16(&sc->sc_cmd_data[7]);
+	vlen = get_be16(&sc->sc_cbw->CBWCDB[7]);
 	if (vlen == 0) {
 		goto done;
 	}
@@ -1092,8 +1096,8 @@
 {
 	uint8_t *buf = sc->sc_transfer.data_ptr;
 	struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
-	uint32_t lba = get_be32(&sc->sc_cmd_data[2]);
-	uint8_t pmi = sc->sc_cmd_data[8];
+	uint32_t lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
+	uint8_t pmi = sc->sc_cbw->CBWCDB[8];
 
 	/* Check the PMI and LBA fields */
 	if ((pmi > 1) || ((pmi == 0) && (lba != 0))) {
@@ -1126,7 +1130,7 @@
 	uint8_t *buf0;
 	uint16_t len;
 	uint16_t limit;
-	uint8_t mscmnd = sc->sc_cmd_data[0];
+	uint8_t mscmnd = sc->sc_cbw->CBWCDB[0];
 	uint8_t pc;
 	uint8_t page_code;
 	uint8_t changeable_values;
@@ -1134,13 +1138,13 @@
 
 	buf0 = buf;
 
-	if ((sc->sc_cmd_data[1] & ~0x08) != 0) {
+	if ((sc->sc_cbw->CBWCDB[1] & ~0x08) != 0) {
 		/* Mask away DBD */
 		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 		return (1);
 	}
-	pc = sc->sc_cmd_data[2] >> 6;
-	page_code = sc->sc_cmd_data[2] & 0x3f;
+	pc = sc->sc_cbw->CBWCDB[2] >> 6;
+	page_code = sc->sc_cbw->CBWCDB[2] & 0x3f;
 	if (pc == 3) {
 		currlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
 		return (1);
@@ -1237,9 +1241,9 @@
 		currlun->sense_data = SS_INVALID_COMMAND;
 		return (1);
 	}
-	immed = sc->sc_cmd_data[1] & 0x01;
-	loej = sc->sc_cmd_data[4] & 0x02;
-	start = sc->sc_cmd_data[4] & 0x01;
+	immed = sc->sc_cbw->CBWCDB[1] & 0x01;
+	loej = sc->sc_cbw->CBWCDB[4] & 0x02;
+	start = sc->sc_cbw->CBWCDB[4] & 0x01;
 
 	if (immed || loej || start) {
 		/* compile fix */
@@ -1264,8 +1268,8 @@
 		currlun->sense_data = SS_INVALID_COMMAND;
 		return (1);
 	}
-	prevent = sc->sc_cmd_data[4] & 0x01;
-	if ((sc->sc_cmd_data[4] & ~0x01) != 0) {
+	prevent = sc->sc_cbw->CBWCDB[4] & 0x01;
+	if ((sc->sc_cbw->CBWCDB[4] & ~0x01) != 0) {
 		/* Mask away Prevent */
 		currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 		return (1);
@@ -1369,18 +1373,18 @@
 	 * Get the starting Logical Block Address and check that it's not
 	 * too big
 	 */
-	if (sc->sc_cmd_data[0] == SC_READ_6) {
-		lba = (((uint32_t)sc->sc_cmd_data[1]) << 16) |
-		    get_be16(&sc->sc_cmd_data[2]);
+	if (sc->sc_cbw->CBWCDB[0] == SC_READ_6) {
+		lba = (((uint32_t)sc->sc_cbw->CBWCDB[1]) << 16) |
+		    get_be16(&sc->sc_cbw->CBWCDB[2]);
 	} else {
-		lba = get_be32(&sc->sc_cmd_data[2]);
+		lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
 
 		/*
 		 * We allow DPO (Disable Page Out = don't save data in the
 		 * cache) and FUA (Force Unit Access = don't read from the
 		 * cache), but we don't implement them.
 		 */
-		if ((sc->sc_cmd_data[1] & ~0x18) != 0) {
+		if ((sc->sc_cbw->CBWCDB[1] & ~0x18) != 0) {
 			currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 			return (1);
 		}
@@ -1427,11 +1431,11 @@
 	 * Get the starting Logical Block Address and check that it's not
 	 * too big.
 	 */
-	if (sc->sc_cmd_data[0] == SC_WRITE_6)
-		lba = (((uint32_t)sc->sc_cmd_data[1]) << 16) |
-		    get_be16(&sc->sc_cmd_data[2]);
+	if (sc->sc_cbw->CBWCDB[0] == SC_WRITE_6)
+		lba = (((uint32_t)sc->sc_cbw->CBWCDB[1]) << 16) |
+		    get_be16(&sc->sc_cbw->CBWCDB[2]);
 	else {
-		lba = get_be32(&sc->sc_cmd_data[2]);
+		lba = get_be32(&sc->sc_cbw->CBWCDB[2]);
 
 		/*
 		 * We allow DPO (Disable Page Out = don't save data in the
@@ -1439,11 +1443,11 @@
 		 * medium).  We don't implement DPO; we implement FUA by
 		 * performing synchronous output.
 		 */
-		if ((sc->sc_cmd_data[1] & ~0x18) != 0) {
+		if ((sc->sc_cbw->CBWCDB[1] & ~0x18) != 0) {
 			currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 			return (1);
 		}
-		if (sc->sc_cmd_data[1] & 0x08) {
+		if (sc->sc_cbw->CBWCDB[1] & 0x08) {
 			/* FUA */
 			/* XXX set SYNC flag here */
 		}
@@ -1483,7 +1487,7 @@
 			 * there must be something wrong about this SCSI
 			 * command
 			 */
-			sc->sc_csw.bCSWStatus = CSWSTATUS_PHASE;
+			sc->sc_csw->bCSWStatus = CSWSTATUS_PHASE;
 			return (1);
 		}
 		/* compute the minimum length */
@@ -1519,18 +1523,18 @@
     uint16_t mask, uint8_t needs_medium)
 {
 	struct ustorage_fs_lun *currlun;
-	uint8_t lun = (sc->sc_cmd_data[1] >> 5);
+	uint8_t lun = (sc->sc_cbw->CBWCDB[1] >> 5);
 	uint8_t i;
 
 	/* Verify the length of the command itself */
 	if (min_cmd_size > sc->sc_transfer.cmd_len) {
 		DPRINTF("%u > %u\n",
 		    min_cmd_size, sc->sc_transfer.cmd_len);
-		sc->sc_csw.bCSWStatus = CSWSTATUS_PHASE;
+		sc->sc_csw->bCSWStatus = CSWSTATUS_PHASE;
 		return (1);
 	}
 	/* Mask away the LUN */
-	sc->sc_cmd_data[1] &= 0x1f;
+	sc->sc_cbw->CBWCDB[1] &= 0x1f;
 
 	/* Check if LUN is correct */
 	if (lun != sc->sc_transfer.lun) {
@@ -1540,7 +1544,7 @@
 	if (sc->sc_transfer.lun <= sc->sc_last_lun) {
 		sc->sc_transfer.currlun = currlun =
 		    sc->sc_lun + sc->sc_transfer.lun;
-		if (sc->sc_cmd_data[0] != SC_REQUEST_SENSE) {
+		if (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE) {
 			currlun->sense_data = SS_NO_SENSE;
 			currlun->sense_data_info = 0;
 			currlun->info_valid = 0;
@@ -1551,8 +1555,8 @@
 		 * else must fail!
 		 */
 		if ((currlun->unit_attention_data != SS_NO_SENSE) &&
-		    (sc->sc_cmd_data[0] != SC_INQUIRY) &&
-		    (sc->sc_cmd_data[0] != SC_REQUEST_SENSE)) {
+		    (sc->sc_cbw->CBWCDB[0] != SC_INQUIRY) &&
+		    (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE)) {
 			currlun->sense_data = currlun->unit_attention_data;
 			currlun->unit_attention_data = SS_NO_SENSE;
 			return (1);
@@ -1564,8 +1568,8 @@
 		 * INQUIRY and REQUEST SENSE commands are explicitly allowed
 		 * to use unsupported LUNs; all others may not.
 		 */
-		if ((sc->sc_cmd_data[0] != SC_INQUIRY) &&
-		    (sc->sc_cmd_data[0] != SC_REQUEST_SENSE)) {
+		if ((sc->sc_cbw->CBWCDB[0] != SC_INQUIRY) &&
+		    (sc->sc_cbw->CBWCDB[0] != SC_REQUEST_SENSE)) {
 			return (1);
 		}
 	}
@@ -1575,7 +1579,7 @@
 	 * non-zero.
 	 */
 	for (i = 0; i != min_cmd_size; i++) {
-		if (sc->sc_cmd_data[i] && !(mask & (1UL << i))) {
+		if (sc->sc_cbw->CBWCDB[i] && !(mask & (1UL << i))) {
 			if (currlun) {
 				currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
 			}
@@ -1613,12 +1617,12 @@
 	sc->sc_transfer.data_ptr = sc->sc_qdata;
 
 	DPRINTF("cmd_data[0]=0x%02x, data_rem=0x%08x\n",
-	    sc->sc_cmd_data[0], sc->sc_transfer.data_rem);
+	    sc->sc_cbw->CBWCDB[0], sc->sc_transfer.data_rem);
 
-	switch (sc->sc_cmd_data[0]) {
+	switch (sc->sc_cbw->CBWCDB[0]) {
 	case SC_INQUIRY:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
-		error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
+		error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
 		if (error) {
 			break;
 		}
@@ -1633,7 +1637,7 @@
 
 	case SC_MODE_SELECT_6:
 		sc->sc_transfer.cmd_dir = DIR_READ;
-		error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
+		error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
 		if (error) {
 			break;
 		}
@@ -1649,7 +1653,7 @@
 	case SC_MODE_SELECT_10:
 		sc->sc_transfer.cmd_dir = DIR_READ;
 		error = ustorage_fs_min_len(sc,
-		    get_be16(&sc->sc_cmd_data[7]), -1U);
+		    get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
 		if (error) {
 			break;
 		}
@@ -1664,7 +1668,7 @@
 
 	case SC_MODE_SENSE_6:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
-		error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
+		error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
 		if (error) {
 			break;
 		}
@@ -1680,7 +1684,7 @@
 	case SC_MODE_SENSE_10:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
 		error = ustorage_fs_min_len(sc,
-		    get_be16(&sc->sc_cmd_data[7]), -1U);
+		    get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
 		if (error) {
 			break;
 		}
@@ -1708,7 +1712,7 @@
 		break;
 
 	case SC_READ_6:
-		i = sc->sc_cmd_data[4];
+		i = sc->sc_cbw->CBWCDB[4];
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
 		temp = ((i == 0) ? 256UL : i);
 		error = ustorage_fs_min_len(sc, temp << 9, mask9);
@@ -1726,7 +1730,7 @@
 
 	case SC_READ_10:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
-		temp = get_be16(&sc->sc_cmd_data[7]);
+		temp = get_be16(&sc->sc_cbw->CBWCDB[7]);
 		error = ustorage_fs_min_len(sc, temp << 9, mask9);
 		if (error) {
 			break;
@@ -1742,10 +1746,10 @@
 
 	case SC_READ_12:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
-		temp = get_be32(&sc->sc_cmd_data[6]);
+		temp = get_be32(&sc->sc_cbw->CBWCDB[6]);
 		if (temp >= (1UL << (32 - 9))) {
 			/* numerical overflow */
-			sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
+			sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
 			error = 1;
 			break;
 		}
@@ -1776,7 +1780,7 @@
 	case SC_READ_FORMAT_CAPACITIES:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
 		error = ustorage_fs_min_len(sc,
-		    get_be16(&sc->sc_cmd_data[7]), -1U);
+		    get_be16(&sc->sc_cbw->CBWCDB[7]), -1U);
 		if (error) {
 			break;
 		}
@@ -1791,7 +1795,7 @@
 
 	case SC_REQUEST_SENSE:
 		sc->sc_transfer.cmd_dir = DIR_WRITE;
-		error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], -1U);
+		error = ustorage_fs_min_len(sc, sc->sc_cbw->CBWCDB[4], -1U);
 		if (error) {
 			break;
 		}
@@ -1860,7 +1864,7 @@
 		break;
 
 	case SC_WRITE_6:
-		i = sc->sc_cmd_data[4];
+		i = sc->sc_cbw->CBWCDB[4];
 		sc->sc_transfer.cmd_dir = DIR_READ;
 		temp = ((i == 0) ? 256UL : i);
 		error = ustorage_fs_min_len(sc, temp << 9, mask9);
@@ -1878,7 +1882,7 @@
 
 	case SC_WRITE_10:
 		sc->sc_transfer.cmd_dir = DIR_READ;
-		temp = get_be16(&sc->sc_cmd_data[7]);
+		temp = get_be16(&sc->sc_cbw->CBWCDB[7]);
 		error = ustorage_fs_min_len(sc, temp << 9, mask9);
 		if (error) {
 			break;
@@ -1894,10 +1898,10 @@
 
 	case SC_WRITE_12:
 		sc->sc_transfer.cmd_dir = DIR_READ;
-		temp = get_be32(&sc->sc_cmd_data[6]);
+		temp = get_be32(&sc->sc_cbw->CBWCDB[6]);
 		if (temp > (mask9 >> 9)) {
 			/* numerical overflow */
-			sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
+			sc->sc_csw->bCSWStatus = CSWSTATUS_FAILED;
 			error = 1;
 			break;
 		}
=== dev/usb/usb_msctest.c
==================================================================
--- dev/usb/usb_msctest.c	(revision 244051)
+++ dev/usb/usb_msctest.c	(local)
@@ -139,8 +139,8 @@
 struct bbb_transfer {
 	struct mtx mtx;
 	struct cv cv;
-	struct bbb_cbw cbw;
-	struct bbb_csw csw;
+	struct bbb_cbw *cbw;
+	struct bbb_csw *csw;
 
 	struct usb_xfer *xfer[ST_MAX];
 
@@ -158,7 +158,7 @@
 	uint8_t	status_try;
 	int	error;
 
-	uint8_t	buffer[SCSI_MAX_LEN] __aligned(4);
+	uint8_t	*buffer;
 };
 
 static usb_callback_t bbb_command_callback;
@@ -184,7 +184,6 @@
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
 		.bufsize = sizeof(struct bbb_cbw),
-		.flags = {.ext_buffer = 1,},
 		.callback = &bbb_command_callback,
 		.timeout = 4 * USB_MS_HZ,	/* 4 seconds */
 	},
@@ -193,8 +192,8 @@
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
-		.bufsize = BULK_SIZE,
-		.flags = {.ext_buffer = 1,.proxy_buffer = 1,.short_xfer_ok = 1,},
+		.bufsize = MAX(SCSI_MAX_LEN, BULK_SIZE),
+		.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
 		.callback = &bbb_data_read_callback,
 		.timeout = 4 * USB_MS_HZ,	/* 4 seconds */
 	},
@@ -232,7 +231,7 @@
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
 		.bufsize = sizeof(struct bbb_csw),
-		.flags = {.ext_buffer = 1,.short_xfer_ok = 1,},
+		.flags = {.short_xfer_ok = 1,},
 		.callback = &bbb_status_callback,
 		.timeout = 1 * USB_MS_HZ,	/* 1 second  */
 	},
@@ -241,7 +240,6 @@
 static void
 bbb_done(struct bbb_transfer *sc, int error)
 {
-
 	sc->error = error;
 	sc->state = ST_COMMAND;
 	sc->status_try = 1;
@@ -290,18 +288,17 @@
 
 	case USB_ST_SETUP:
 		sc->status_try = 0;
-		tag = UGETDW(sc->cbw.dCBWTag) + 1;
-		USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE);
-		USETDW(sc->cbw.dCBWTag, tag);
-		USETDW(sc->cbw.dCBWDataTransferLength, (uint32_t)sc->data_len);
-		sc->cbw.bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT);
-		sc->cbw.bCBWLUN = sc->lun;
-		sc->cbw.bCDBLength = sc->cmd_len;
-		if (sc->cbw.bCDBLength > sizeof(sc->cbw.CBWCDB)) {
-			sc->cbw.bCDBLength = sizeof(sc->cbw.CBWCDB);
+		tag = UGETDW(sc->cbw->dCBWTag) + 1;
+		USETDW(sc->cbw->dCBWSignature, CBWSIGNATURE);
+		USETDW(sc->cbw->dCBWTag, tag);
+		USETDW(sc->cbw->dCBWDataTransferLength, (uint32_t)sc->data_len);
+		sc->cbw->bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT);
+		sc->cbw->bCBWLUN = sc->lun;
+		sc->cbw->bCDBLength = sc->cmd_len;
+		if (sc->cbw->bCDBLength > sizeof(sc->cbw->CBWCDB)) {
+			sc->cbw->bCDBLength = sizeof(sc->cbw->CBWCDB);
 			DPRINTFN(0, "Truncating long command\n");
 		}
-		usbd_xfer_set_frame_data(xfer, 0, &sc->cbw, sizeof(sc->cbw));
 		usbd_transfer_submit(xfer);
 		break;
 
@@ -430,9 +427,9 @@
 
 		/* very simple status check */
 
-		if (actlen < (int)sizeof(sc->csw)) {
+		if (actlen < (int)sizeof(struct bbb_csw)) {
 			bbb_done(sc, USB_ERR_SHORT_XFER);
-		} else if (sc->csw.bCSWStatus == CSWSTATUS_GOOD) {
+		} else if (sc->csw->bCSWStatus == CSWSTATUS_GOOD) {
 			bbb_done(sc, 0);	/* success */
 		} else {
 			bbb_done(sc, ERR_CSW_FAILED);	/* error */
@@ -440,7 +437,6 @@
 		break;
 
 	case USB_ST_SETUP:
-		usbd_xfer_set_frame_data(xfer, 0, &sc->csw, sizeof(sc->csw));
 		usbd_transfer_submit(xfer);
 		break;
 
@@ -478,9 +474,9 @@
 	sc->data_timeout = (data_timeout + USB_MS_HZ);
 	sc->actlen = 0;
 	sc->cmd_len = cmd_len;
-	memset(&sc->cbw.CBWCDB, 0, sizeof(sc->cbw.CBWCDB));
-	memcpy(&sc->cbw.CBWCDB, cmd_ptr, cmd_len);
-	DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw.CBWCDB, ":");
+	memset(&sc->cbw->CBWCDB, 0, sizeof(sc->cbw->CBWCDB));
+	memcpy(&sc->cbw->CBWCDB, cmd_ptr, cmd_len);
+	DPRINTFN(1, "SCSI cmd = %*D\n", (int)cmd_len, (char *)sc->cbw->CBWCDB, ":");
 
 	mtx_lock(&sc->mtx);
 	usbd_transfer_start(sc->xfer[sc->state]);
@@ -554,6 +550,14 @@
 		bbb_detach(sc);
 		return (NULL);
 	}
+	/* store pointer to DMA buffers */
+	sc->buffer = usbd_xfer_get_frame_buffer(
+	    sc->xfer[ST_DATA_RD], 0);
+	sc->cbw = usbd_xfer_get_frame_buffer(
+	    sc->xfer[ST_COMMAND], 0);
+	sc->csw = usbd_xfer_get_frame_buffer(
+	    sc->xfer[ST_STATUS], 0);
+
 	return (sc);
 }
 
=== dev/usb/usb_transfer.c
==================================================================
--- dev/usb/usb_transfer.c	(revision 244051)
+++ dev/usb/usb_transfer.c	(local)
@@ -688,12 +688,30 @@
 	 */
 
 	if (!xfer->flags.ext_buffer) {
+#if USB_HAVE_BUSDMA
+		struct usb_page_search page_info;
+		struct usb_page_cache *pc;
 
+		if (usbd_transfer_setup_sub_malloc(parm,
+		    &pc, parm->bufsize, 1, 1)) {
+			parm->err = USB_ERR_NOMEM;
+		} else if (parm->buf != NULL) {
+
+			usbd_get_page(pc, 0, &page_info);
+
+			xfer->local_buffer = page_info.buffer;
+
+			usbd_xfer_set_frame_offset(xfer, 0, 0);
+
+			if ((type == UE_CONTROL) && (n_frbuffers > 1)) {
+				usbd_xfer_set_frame_offset(xfer, REQ_SIZE, 1);
+			}
+		}
+#else
 		/* align data */
 		parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
 
-		if (parm->buf) {
-
+		if (parm->buf != NULL) {
 			xfer->local_buffer =
 			    USB_ADD_BYTES(parm->buf, parm->size[0]);
 
@@ -707,6 +725,7 @@
 
 		/* align data again */
 		parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1));
+#endif
 	}
 	/*
 	 * Compute maximum buffer size
@@ -1078,9 +1097,12 @@
 		 * The number of DMA tags required depends on
 		 * the number of endpoints. The current estimate
 		 * for maximum number of DMA tags per endpoint
-		 * is two.
+		 * is three:
+		 * 1) for loading memory
+		 * 2) for allocating memory
+		 * 3) for fixing memory [UHCI]
 		 */
-		parm.dma_tag_max += 2 * MIN(n_setup, USB_EP_MAX);
+		parm.dma_tag_max += 3 * MIN(n_setup, USB_EP_MAX);
 
 		/*
 		 * DMA tags for QH, TD, Data and more.
@@ -1943,6 +1965,17 @@
 	return (&xfer->frbuffers[frindex]);
 }
 
+void *
+usbd_xfer_get_frame_buffer(struct usb_xfer *xfer, usb_frcount_t frindex)
+{
+	struct usb_page_search page_info;
+
+	KASSERT(frindex < xfer->max_frame_count, ("frame index overflow"));
+
+	usbd_get_page(&xfer->frbuffers[frindex], 0, &page_info);
+	return (page_info.buffer);
+}
+
 /*------------------------------------------------------------------------*
  *	usbd_xfer_get_fps_shift
  *
=== dev/usb/usbdi.h
==================================================================
--- dev/usb/usbdi.h	(revision 244051)
+++ dev/usb/usbdi.h	(local)
@@ -530,8 +530,8 @@
 	usbd_xfer_old_frame_length(struct usb_xfer *xfer, usb_frcount_t frindex);
 void	usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen,
 	    int *aframes, int *nframes);
-struct usb_page_cache *usbd_xfer_get_frame(struct usb_xfer *xfer,
-	    usb_frcount_t frindex);
+struct usb_page_cache *usbd_xfer_get_frame(struct usb_xfer *, usb_frcount_t);
+void	*usbd_xfer_get_frame_buffer(struct usb_xfer *, usb_frcount_t);
 void	*usbd_xfer_softc(struct usb_xfer *xfer);
 void	*usbd_xfer_get_priv(struct usb_xfer *xfer);
 void	usbd_xfer_set_priv(struct usb_xfer *xfer, void *);
=== dev/usb/wlan/if_uath.c
==================================================================
--- dev/usb/wlan/if_uath.c	(revision 244051)
+++ dev/usb/wlan/if_uath.c	(local)
@@ -217,9 +217,8 @@
 		.type = UE_BULK,
 		.endpoint = 0x1,
 		.direction = UE_DIR_OUT,
-		.bufsize = UATH_MAX_CMDSZ,
+		.bufsize = UATH_MAX_CMDSZ * UATH_CMD_LIST_COUNT,
 		.flags = {
-			.ext_buffer = 1,
 			.force_short_xfer = 1,
 			.pipe_bof = 1,
 		},
@@ -242,9 +241,8 @@
 		.type = UE_BULK,
 		.endpoint = 0x2,
 		.direction = UE_DIR_OUT,
-		.bufsize = UATH_MAX_TXBUFSZ,
+		.bufsize = UATH_MAX_TXBUFSZ * UATH_TX_DATA_LIST_COUNT,
 		.flags = {
-			.ext_buffer = 1,
 			.force_short_xfer = 1,
 			.pipe_bof = 1
 		},
@@ -258,10 +256,8 @@
 		    const uint8_t [IEEE80211_ADDR_LEN],
 		    const uint8_t [IEEE80211_ADDR_LEN]);
 static void	uath_vap_delete(struct ieee80211vap *);
-static int	uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd [],
-		    int, int);
-static void	uath_free_cmd_list(struct uath_softc *, struct uath_cmd [],
-		    int);
+static int	uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd []);
+static void	uath_free_cmd_list(struct uath_softc *, struct uath_cmd []);
 static int	uath_host_available(struct uath_softc *);
 static int	uath_get_capability(struct uath_softc *, uint32_t, uint32_t *);
 static int	uath_get_devcap(struct uath_softc *);
@@ -365,8 +361,7 @@
 	/*
 	 * Allocate xfers for firmware commands.
 	 */
-	error = uath_alloc_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT,
-	    UATH_MAX_CMDSZ);
+	error = uath_alloc_cmd_list(sc, sc->sc_cmd);
 	if (error != 0) {
 		device_printf(sc->sc_dev,
 		    "could not allocate Tx command list\n");
@@ -381,6 +376,11 @@
 		goto fail1;
 	}
 
+	sc->sc_cmd_dma_buf = 
+	    usbd_xfer_get_frame_buffer(sc->sc_xfer[UATH_INTR_TX], 0);
+	sc->sc_tx_dma_buf = 
+	    usbd_xfer_get_frame_buffer(sc->sc_xfer[UATH_BULK_TX], 0);
+
 	/*
 	 * We're now ready to send+receive firmware commands.
 	 */
@@ -493,7 +493,7 @@
 fail4:	if_free(ifp);
 fail3:	UATH_UNLOCK(sc);
 fail2:	usbd_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
-fail1:	uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
+fail1:	uath_free_cmd_list(sc, sc->sc_cmd);
 fail:
 	return (error);
 }
@@ -524,7 +524,7 @@
 	UATH_LOCK(sc);
 	uath_free_rx_data_list(sc);
 	uath_free_tx_data_list(sc);
-	uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
+	uath_free_cmd_list(sc, sc->sc_cmd);
 	UATH_UNLOCK(sc);
 
 	if_free(ifp);
@@ -533,45 +533,35 @@
 }
 
 static void
-uath_free_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[], int ncmd)
+uath_free_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[])
 {
 	int i;
 
-	for (i = 0; i < ncmd; i++)
-		if (cmds[i].buf != NULL)
-			free(cmds[i].buf, M_USBDEV);
+	for (i = 0; i != UATH_CMD_LIST_COUNT; i++)
+		cmds[i].buf = NULL;
 }
 
 static int
-uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[],
-	int ncmd, int maxsz)
+uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[])
 {
-	int i, error;
+	int i;
 
 	STAILQ_INIT(&sc->sc_cmd_active);
 	STAILQ_INIT(&sc->sc_cmd_pending);
 	STAILQ_INIT(&sc->sc_cmd_waiting);
 	STAILQ_INIT(&sc->sc_cmd_inactive);
 
-	for (i = 0; i < ncmd; i++) {
+	for (i = 0; i != UATH_CMD_LIST_COUNT; i++) {
 		struct uath_cmd *cmd = &cmds[i];
 
 		cmd->sc = sc;	/* backpointer for callbacks */
 		cmd->msgid = i;
-		cmd->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
-		if (cmd->buf == NULL) {
-			device_printf(sc->sc_dev,
-			    "could not allocate xfer buffer\n");
-			error = ENOMEM;
-			goto fail;
-		}
+		cmd->buf = ((uint8_t *)sc->sc_cmd_dma_buf) +
+		    (i * UATH_MAX_CMDSZ);
 		STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next);
 		UATH_STAT_INC(sc, st_cmd_inactive);
 	}
 	return (0);
-
-fail:	uath_free_cmd_list(sc, cmds, ncmd);
-	return (error);
 }
 
 static int
@@ -942,10 +932,7 @@
 				dp->buf = NULL;
 			}
 		} else {
-			if (dp->buf != NULL) {
-				free(dp->buf, M_USBDEV);
-				dp->buf = NULL;
-			}
+			dp->buf = NULL;
 		}
 #ifdef UATH_DEBUG
 		if (dp->ni != NULL)
@@ -956,7 +943,7 @@
 
 static int
 uath_alloc_data_list(struct uath_softc *sc, struct uath_data data[],
-	int ndata, int maxsz, int fillmbuf)
+    int ndata, int maxsz, void *dma_buf)
 {
 	int i, error;
 
@@ -964,7 +951,7 @@
 		struct uath_data *dp = &data[i];
 
 		dp->sc = sc;
-		if (fillmbuf) {
+		if (dma_buf == NULL) {
 			/* XXX check maxsz */
 			dp->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
 			if (dp->m == NULL) {
@@ -976,20 +963,14 @@
 			dp->buf = mtod(dp->m, uint8_t *);
 		} else {
 			dp->m = NULL;
-			dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
-			if (dp->buf == NULL) {
-				device_printf(sc->sc_dev,
-				    "could not allocate buffer\n");
-				error = ENOMEM;
-				goto fail;
-			}
+			dp->buf = ((uint8_t *)dma_buf) + (i * maxsz);
 		}
 		dp->ni = NULL;
 	}
 
 	return (0);
 
-fail:	uath_free_data_list(sc, data, ndata, fillmbuf);
+fail:	uath_free_data_list(sc, data, ndata, 1 /* free mbufs */);
 	return (error);
 }
 
@@ -1001,7 +982,7 @@
 	/* XXX is it enough to store the RX packet with MCLBYTES bytes?  */
 	error = uath_alloc_data_list(sc,
 	    sc->sc_rx, UATH_RX_DATA_LIST_COUNT, MCLBYTES,
-	    1 /* setup mbufs */);
+	    NULL /* setup mbufs */);
 	if (error != 0)
 		return (error);
 
@@ -1024,7 +1005,7 @@
 
 	error = uath_alloc_data_list(sc,
 	    sc->sc_tx, UATH_TX_DATA_LIST_COUNT, UATH_MAX_TXBUFSZ,
-	    0 /* no mbufs */);
+	    sc->sc_tx_dma_buf);
 	if (error != 0)
 		return (error);
 
@@ -2741,8 +2722,7 @@
 		UATH_STAT_DEC(sc, st_rx_inactive);
 		STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next);
 		UATH_STAT_INC(sc, st_rx_active);
-		usbd_xfer_set_frame_data(xfer, 0, data->buf,
-		    usbd_xfer_max_len(xfer));
+		usbd_xfer_set_frame_data(xfer, 0, data->buf, MCLBYTES);
 		usbd_transfer_submit(xfer);
 
 		/*
=== dev/usb/wlan/if_uathvar.h
==================================================================
--- dev/usb/wlan/if_uathvar.h	(revision 244051)
+++ dev/usb/wlan/if_uathvar.h	(local)
@@ -186,6 +186,8 @@
 	struct ifnet			*sc_ifp;
 	device_t			sc_dev;
 	struct usb_device		*sc_udev;
+	void				*sc_cmd_dma_buf;
+	void				*sc_tx_dma_buf;
 	struct mtx			sc_mtx;
 	uint32_t			sc_debug;
 
=== dev/usb/wlan/if_upgt.c
==================================================================
--- dev/usb/wlan/if_upgt.c	(revision 244051)
+++ dev/usb/wlan/if_upgt.c	(local)
@@ -201,9 +201,8 @@
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_OUT,
-		.bufsize = MCLBYTES,
+		.bufsize = MCLBYTES * UPGT_TX_MAXCOUNT,
 		.flags = {
-			.ext_buffer = 1,
 			.force_short_xfer = 1,
 			.pipe_bof = 1
 		},
@@ -214,9 +213,8 @@
 		.type = UE_BULK,
 		.endpoint = UE_ADDR_ANY,
 		.direction = UE_DIR_IN,
-		.bufsize = MCLBYTES,
+		.bufsize = MCLBYTES * UPGT_RX_MAXCOUNT,
 		.flags = {
-			.ext_buffer = 1,
 			.pipe_bof = 1,
 			.short_xfer_ok = 1
 		},
@@ -277,6 +275,11 @@
 		goto fail3;
 	}
 
+	sc->sc_rx_dma_buf = usbd_xfer_get_frame_buffer(
+	    sc->sc_xfer[UPGT_BULK_RX], 0);
+	sc->sc_tx_dma_buf = usbd_xfer_get_frame_buffer(
+	    sc->sc_xfer[UPGT_BULK_TX], 0);
+
 	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
 	if (ifp == NULL) {
 		device_printf(dev, "can not if_alloc()\n");
@@ -1952,13 +1955,7 @@
 
 	for (i = 0; i < UPGT_TX_MAXCOUNT; i++) {
 		struct upgt_data *data = &sc->sc_tx_data[i];
-
-		data->buf = malloc(MCLBYTES, M_USBDEV, M_NOWAIT | M_ZERO);
-		if (data->buf == NULL) {
-			device_printf(sc->sc_dev,
-			    "could not allocate TX buffer\n");
-			return (ENOMEM);
-		}
+		data->buf = ((uint8_t *)sc->sc_tx_dma_buf) + (i * MCLBYTES);
 		STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next);
 		UPGT_STAT_INC(sc, st_tx_inactive);
 	}
@@ -1976,13 +1973,7 @@
 
 	for (i = 0; i < UPGT_RX_MAXCOUNT; i++) {
 		struct upgt_data *data = &sc->sc_rx_data[i];
-
-		data->buf = malloc(MCLBYTES, M_USBDEV, M_NOWAIT | M_ZERO);
-		if (data->buf == NULL) {
-			device_printf(sc->sc_dev,
-			    "could not allocate RX buffer\n");
-			return (ENOMEM);
-		}
+		data->buf = ((uint8_t *)sc->sc_rx_dma_buf) + (i * MCLBYTES);
 		STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
 	}
 
@@ -2023,7 +2014,7 @@
 	for (i = 0; i < UPGT_RX_MAXCOUNT; i++) {
 		struct upgt_data *data = &sc->sc_rx_data[i];
 
-		free(data->buf, M_USBDEV);
+		data->buf = NULL;
 		data->ni = NULL;
 	}
 }
@@ -2036,7 +2027,7 @@
 	for (i = 0; i < UPGT_TX_MAXCOUNT; i++) {
 		struct upgt_data *data = &sc->sc_tx_data[i];
 
-		free(data->buf, M_USBDEV);
+		data->buf = NULL;
 		data->ni = NULL;
 	}
 }
@@ -2278,8 +2269,7 @@
 			return;
 		STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next);
 		STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next);
-		usbd_xfer_set_frame_data(xfer, 0, data->buf,
-		    usbd_xfer_max_len(xfer));
+		usbd_xfer_set_frame_data(xfer, 0, data->buf, MCLBYTES);
 		usbd_transfer_submit(xfer);
 
 		/*
=== dev/usb/wlan/if_upgtvar.h
==================================================================
--- dev/usb/wlan/if_upgtvar.h	(revision 244051)
+++ dev/usb/wlan/if_upgtvar.h	(local)
@@ -422,6 +422,8 @@
 	device_t		 sc_dev;
 	struct ifnet		*sc_ifp;
 	struct usb_device	*sc_udev;
+	void			*sc_rx_dma_buf;
+	void			*sc_tx_dma_buf;
 	struct mtx		 sc_mtx;
 	struct upgt_stat	 sc_stat;
 	int			 sc_flags;
=== dev/usb/wlan/if_urtw.c
==================================================================
--- dev/usb/wlan/if_urtw.c	(revision 244051)
+++ dev/usb/wlan/if_urtw.c	(local)
@@ -532,9 +532,8 @@
 		.type = UE_BULK,
 		.endpoint = 0x89,
 		.direction = UE_DIR_IN,
-		.bufsize = MCLBYTES,
+		.bufsize = sizeof(uint64_t),
 		.flags = {
-			.ext_buffer = 1,
 			.pipe_bof = 1,
 			.short_xfer_ok = 1
 		},
@@ -544,9 +543,8 @@
 		.type = UE_BULK,
 		.endpoint = URTW_8187B_TXPIPE_BE,
 		.direction = UE_DIR_OUT,
-		.bufsize = URTW_TX_MAXSIZE,
+		.bufsize = URTW_TX_MAXSIZE * URTW_TX_DATA_LIST_COUNT,
 		.flags = {
-			.ext_buffer = 1,
 			.force_short_xfer = 1,
 			.pipe_bof = 1,
 		},
@@ -624,9 +622,8 @@
 		.type = UE_BULK,
 		.endpoint = 0x2,
 		.direction = UE_DIR_OUT,
-		.bufsize = URTW_TX_MAXSIZE,
+		.bufsize = URTW_TX_MAXSIZE * URTW_TX_DATA_LIST_COUNT,
 		.flags = {
-			.ext_buffer = 1,
 			.force_short_xfer = 1,
 			.pipe_bof = 1,
 		},
@@ -827,6 +824,16 @@
 		goto fail0;
 	}
 
+	if (sc->sc_flags & URTW_RTL8187B) {
+		sc->sc_tx_dma_buf = 
+		    usbd_xfer_get_frame_buffer(sc->sc_xfer[
+		    URTW_8187B_BULK_TX_BE], 0);
+	} else {
+		sc->sc_tx_dma_buf =
+		    usbd_xfer_get_frame_buffer(sc->sc_xfer[
+		    URTW_8187L_BULK_TX_LOW], 0);
+	}
+
 	URTW_LOCK(sc);
 
 	urtw_read32_m(sc, URTW_RX, &data);
@@ -980,10 +987,7 @@
 				dp->buf = NULL;
 			}
 		} else {
-			if (dp->buf != NULL) {
-				free(dp->buf, M_USBDEV);
-				dp->buf = NULL;
-			}
+			dp->buf = NULL;
 		}
 		if (dp->ni != NULL) {
 			ieee80211_free_node(dp->ni);
@@ -1449,7 +1453,7 @@
 
 static int
 urtw_alloc_data_list(struct urtw_softc *sc, struct urtw_data data[],
-	int ndata, int maxsz, int fillmbuf)
+    int ndata, int maxsz, void *dma_buf)
 {
 	int i, error;
 
@@ -1457,7 +1461,7 @@
 		struct urtw_data *dp = &data[i];
 
 		dp->sc = sc;
-		if (fillmbuf) {
+		if (dma_buf == NULL) {
 			dp->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
 			if (dp->m == NULL) {
 				device_printf(sc->sc_dev,
@@ -1468,24 +1472,15 @@
 			dp->buf = mtod(dp->m, uint8_t *);
 		} else {
 			dp->m = NULL;
-			dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
-			if (dp->buf == NULL) {
-				device_printf(sc->sc_dev,
-				    "could not allocate buffer\n");
-				error = ENOMEM;
-				goto fail;
-			}
-			if (((unsigned long)dp->buf) % 4)
-				device_printf(sc->sc_dev,
-				    "warn: unaligned buffer %p\n", dp->buf);
+			dp->buf = ((uint8_t *)dma_buf) +
+			    (i * maxsz);
 		}
 		dp->ni = NULL;
 	}
+	return (0);
 
-	return 0;
-
-fail:	urtw_free_data_list(sc, data, ndata, fillmbuf);
-	return error;
+fail:	urtw_free_data_list(sc, data, ndata, 1);
+	return (error);
 }
 
 static int
@@ -1494,7 +1489,8 @@
 	int error, i;
 
 	error = urtw_alloc_data_list(sc,
-	    sc->sc_rx, URTW_RX_DATA_LIST_COUNT, MCLBYTES, 1 /* mbufs */);
+	    sc->sc_rx, URTW_RX_DATA_LIST_COUNT,
+	    MCLBYTES, NULL /* mbufs */);
 	if (error != 0)
 		return (error);
 
@@ -1514,7 +1510,7 @@
 
 	error = urtw_alloc_data_list(sc,
 	    sc->sc_tx, URTW_TX_DATA_LIST_COUNT, URTW_TX_MAXSIZE,
-	    0 /* no mbufs */);
+	    sc->sc_tx_dma_buf /* no mbufs */);
 	if (error != 0)
 		return (error);
 
@@ -2709,42 +2705,28 @@
 	return (error);
 }
 
-/* XXX why we should allocalte memory buffer instead of using memory stack?  */
 static usb_error_t
 urtw_8225_write_s16(struct urtw_softc *sc, uint8_t addr, int index,
     uint16_t *data)
 {
-	uint8_t *buf;
+	uint8_t buf[2];
 	uint16_t data16;
-	struct usb_device_request *req;
+	struct usb_device_request req;
 	usb_error_t error = 0;
 
 	data16 = *data;
-	req = (usb_device_request_t *)malloc(sizeof(usb_device_request_t),
-	    M_80211_VAP, M_NOWAIT | M_ZERO);
-	if (req == NULL) {
-		device_printf(sc->sc_dev, "could not allocate a memory\n");
-		goto fail0;
-	}
-	buf = (uint8_t *)malloc(2, M_80211_VAP, M_NOWAIT | M_ZERO);
-	if (req == NULL) {
-		device_printf(sc->sc_dev, "could not allocate a memory\n");
-		goto fail1;
-	}
 
-	req->bmRequestType = UT_WRITE_VENDOR_DEVICE;
-	req->bRequest = URTW_8187_SETREGS_REQ;
-	USETW(req->wValue, addr);
-	USETW(req->wIndex, index);
-	USETW(req->wLength, sizeof(uint16_t));
+	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+	req.bRequest = URTW_8187_SETREGS_REQ;
+	USETW(req.wValue, addr);
+	USETW(req.wIndex, index);
+	USETW(req.wLength, sizeof(uint16_t));
 	buf[0] = (data16 & 0x00ff);
 	buf[1] = (data16 & 0xff00) >> 8;
 
-	error = urtw_do_request(sc, req, buf);
+	error = urtw_do_request(sc, &req, buf);
 
-	free(buf, M_80211_VAP);
-fail1:	free(req, M_80211_VAP);
-fail0:	return (error);
+	return (error);
 }
 
 static usb_error_t
@@ -4133,6 +4115,7 @@
 {
 	struct urtw_softc *sc = usbd_xfer_softc(xfer);
 	struct ifnet *ifp = sc->sc_ifp;
+	void *dma_buf = usbd_xfer_get_frame_buffer(xfer, 0);
 
 	URTW_ASSERT_LOCKED(sc);
 
@@ -4142,8 +4125,7 @@
 		/* FALLTHROUGH */
 	case USB_ST_SETUP:
 setup:
-		usbd_xfer_set_frame_data(xfer, 0, &sc->sc_txstatus,
-		    sizeof(int64_t));
+		memcpy(dma_buf, &sc->sc_txstatus, sizeof(uint64_t));
 		usbd_transfer_submit(xfer);
 		break;
 	default:
=== dev/usb/wlan/if_urtwvar.h
==================================================================
--- dev/usb/wlan/if_urtwvar.h	(revision 244051)
+++ dev/usb/wlan/if_urtwvar.h	(local)
@@ -97,6 +97,7 @@
 	device_t			sc_dev;
 	struct usb_device		*sc_udev;
 	struct mtx			sc_mtx;
+	void				*sc_tx_dma_buf;
 
 	int				sc_debug;
 	int				sc_if_flags;

--Boundary-00=_Kuw0QlgeVxE9A/+--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212201358.50067.hselasky>