Re: usbmon problem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 12 Mar 2010, Alan Stern wrote:

> Maybe we could have the scatter-gather library put pointers to the
> scatterlist elements in the URBs, and then for each URB have usbmon
> call dma_sync_sg() with nelems set to 1 (see
> Documentation/DMA-API.txt).  I'm not sure whether this will work
> properly if the original scatter-gather list contained more than one
> element, but it probably will.  I can ask.

Here's a patch.  Oliver, does it fix your problem?

Alan Stern



Index: usb-2.6/drivers/usb/mon/usb_mon.h
===================================================================
--- usb-2.6.orig/drivers/usb/mon/usb_mon.h
+++ usb-2.6/drivers/usb/mon/usb_mon.h
@@ -72,4 +72,6 @@ extern const struct file_operations mon_
 
 extern struct mon_bus mon_bus0;		/* Only for redundant checks */
 
+extern void usb_sg_sync_for_cpu(struct urb *urb, int nelems);
+
 #endif /* __USB_MON_H */
Index: usb-2.6/drivers/usb/mon/mon_bin.c
===================================================================
--- usb-2.6.orig/drivers/usb/mon/mon_bin.c
+++ usb-2.6/drivers/usb/mon/mon_bin.c
@@ -410,6 +410,7 @@ static unsigned int mon_bin_get_data(con
 			*flag = 'Z';
 			return length;
 		}
+		usb_sg_sync_for_cpu(urb, 1);
 		mon_copy_to_buff(rp, offset, urb->transfer_buffer, length);
 		length = 0;
 
@@ -421,6 +422,7 @@ static unsigned int mon_bin_get_data(con
 		}
 
 		/* Copy up to the first non-addressable segment */
+		usb_sg_sync_for_cpu(urb, urb->num_sgs);
 		for_each_sg(urb->sg->sg, sg, urb->num_sgs, i) {
 			if (length == 0 || PageHighMem(sg_page(sg)))
 				break;
Index: usb-2.6/drivers/usb/mon/mon_text.c
===================================================================
--- usb-2.6.orig/drivers/usb/mon/mon_text.c
+++ usb-2.6/drivers/usb/mon/mon_text.c
@@ -170,6 +170,7 @@ static inline char mon_text_get_data(str
 		src = sg_virt(sg);
 	}
 
+	usb_sg_sync_for_cpu(urb, 1);
 	memcpy(ep->data, src, len);
 	return 0;
 }
Index: usb-2.6/drivers/usb/core/message.c
===================================================================
--- usb-2.6.orig/drivers/usb/core/message.c
+++ usb-2.6/drivers/usb/core/message.c
@@ -467,6 +467,7 @@ int usb_sg_init(struct usb_sg_request *i
 				io->urbs[i]->transfer_buffer = NULL;
 
 			if (dma) {
+				io->urbs[i]->sg = (struct usb_sg_request *) sg;
 				io->urbs[i]->transfer_dma = sg_dma_address(sg);
 				len = sg_dma_len(sg);
 			} else {
@@ -643,6 +644,35 @@ void usb_sg_cancel(struct usb_sg_request
 }
 EXPORT_SYMBOL_GPL(usb_sg_cancel);
 
+/**
+ * usb_sg_sync_for_cpu -- give ownership of DMA buffers to the CPU
+ * @urb: URB whose buffers should be affected
+ * @nelems: number of sg elements to affect
+ *
+ * This allows the CPU to access @urb's sg transfer buffers after @urb
+ * has completed but before sg_clean() has unmapped the buffers for DMA.
+ * This is intended solely for use by usbmon.
+ */
+void usb_sg_sync_for_cpu(struct urb *urb, int nelems)
+{
+	enum dma_data_direction dir;
+	struct scatterlist *sg;
+
+	if (!(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP))
+		return;			/* Either not sg or not DMA */
+
+	if (urb->num_sgs == 0) {	/* HCD has no native sg support */
+		sg = (struct scatterlist *) urb->sg;
+		if (!sg)
+			return;		/* Coherent mapping, not sg-mapped */
+	} else {			/* HCD has native sg support */
+		sg = urb->sg->sg;
+	}
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	dma_sync_sg_for_cpu(urb->dev->bus->controller, sg, nelems, dir);
+}
+EXPORT_SYMBOL_GPL(usb_sg_sync_for_cpu);
+
 /*-------------------------------------------------------------------*/
 
 /**

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux