Re: usbmon problem

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

 



On Mon, 15 Mar 2010, Oliver Neukum wrote:

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

Below is an updated version, based on a comment from James Bottomley.  
Can you test it using both the text and binary usbmon interfaces?  Pete 
has a program for the binary interface on his web page:

	http://people.redhat.com/zaitcev/linux/usbmon-5.4.tar.gz

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,43 @@ 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)
+{
+	struct scatterlist *sg;
+	struct device *dev;
+	enum dma_data_direction dir;
+
+	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 */
+		nelems = 1;
+	} else {			/* HCD has native sg support */
+		sg = urb->sg->sg;
+	}
+
+	dev = urb->dev->bus->controller;
+	dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+	if (nelems > 1)
+		dma_sync_sg_for_cpu(dev, sg, nelems, dir);
+	else
+		dma_sync_single_for_cpu(dev, sg_dma_address(sg),
+				sg_dma_len(sg), 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