[RFC] [PATCH] usbatm.[ch]: multiple changes

Roman Kagan rkagan at mail.ru
Tue Mar 29 16:02:54 EST 2005


On Tue, Mar 29, 2005 at 04:04:45PM +0400, Roman Kagan wrote:
> 3) All the urb-related stuff (buffer and its size, urb status, etc.) is
>    now contained in the urb itself.  This makes it trivial to add iso
>    transport for rx (which I'm going to do later today).

So here you are: below is the incremental patch adding iso rx transfers.

Matthieu, can you please test it?  To do so, you need to claim the
appropriate interface in your subdriver's ->bind() and set the
usbatm_data.rx_channel.endpoint to the appropriate iso pipe.

The code in the patch will calculate the right iso frame size based on
the wMaxPacketSize of the given endpoint, and fill the
urb->iso_frame_desc[] array.

Note that the two today's patches are by no means thoroughly tested and
may have fatal bugs, so please take neccessary precautions (e.g. don't
experiment with it with your hard drive partitions mounted r/w :).

Comments are appreciated, as usual.
Cheers,
  Roman.


--- usbatm.c.isopipe	2005-03-29 06:12:17.000000000 +0400
+++ usbatm.c	2005-03-30 00:58:07.000000000 +0400
@@ -552,11 +552,22 @@
 	struct usbatm_transceiver *rx;
 
 	while ((rx = usbatm_pop_transceiver(&instance->rx_channel))) {
+		struct urb *urb = rx->urb;
+
 		vdbg("usbatm_rx_process: processing rx 0x%p", rx);
 
-		if (!rx->urb->status)
-			usbatm_extract_cells(instance, rx->urb->transfer_buffer,
-					     rx->urb->actual_length);
+		if (usb_pipeisoc(urb->pipe)) {
+			int i;
+			for (i = 0; i < urb->number_of_packets; i++)
+				if (!urb->iso_frame_desc[i].status)
+					usbatm_extract_cells(instance,
+							     (u8 *)urb->transfer_buffer + urb->iso_frame_desc[i].offset,
+							     urb->iso_frame_desc[i].actual_length);
+		}
+		else
+			if (!urb->status)
+				usbatm_extract_cells(instance, urb->transfer_buffer,
+						     urb->actual_length);
 
 		if (usbatm_submit(rx))
 			return;
@@ -1103,6 +1114,7 @@
 	for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {
 		struct usbatm_transceiver *trx = instance->transceivers + i;
 		u8 *buffer;
+		unsigned int iso_packets = 0, iso_size = 0;
 		trx->channel = i < num_rcv_urbs ? &instance->rx_channel : &instance->tx_channel;
 
 		buffer = kmalloc(trx->channel->buf_size, GFP_KERNEL);
@@ -1112,7 +1124,15 @@
 		}
 		memset(buffer, 0, trx->channel->buf_size);
 
-		trx->urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (usb_pipeisoc(trx->urb->pipe)) {
+			/* don't expect iso out endpoints */
+			iso_size = usb_maxpacket(instance->usb_dev, trx->channel->endpoint, 0);
+			iso_size -= iso_size % trx->channel->stride;	/* alignment */
+			BUG_ON(!iso_size);
+			iso_packets = (trx->channel->buf_size - 1) / iso_size + 1;
+		}
+
+		trx->urb = usb_alloc_urb(iso_packets, GFP_KERNEL);
 		if (!trx->urb) {
 			dev_dbg(&intf->dev, "no memory for urb %d!\n", i);
 			goto fail_unbind;
@@ -1120,6 +1140,17 @@
 
 		usb_fill_bulk_urb(trx->urb, instance->usb_dev, trx->channel->endpoint,
 				  buffer, trx->channel->buf_size, usbatm_complete, trx);
+		if (iso_packets) {
+			int j;
+			trx->urb->interval = 1;
+			trx->urb->transfer_flags = URB_ISO_ASAP;
+			trx->urb->number_of_packets = iso_packets;
+			for (j = 0; j < iso_packets; j++) {
+				trx->urb->iso_frame_desc[j].offset = iso_size * j;
+				trx->urb->iso_frame_desc[j].length = min_t(int, iso_size,
+									   trx->channel->buf_size - trx->urb->iso_frame_desc[j].offset);
+			}
+		}
 
 		/* put all tx URBs on the list of spares */
 		if (i >= num_rcv_urbs)



More information about the Usbatm mailing list