# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.474.2.3 -> 1.474.2.4
#	drivers/usb/host/ehci-q.c	1.21    -> 1.22   
#	drivers/usb/host/ehci-sched.c	1.16    -> 1.17   
#	drivers/usb/host/ohci-sa1111.c	1.4     -> 1.5    
#	drivers/usb/host/uhci-hcd.h	1.1     -> 1.2    
#	drivers/usb/host/ehci.h	1.6     -> 1.7    
#	drivers/usb/host/uhci-hcd.c	1.9     -> 1.10   
#	drivers/usb/host/ohci-q.c	1.18    -> 1.19   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/08/13	david-b@pacbell.net	1.474.2.4
# [PATCH] HCDs support new DMA APIs (part 1 of 2)
# 
# -  teaches the hardware-specific code to
#    use urb->*_dma instead of creating mappings.
#    (And tells ohci-sa1111 to init its buffer pools.)
#    EHCI and UHCI also eliminated duplicated state;
#    all the HCDs are now a smidgeon smaller.
# 
# Sanity checked by enumerating, including through
# a hub, and using a USB Ethernet adapter, with each
# of the three host controllers.
# 
# Worth noting:  this removes pci_dma_sync_single()
# calls from UHCI.  On x86 (and some others) that's
# a NOP, but for UHCI on other platforms (rare except
# maybe on IA64, as I understand) this anticipates
# the upcoming patch to remove interrupt automagic.
# (I'll likely submit that after a Linus release that
# catches up to your USB tree. :)
# --------------------------------------------
#
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c	Tue Aug 13 15:34:06 2002
+++ b/drivers/usb/host/ehci-q.c	Tue Aug 13 15:34:06 2002
@@ -163,7 +163,6 @@
 
 static void ehci_urb_done (
 	struct ehci_hcd		*ehci,
-	dma_addr_t		addr,
 	struct urb		*urb
 ) {
 #ifdef	INTR_AUTOMAGIC
@@ -171,13 +170,6 @@
 	struct usb_device	*dev = 0;
 #endif
 
-	if (urb->transfer_buffer_length)
-		pci_unmap_single (ehci->hcd.pdev,
-			addr,
-			urb->transfer_buffer_length,
-			usb_pipein (urb->pipe)
-			    ? PCI_DMA_FROMDEVICE
-			    : PCI_DMA_TODEVICE);
 	if (likely (urb->hcpriv != 0)) {
 		struct ehci_qh	*qh = (struct ehci_qh *) urb->hcpriv;
 
@@ -263,7 +255,7 @@
 			if (likely (last->urb != urb)) {
 				/* complete() can reenter this HCD */
 				spin_unlock_irqrestore (&ehci->lock, flags);
-				ehci_urb_done (ehci, last->buf_dma, last->urb);
+				ehci_urb_done (ehci, last->urb);
 				spin_lock_irqsave (&ehci->lock, flags);
 			}
 
@@ -347,12 +339,6 @@
 				urb, urb->status, qtd, token,
 				urb->actual_length);
 #endif
-
-		/* SETUP for control urb? */
-		if (unlikely (QTD_PID (token) == 2))
-			pci_unmap_single (ehci->hcd.pdev,
-				qtd->buf_dma, sizeof (struct usb_ctrlrequest),
-				PCI_DMA_TODEVICE);
 	}
 
 	/* patch up list head? */
@@ -364,7 +350,7 @@
 
 	/* last urb's completion might still need calling */
 	if (likely (last != 0)) {
-		ehci_urb_done (ehci, last->buf_dma, last->urb);
+		ehci_urb_done (ehci, last->urb);
 		ehci_qtd_free (ehci, last);
 	}
 }
@@ -405,10 +391,6 @@
 				size = qtd->urb->transfer_buffer_length;
 				unmapped++;
 			}
-			if (qtd->buf_dma)
-				pci_unmap_single (ehci->hcd.pdev,
-					qtd->buf_dma,
-					size, direction);
 		}
 		ehci_qtd_free (ehci, qtd);
 	}
@@ -425,7 +407,7 @@
 	int			flags
 ) {
 	struct ehci_qtd		*qtd, *qtd_prev;
-	dma_addr_t		buf, map_buf;
+	dma_addr_t		buf;
 	int			len, maxpacket;
 	int			is_input;
 	u32			token;
@@ -445,17 +427,8 @@
 	/* for split transactions, SplitXState initialized to zero */
 
 	if (usb_pipecontrol (urb->pipe)) {
-		/* control request data is passed in the "setup" pid */
-		qtd->buf_dma = pci_map_single (
-					ehci->hcd.pdev,
-					urb->setup_packet,
-					sizeof (struct usb_ctrlrequest),
-					PCI_DMA_TODEVICE);
-		if (unlikely (!qtd->buf_dma))
-			goto cleanup;
-
 		/* SETUP pid */
-		qtd_fill (qtd, qtd->buf_dma, sizeof (struct usb_ctrlrequest),
+		qtd_fill (qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest),
 			token | (2 /* "setup" */ << 8));
 
 		/* ... and always at least one more pid */
@@ -474,16 +447,10 @@
 	 */
 	len = urb->transfer_buffer_length;
 	is_input = usb_pipein (urb->pipe);
-	if (likely (len > 0)) {
-		buf = map_buf = pci_map_single (ehci->hcd.pdev,
-			urb->transfer_buffer, len,
-			is_input
-			    ? PCI_DMA_FROMDEVICE
-			    : PCI_DMA_TODEVICE);
-		if (unlikely (!buf))
-			goto cleanup;
-	} else
-		buf = map_buf = 0;
+	if (likely (len > 0))
+		buf = urb->transfer_dma;
+	else
+		buf = 0;
 
 	if (!buf || is_input)
 		token |= (1 /* "in" */ << 8);
@@ -500,7 +467,6 @@
 		int this_qtd_len;
 
 		qtd->urb = urb;
-		qtd->buf_dma = map_buf;
 		this_qtd_len = qtd_fill (qtd, buf, len, token);
 		len -= this_qtd_len;
 		buf += this_qtd_len;
diff -Nru a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
--- a/drivers/usb/host/ehci-sched.c	Tue Aug 13 15:34:06 2002
+++ b/drivers/usb/host/ehci-sched.c	Tue Aug 13 15:34:06 2002
@@ -530,11 +530,6 @@
 {
 	struct ehci_itd *first_itd = urb->hcpriv;
 
-	pci_unmap_single (ehci->hcd.pdev,
-		first_itd->buf_dma, urb->transfer_buffer_length,
-		usb_pipein (urb->pipe)
-		    ? PCI_DMA_FROMDEVICE
-		    : PCI_DMA_TODEVICE);
 	while (!list_empty (&first_itd->itd_list)) {
 		struct ehci_itd	*itd;
 
@@ -630,16 +625,7 @@
 	int			frame_index;
 	struct ehci_itd		*first_itd, *itd;
 	int			status;
-	dma_addr_t		buf_dma, itd_dma;
-
-	/* set up one dma mapping for this urb */
-	buf_dma = pci_map_single (ehci->hcd.pdev,
-		urb->transfer_buffer, urb->transfer_buffer_length,
-		usb_pipein (urb->pipe)
-		    ? PCI_DMA_FROMDEVICE
-		    : PCI_DMA_TODEVICE);
-	if (buf_dma == 0)
-		return -ENOMEM;
+	dma_addr_t		itd_dma;
 
 	/* allocate/init ITDs */
 	for (frame_index = 0, first_itd = 0;
@@ -653,7 +639,8 @@
 		memset (itd, 0, sizeof *itd);
 		itd->itd_dma = itd_dma;
 
-		status = itd_fill (ehci, itd, urb, frame_index, buf_dma);
+		status = itd_fill (ehci, itd, urb, frame_index,
+				urb->transfer_dma);
 		if (status != 0)
 			goto fail;
 
diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
--- a/drivers/usb/host/ehci.h	Tue Aug 13 15:34:06 2002
+++ b/drivers/usb/host/ehci.h	Tue Aug 13 15:34:06 2002
@@ -219,7 +219,6 @@
 
 	/* dma same in urb's qtds, except 1st control qtd (setup buffer) */
 	struct urb		*urb;			/* qtd's urb */
-	dma_addr_t		buf_dma;		/* buffer address */
 	size_t			length;			/* length of buffer */
 } __attribute__ ((aligned (32)));
 
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	Tue Aug 13 15:34:06 2002
+++ b/drivers/usb/host/ohci-q.c	Tue Aug 13 15:34:06 2002
@@ -14,27 +14,8 @@
 
 	if (last >= 0) {
 		int		i;
-		struct td	*td = urb_priv->td [0];
-		int		len = td->urb->transfer_buffer_length;
-		int		dir = usb_pipeout (td->urb->pipe)
-					? PCI_DMA_TODEVICE
-					: PCI_DMA_FROMDEVICE;
-
-		/* unmap CTRL URB setup buffer (always td 0) */
-		if (usb_pipecontrol (td->urb->pipe)) {
-			pci_unmap_single (hc->hcd.pdev, 
-					td->data_dma, 8, PCI_DMA_TODEVICE);
-			
-			/* CTRL data buffer starts at td 1 if len > 0 */
-			if (len && last > 0)
-				td = urb_priv->td [1]; 		
-		}
-		/* else:  ISOC, BULK, INTR data buffer starts at td 0 */
-
-		/* unmap data buffer */
-		if (len && td->data_dma)
-			pci_unmap_single (hc->hcd.pdev,
-					td->data_dma, len, dir);
+		struct td	*td;
+
 		for (i = 0; i <= last; i++) {
 			td = urb_priv->td [i];
 			if (td)
@@ -85,15 +66,8 @@
 	struct urb_priv	*urb_priv = urb->hcpriv;
 	unsigned long	flags;
 
-// FIXME rewrite this resubmit path.  use pci_dma_sync_single()
-// and requeue more cheaply, and only if needed.
-// Better yet ... abolish the notion of automagic resubmission.
-	pci_unmap_single (hc->hcd.pdev,
-		urb_priv->td [0]->data_dma,
-		urb->transfer_buffer_length,
-		usb_pipeout (urb->pipe)
-			? PCI_DMA_TODEVICE
-			: PCI_DMA_FROMDEVICE);
+// FIXME going away along with the rest of interrrupt automagic...
+
 	/* FIXME: MP race.  If another CPU partially unlinks
 	 * this URB (urb->status was updated, hasn't yet told
 	 * us to dequeue) before we call complete() here, an
@@ -612,13 +586,9 @@
 
 	urb_priv->td_cnt = 0;
 
-	if (data_len) {
-		data = pci_map_single (ohci->hcd.pdev,
-				       urb->transfer_buffer, data_len,
-				       is_out
-					       ? PCI_DMA_TODEVICE
-					       : PCI_DMA_FROMDEVICE);
-	} else
+	if (data_len)
+		data = urb->transfer_dma;
+	else
 		data = 0;
 
 	/* NOTE:  TD_CC is set so we can tell which TDs the HC processed by
@@ -665,11 +635,7 @@
 	 */
 	case PIPE_CONTROL:
 		info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
-		td_fill (info,
-			pci_map_single (ohci->hcd.pdev,
-					urb->setup_packet, 8,
-					PCI_DMA_TODEVICE),
-			 8, urb, cnt++);
+		td_fill (info, urb->setup_dma, 8, urb, cnt++);
 		if (data_len > 0) {
 			info = TD_CC | TD_R | TD_T_DATA1;
 			info |= is_out ? TD_DP_OUT : TD_DP_IN;
diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
--- a/drivers/usb/host/ohci-sa1111.c	Tue Aug 13 15:34:06 2002
+++ b/drivers/usb/host/ohci-sa1111.c	Tue Aug 13 15:34:06 2002
@@ -161,6 +161,12 @@
 	hcd->regs = (void *) &USB_OHCI_OP_BASE;
 	hcd->pdev = SA1111_FAKE_PCIDEV;
 
+	retval = hcd_buffer_create (hcd);
+	if (retval != 0) {
+		dbg ("pool alloc fail");
+		goto err1;
+	}
+
 	set_irq_type(NIRQHCIM, IRQT_RISING);
 	retval = request_irq (NIRQHCIM, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT,
 			      hcd->description, hcd);
@@ -193,6 +199,7 @@
 	return 0;
 
  err2:
+	hcd_buffer_destroy (hcd);
 	if (hcd) driver->hcd_free(hcd);
  err1:
 	sa1111_stop_hc();
@@ -233,6 +240,7 @@
 	hcd->state = USB_STATE_HALT;
 
 	free_irq (hcd->irq, hcd);
+	hcd_buffer_destroy (hcd);
 
 	usb_deregister_bus (&hcd->self);
 	if (atomic_read (&hcd->self.refcnt) != 1)
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	Tue Aug 13 15:34:06 2002
+++ b/drivers/usb/host/uhci-hcd.c	Tue Aug 13 15:34:06 2002
@@ -646,23 +646,6 @@
 
 	urb->hcpriv = urbp;
 
-	if (urb->transfer_buffer_length) {
-		urbp->transfer_buffer_dma_handle = pci_map_single(uhci->dev,
-			urb->transfer_buffer, urb->transfer_buffer_length,
-			usb_pipein(urb->pipe) ? PCI_DMA_FROMDEVICE :
-			PCI_DMA_TODEVICE);
-		if (!urbp->transfer_buffer_dma_handle)
-			return NULL;
-	}
-
-	if (usb_pipetype(urb->pipe) == PIPE_CONTROL && urb->setup_packet) {
-		urbp->setup_packet_dma_handle = pci_map_single(uhci->dev,
-			urb->setup_packet, sizeof(struct usb_ctrlrequest),
-			PCI_DMA_TODEVICE);
-		if (!urbp->setup_packet_dma_handle)
-			return NULL;
-	}
-
 	return urbp;
 }
 
@@ -721,19 +704,6 @@
 		uhci_free_td(uhci, td);
 	}
 
-	if (urbp->setup_packet_dma_handle) {
-		pci_unmap_single(uhci->dev, urbp->setup_packet_dma_handle,
-			sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
-		urbp->setup_packet_dma_handle = 0;
-	}
-
-	if (urbp->transfer_buffer_dma_handle) {
-		pci_unmap_single(uhci->dev, urbp->transfer_buffer_dma_handle,
-			urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
-			PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
-		urbp->transfer_buffer_dma_handle = 0;
-	}
-
 	urb->hcpriv = NULL;
 	kmem_cache_free(uhci_up_cachep, urbp);
 }
@@ -813,7 +783,7 @@
 	unsigned long destination, status;
 	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
 	int len = urb->transfer_buffer_length;
-	dma_addr_t data = urbp->transfer_buffer_dma_handle;
+	dma_addr_t data = urb->transfer_dma;
 
 	/* The "pipe" thing contains the destination in bits 8--18 */
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
@@ -832,7 +802,7 @@
 
 	uhci_add_td_to_urb(urb, td);
 	uhci_fill_td(td, status, destination | uhci_explen(7),
-		urbp->setup_packet_dma_handle);
+		urb->setup_dma);
 
 	/*
 	 * If direction is "send", change the frame from SETUP (0x2D)
@@ -1072,7 +1042,6 @@
 {
 	struct uhci_td *td;
 	unsigned long destination, status;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 
 	if (urb->transfer_buffer_length > usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))
 		return -EINVAL;
@@ -1094,7 +1063,7 @@
 	usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
 
 	uhci_add_td_to_urb(urb, td);
-	uhci_fill_td(td, status, destination, urbp->transfer_buffer_dma_handle);
+	uhci_fill_td(td, status, destination, urb->transfer_dma);
 
 	uhci_insert_td(uhci, uhci->skeltd[__interval_to_skel(urb->interval)], td);
 
@@ -1196,7 +1165,7 @@
 	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
 	int len = urb->transfer_buffer_length;
 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	dma_addr_t data = urbp->transfer_buffer_dma_handle;
+	dma_addr_t data = urb->transfer_dma;
 
 	if (len < 0)
 		return -EINVAL;
@@ -1358,7 +1327,6 @@
 	struct uhci_td *td;
 	int i, ret, frame;
 	int status, destination;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 
 	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
@@ -1378,7 +1346,7 @@
 
 		uhci_add_td_to_urb(urb, td);
 		uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1),
-			urbp->transfer_buffer_dma_handle + urb->iso_frame_desc[i].offset);
+			urb->transfer_dma + urb->iso_frame_desc[i].offset);
 
 		if (i + 1 >= urb->number_of_packets)
 			td->status |= cpu_to_le32(TD_CTRL_IOC);
@@ -1831,15 +1799,6 @@
 			urb->status == -ECONNRESET);
 	resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT &&
 			urb->interval);
-
-	if (urbp->transfer_buffer_dma_handle)
-		pci_dma_sync_single(uhci->dev, urbp->transfer_buffer_dma_handle,
-			urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
-			PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
-
-	if (urbp->setup_packet_dma_handle)
-		pci_dma_sync_single(uhci->dev, urbp->setup_packet_dma_handle,
-			sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
 
 	status = urbp->status;
 	if (!resubmit_interrupt || killed)
diff -Nru a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
--- a/drivers/usb/host/uhci-hcd.h	Tue Aug 13 15:34:06 2002
+++ b/drivers/usb/host/uhci-hcd.h	Tue Aug 13 15:34:06 2002
@@ -338,9 +338,6 @@
 	struct urb *urb;
 	struct usb_device *dev;
 
-	dma_addr_t setup_packet_dma_handle;
-	dma_addr_t transfer_buffer_dma_handle;
-
 	struct uhci_qh *qh;		/* QH for this URB */
 	struct list_head td_list;	/* P: urb->lock */
 
