All of lore.kernel.org
 help / color / mirror / Atom feed
From: Albert Herranz <albert_herranz@yahoo.es>
To: linux-usb@vger.kernel.org, linuxppc-dev@lists.ozlabs.org
Cc: Albert Herranz <albert_herranz@yahoo.es>
Subject: [RFC PATCH v3 06/11] USB: refactor unmap_urb_for_dma/map_urb_for_dma
Date: Sun,  7 Mar 2010 13:11:47 +0100	[thread overview]
Message-ID: <1267963912-984-7-git-send-email-albert_herranz@yahoo.es> (raw)
In-Reply-To: <1267963912-984-1-git-send-email-albert_herranz@yahoo.es>

Split unmap_urb_for_dma() and map_urb_for_dma() into smaller pieces
to make the code easier to read and maintain.

This patch adds four new URB flags which are used by map_urb_for_dma()
to mark URBs with the exact method used to map the setup packet and/or the
transfer buffer.
These flags are checked too at unmap_urb_for_dma() time to determine how
to unmap the setup packet and/or the transfer buffer. The flags are cleared
when the actual unmap happens.

No functional change.

Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
---
 drivers/usb/core/hcd.c |  211 +++++++++++++++++++++++++++++++-----------------
 include/linux/usb.h    |    5 +
 2 files changed, 143 insertions(+), 73 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 80995ef..44ad710 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1260,106 +1260,171 @@ static void hcd_free_coherent(struct usb_bus *bus, dma_addr_t *dma_handle,
 	*dma_handle = 0;
 }
 
-static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
-			   gfp_t mem_flags)
+static void unmap_urb_setup_packet(struct usb_hcd *hcd, struct urb *urb)
+{
+	if (urb->transfer_flags & URB_SETUP_DMA_MAPPED) {
+		urb->transfer_flags &= ~URB_SETUP_DMA_MAPPED;
+		dma_unmap_single(hcd->self.controller, urb->setup_dma,
+				 sizeof(struct usb_ctrlrequest),
+				 DMA_TO_DEVICE);
+	} else if (urb->transfer_flags & URB_SETUP_BOUNCE_MAPPED) {
+		/* bounce from "local" memory */
+		urb->transfer_flags &= ~URB_SETUP_BOUNCE_MAPPED;
+		hcd_free_coherent(urb->dev->bus, &urb->setup_dma,
+				  (void **)&urb->setup_packet,
+				  sizeof(struct usb_ctrlrequest),
+				  DMA_TO_DEVICE);
+	} else {
+		/* nothing to do for PIO-based controller requests */
+	}
+}
+
+static void unmap_urb_transfer_buffer(struct usb_hcd *hcd, struct urb *urb)
 {
 	enum dma_data_direction dir;
-	int ret = 0;
 
-	/* Map the URB's buffers for DMA access.
-	 * Lower level HCD code should use *_dma exclusively,
-	 * unless it uses pio or talks to another transport,
-	 * or uses the provided scatter gather list for bulk.
-	 */
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	if (urb->transfer_flags & URB_TRANSFER_DMA_MAPPED) {
+		urb->transfer_flags &= ~URB_TRANSFER_DMA_MAPPED;
+		dma_unmap_single(hcd->self.controller,
+				 urb->transfer_dma,
+				 urb->transfer_buffer_length,
+				 dir);
+	} else if (urb->transfer_flags & URB_TRANSFER_BOUNCE_MAPPED) {
+		/* bounce from "local" memory */
+		urb->transfer_flags &= ~URB_TRANSFER_BOUNCE_MAPPED;
+		hcd_free_coherent(urb->dev->bus, &urb->transfer_dma,
+				  &urb->transfer_buffer,
+				  urb->transfer_buffer_length,
+				  dir);
+	} else {
+		/* nothing to do for PIO-based controller requests */
+	}
+}
+
+static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+{
 	if (is_root_hub(urb->dev))
+		return;
+
+	unmap_urb_setup_packet(hcd, urb);
+	unmap_urb_transfer_buffer(hcd, urb);
+}
+
+static int urb_needs_setup_map(struct usb_hcd *hcd, struct urb *urb)
+{
+	/* setup mappings are required only for control requests */
+	if (!usb_endpoint_xfer_control(&urb->ep->desc))
+		return 0;
+
+	/* If the caller set URB_NO_SETUP_DMA_MAP then no mapping is needed */
+	if ((urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
+		return 0;
+
+	return 1;
+}
+
+static int urb_needs_transfer_map(struct usb_hcd *hcd, struct urb *urb)
+{
+	/* don't need to map anything if there's nothing to map */
+	if (urb->transfer_buffer_length == 0)
 		return 0;
 
-	if (usb_endpoint_xfer_control(&urb->ep->desc)
-	    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
+	/* If the caller set URB_NO_SETUP_DMA_MAP then no mapping is needed */
+	if ((urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+		return 0;
+
+	return 1;
+}
+
+static int map_urb_setup_packet(struct usb_hcd *hcd, struct urb *urb,
+				gfp_t mem_flags)
+{
+	int ret;
+
+	if (urb_needs_setup_map(hcd, urb)) {
 		if (hcd->self.uses_dma) {
 			urb->setup_dma = dma_map_single(
-					hcd->self.controller,
-					urb->setup_packet,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
+						hcd->self.controller,
+						urb->setup_packet,
+						sizeof(struct usb_ctrlrequest),
+						DMA_TO_DEVICE);
 			if (dma_mapping_error(hcd->self.controller,
-						urb->setup_dma))
+					      urb->setup_dma))
 				return -EAGAIN;
-		} else if (hcd->driver->flags & HCD_LOCAL_MEM)
-			ret = hcd_alloc_coherent(
-					urb->dev->bus, mem_flags,
-					&urb->setup_dma,
-					(void **)&urb->setup_packet,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
+			urb->transfer_flags |= URB_SETUP_DMA_MAPPED;
+		} else if (hcd->driver->flags & HCD_LOCAL_MEM) {
+			/* bounce to "local" memory */
+			ret = hcd_alloc_coherent(urb->dev->bus, mem_flags,
+						 &urb->setup_dma,
+						 (void **)&urb->setup_packet,
+						 sizeof(struct usb_ctrlrequest),
+						 DMA_TO_DEVICE);
+			if (ret)
+				return ret;
+			urb->transfer_flags |= URB_SETUP_BOUNCE_MAPPED;
+		} else {
+			/* nothing to do for PIO-based controller requests */
+		}
 	}
+	return 0;
+}
+
+static int map_urb_transfer_buffer(struct usb_hcd *hcd, struct urb *urb,
+				   gfp_t mem_flags)
+{
+	enum dma_data_direction dir;
+	int ret;
 
 	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-	if (ret == 0 && urb->transfer_buffer_length != 0
-	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
+	if (urb_needs_transfer_map(hcd, urb)) {
 		if (hcd->self.uses_dma) {
 			urb->transfer_dma = dma_map_single (
-					hcd->self.controller,
-					urb->transfer_buffer,
-					urb->transfer_buffer_length,
-					dir);
+						hcd->self.controller,
+						urb->transfer_buffer,
+						urb->transfer_buffer_length,
+						dir);
 			if (dma_mapping_error(hcd->self.controller,
-						urb->transfer_dma))
+					      urb->transfer_dma))
 				return -EAGAIN;
+			urb->transfer_flags |= URB_TRANSFER_DMA_MAPPED;
 		} else if (hcd->driver->flags & HCD_LOCAL_MEM) {
-			ret = hcd_alloc_coherent(
-					urb->dev->bus, mem_flags,
-					&urb->transfer_dma,
-					&urb->transfer_buffer,
-					urb->transfer_buffer_length,
-					dir);
-
-			if (ret && usb_endpoint_xfer_control(&urb->ep->desc)
-			    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
-				hcd_free_coherent(urb->dev->bus,
-					&urb->setup_dma,
-					(void **)&urb->setup_packet,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
+			/* bounce to "local" memory */
+			ret = hcd_alloc_coherent(urb->dev->bus, mem_flags,
+						 &urb->transfer_dma,
+						 &urb->transfer_buffer,
+						 urb->transfer_buffer_length,
+						 dir);
+			if (ret)
+				return ret;
+			urb->transfer_flags |= URB_TRANSFER_BOUNCE_MAPPED;
+		} else {
+			/* nothing to do for PIO-based controller requests */
 		}
 	}
-	return ret;
+	return 0;
 }
 
-static void unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
+static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+			   gfp_t mem_flags)
 {
-	enum dma_data_direction dir;
+	int error;
 
+	/* Map the URB's buffers for DMA access.
+	 * Lower level HCD code should use *_dma exclusively,
+	 * unless it uses pio or talks to another transport,
+	 * or uses the provided scatter gather list for bulk.
+	 */
 	if (is_root_hub(urb->dev))
-		return;
-
-	if (usb_endpoint_xfer_control(&urb->ep->desc)
-	    && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) {
-		if (hcd->self.uses_dma)
-			dma_unmap_single(hcd->self.controller, urb->setup_dma,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
-		else if (hcd->driver->flags & HCD_LOCAL_MEM)
-			hcd_free_coherent(urb->dev->bus, &urb->setup_dma,
-					(void **)&urb->setup_packet,
-					sizeof(struct usb_ctrlrequest),
-					DMA_TO_DEVICE);
-	}
+		return 0;
 
-	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-	if (urb->transfer_buffer_length != 0
-	    && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
-		if (hcd->self.uses_dma)
-			dma_unmap_single(hcd->self.controller,
-					urb->transfer_dma,
-					urb->transfer_buffer_length,
-					dir);
-		else if (hcd->driver->flags & HCD_LOCAL_MEM)
-			hcd_free_coherent(urb->dev->bus, &urb->transfer_dma,
-					&urb->transfer_buffer,
-					urb->transfer_buffer_length,
-					dir);
+	error = map_urb_setup_packet(hcd, urb, mem_flags);
+	if (!error) {
+		error = map_urb_transfer_buffer(hcd, urb, mem_flags);
+		if (error)
+			unmap_urb_setup_packet(hcd, urb);
 	}
+	return error;
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/include/linux/usb.h b/include/linux/usb.h
index d7ace1b..5e99cbd 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -985,6 +985,11 @@ extern int usb_disabled(void);
 #define URB_DIR_OUT		0
 #define URB_DIR_MASK		URB_DIR_IN
 
+#define URB_SETUP_DMA_MAPPED		0x1000 /* via dma_map_single */
+#define URB_SETUP_BOUNCE_MAPPED		0x2000 /* via hcd_alloc_coherent */
+#define URB_TRANSFER_DMA_MAPPED		0x4000 /* via dma_map_single */
+#define URB_TRANSFER_BOUNCE_MAPPED	0x8000 /* via hcd_alloc_coherent */
+
 struct usb_iso_packet_descriptor {
 	unsigned int offset;
 	unsigned int length;		/* expected length */
-- 
1.6.3.3

  parent reply	other threads:[~2010-03-07 12:12 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-03-07 12:11 [RFC PATCH v3 00/11] wii: add usb 2.0 support Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 01/11] powerpc: add per-device dma coherent support Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 02/11] powerpc: add min_direct_dma_addr Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 03/11] swiotbl: add back swiotlb_alloc_boot() Albert Herranz
2010-03-07 12:11   ` Albert Herranz
2010-03-07 12:11   ` Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms Albert Herranz
2010-03-07 12:11   ` Albert Herranz
2010-03-07 12:11   ` Albert Herranz
2010-03-08 16:55   ` [LKML] " Konrad Rzeszutek Wilk
2010-03-08 16:55     ` [LKML] [RFC PATCH v3 04/11] swiotlb: support Konrad Rzeszutek Wilk
2010-03-08 16:55     ` [LKML] [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms Konrad Rzeszutek Wilk
2010-03-09 18:07     ` Albert Herranz
2010-03-09 18:07       ` [LKML] [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE Albert Herranz
2010-03-09 18:07       ` [LKML] [RFC PATCH v3 04/11] swiotlb: support NOT_COHERENT_CACHE PowerPC platforms Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 05/11] swiotlb: add swiotlb_set_default_size() Albert Herranz
2010-03-07 12:11   ` Albert Herranz
2010-03-07 12:11   ` Albert Herranz
2010-03-08 16:59   ` [LKML] " Konrad Rzeszutek Wilk
2010-03-08 16:59     ` [LKML] [RFC PATCH v3 05/11] swiotlb: add Konrad Rzeszutek Wilk
2010-03-08 16:59     ` [LKML] [RFC PATCH v3 05/11] swiotlb: add swiotlb_set_default_size() Konrad Rzeszutek Wilk
2010-03-09 18:38     ` Albert Herranz
2010-03-09 18:38       ` Albert Herranz
2010-03-09 18:38       ` Albert Herranz
2010-03-07 12:11 ` Albert Herranz [this message]
2010-03-07 12:11 ` [RFC PATCH v3 07/11] USB: add HCD_NO_COHERENT_MEM host controller driver flag Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 08/11] wii: have generic dma coherent Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 09/11] wii: add mem2 dma mapping ops Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 10/11] wii: enable swiotlb Albert Herranz
2010-03-07 12:11 ` [RFC PATCH v3 11/11] wii: hollywood ehci controller support Albert Herranz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1267963912-984-7-git-send-email-albert_herranz@yahoo.es \
    --to=albert_herranz@yahoo.es \
    --cc=linux-usb@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.