RFC : usbatm and iso

matthieu castet castet.matthieu at free.fr
Mon Feb 7 10:36:58 EST 2005


Hi,

I attached a patch for adding iso to the new library.
Seem to work well but need more testing.

cheers,
Matthieu
-------------- next part --------------
Index: usbatm.c
===================================================================
RCS file: /home/cvs/usbatm/usbatm.c,v
retrieving revision 1.4
diff -u -r1.4 usbatm.c
--- usbatm.c	1 Feb 2005 23:20:49 -0000	1.4
+++ usbatm.c	7 Feb 2005 15:32:37 -0000
@@ -145,6 +145,7 @@
 static unsigned int num_snd_bufs = UDSL_DEFAULT_SND_BUFS;
 static unsigned int rcv_buf_size = UDSL_DEFAULT_RCV_BUF_SIZE;
 static unsigned int snd_buf_size = UDSL_DEFAULT_SND_BUF_SIZE;
+static unsigned int rcv_buf_per_urb = UDSL_DEFAULT_RCV_BUF_PER_URB;
 
 module_param(num_rcv_urbs, uint, 0444);
 MODULE_PARM_DESC(num_rcv_urbs,
@@ -182,6 +183,12 @@
 		 __MODULE_STRING(UDSL_MAX_SND_BUF_SIZE) ", default: "
 		 __MODULE_STRING(UDSL_DEFAULT_SND_BUF_SIZE) ")");
 
+module_param(rcv_buf_per_urb, uint, 0444);
+MODULE_PARM_DESC(rcv_buf_per_urb,
+		 "Number of the buffer in iso urb used for reception (range: 0-"
+		 __MODULE_STRING(UDSL_MAX_RCV_BUF_PER_URB) ", default: "
+		 __MODULE_STRING(UDSL_DEFAULT_RCV_BUF_PER_URB) ")");
+
 /* ATM */
 
 static void usbatm_atm_dev_close(struct atm_dev *dev);
@@ -456,6 +463,38 @@
 /**************
 **  receive  **
 **************/
+static inline void usbatm_usb_fill_iso_urb (struct urb *urb,
+					struct usb_device *dev,
+					unsigned int pipe,
+					void *transfer_buffer,
+					int buffer_length,
+					int frame_size,
+					usb_complete_t complete,
+					void *context)
+{
+	int j;
+
+	//spin_lock_init(&urb->lock);
+	urb->dev = dev;
+	urb->pipe = pipe;
+	urb->transfer_buffer = transfer_buffer;
+	urb->transfer_buffer_length = buffer_length;
+	urb->complete = complete;
+	urb->context = context;
+
+	urb->interval = 1;
+	urb->transfer_flags = URB_ISO_ASAP;
+	urb->number_of_packets = rcv_buf_per_urb;
+
+	for (j = 0; j < urb->number_of_packets; j++) {
+		urb->iso_frame_desc[j].offset = j * frame_size;
+		urb->iso_frame_desc[j].length = frame_size;
+		
+		urb->iso_frame_desc[j].status = 0;
+		urb->iso_frame_desc[j].actual_length = 0;
+	}
+	urb->status = 0;
+}
 
 static void usbatm_complete_receive(struct urb *urb, struct pt_regs *regs)
 {
@@ -472,17 +511,44 @@
 	instance = rcv->instance;
 	buf = rcv->buffer;
 
-	buf->filled_cells = urb->actual_length / (ATM_CELL_SIZE + instance->rx_padding);
+	if ( urb->actual_length <= 0 && !urb->status) {
+		int err;
+		if ((err = usb_submit_urb(rcv->urb, GFP_ATOMIC)) < 0) {
+			dbg("usbatm_complete_receive: urb submission failed (%d)!", err);
+			list_add(&buf->list, &instance->spare_receive_buffers);
+			spin_lock_irq(&instance->receive_lock);
+			list_add(&rcv->list, &instance->spare_receivers);
+			spin_unlock_irq(&instance->receive_lock);
+			tasklet_schedule(&instance->receive_tasklet);
+		}
+		return;
+	}
+
+	if (usb_pipeisoc(instance->rx_endpoint)) {
+		int i;
+		for (i = 0; i < urb->number_of_packets; i++) {
+			buf->frames[i].status = urb->iso_frame_desc[i].status;
+			buf->frames[i].filled_cells = urb->iso_frame_desc[i].actual_length / (ATM_CELL_SIZE + instance->rx_padding);
+			UDSL_ASSERT(buf->frames[i].filled_cells <= instance->iso_frame_size);
+			vdbg("usbatm_complete_receive: urb 0x%p, frame %d, status %d, actual_length %d ,filled_cells %d", urb, i, buf->frames[i].status, urb->iso_frame_desc[i].actual_length, buf->frames[i].filled_cells);
+		}
+	}
+	else {
+		buf->filled_cells = urb->actual_length / (ATM_CELL_SIZE + instance->rx_padding);
+	}
 
 	vdbg("usbatm_complete_receive: urb 0x%p, status %d, actual_length %d, filled_cells %u, rcv 0x%p, buf 0x%p", urb, urb->status, urb->actual_length, buf->filled_cells, rcv, buf);
 
-	UDSL_ASSERT(buf->filled_cells <= rcv_buf_size);
+	UDSL_ASSERT(!usb_pipeisoc(instance->rx_endpoint)
+			&& buf->filled_cells <= rcv_buf_size);
 
 	/* may not be in_interrupt() */
 	spin_lock_irqsave(&instance->receive_lock, flags);
 	list_add(&rcv->list, &instance->spare_receivers);
 	list_add_tail(&buf->list, &instance->filled_receive_buffers);
-	if (likely(!urb->status))
+	if (likely(!urb->status) ||
+			/* via chipset produce lot's of crc error...*/
+			(usb_pipeisoc(instance->rx_endpoint) && urb->status == -EILSEQ))
 		tasklet_schedule(&instance->receive_tasklet);
 	spin_unlock_irqrestore(&instance->receive_lock, flags);
 }
@@ -512,11 +578,21 @@
 
 		rcv->buffer = buf;
 
-		usb_fill_bulk_urb(rcv->urb, instance->usb_dev,
-				  instance->rx_endpoint,
-				  buf->base,
-				  rcv_buf_size * (ATM_CELL_SIZE + instance->rx_padding),
-				  usbatm_complete_receive, rcv);
+		/* refill the urb because the buf could have changed...*/
+		/* urb->transfer_buffer and urb->context should be enought */
+		if (usb_pipeisoc(instance->rx_endpoint))
+			usbatm_usb_fill_iso_urb(rcv->urb, instance->usb_dev,
+				  	instance->rx_endpoint,
+				  	buf->base,
+				  	instance->iso_frame_size * rcv_buf_per_urb,
+					instance->iso_frame_size,
+				  	usbatm_complete_receive, rcv);
+		else
+			usb_fill_bulk_urb(rcv->urb, instance->usb_dev,
+				  	instance->rx_endpoint,
+					buf->base,
+				  	rcv_buf_size * (ATM_CELL_SIZE + instance->rx_padding),
+				  	usbatm_complete_receive, rcv);
 
 		vdbg("usbatm_process_receive: sending urb 0x%p, rcv 0x%p, buf 0x%p",
 		     rcv->urb, rcv, buf);
@@ -542,7 +618,17 @@
 	spin_unlock_irq(&instance->receive_lock);
 
 	vdbg("usbatm_process_receive: processing buf 0x%p", buf);
-	usbatm_extract_cells(instance, buf->base, buf->filled_cells);
+	if (usb_pipeisoc(instance->rx_endpoint)) {
+		int i;
+		for (i=0 ; i < rcv_buf_per_urb; i++) {
+			if (buf->frames[i].status == 0) {
+				usbatm_extract_cells(instance, buf->base + i * instance->iso_frame_size, buf->frames[i].filled_cells);
+			}
+		}
+	}
+	else
+		usbatm_extract_cells(instance, buf->base, buf->filled_cells);
+
 	list_add(&buf->list, &instance->spare_receive_buffers);
 	goto made_progress;
 }
@@ -1037,6 +1123,8 @@
 	int error = -ENOMEM;
 	int ifnum = intf->altsetting->desc.bInterfaceNumber;
 	int i, length;
+	int nb_frames = 0;
+	int urb_size;
 	int need_heavy;
 
 	dev_dbg(&intf->dev, "trying device with vendor=0x%x, product=0x%x, ifnum %d\n", dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
@@ -1062,9 +1150,18 @@
 	instance->usb_dev = dev;
 	instance->usb_intf = intf;
 	instance->tx_endpoint = usb_sndbulkpipe(dev, driver->out);
-	instance->rx_endpoint = usb_rcvbulkpipe(dev, driver->in);
+	if (driver->iso_frame_size) {
+		nb_frames = rcv_buf_per_urb;
+		urb_size = driver->iso_frame_size * rcv_buf_per_urb;
+		instance->rx_endpoint = usb_rcvisocpipe(dev, driver->in);
+	}
+	else {
+		urb_size = rcv_buf_size * (ATM_CELL_SIZE + instance->rx_padding);
+		instance->rx_endpoint = usb_rcvbulkpipe(dev, driver->in);
+	}
 	instance->tx_padding = driver->tx_padding;
 	instance->rx_padding = driver->rx_padding;
+	instance->iso_frame_size = driver->iso_frame_size;
 
 	INIT_LIST_HEAD(&instance->vcc_list);
 
@@ -1089,7 +1186,7 @@
 	for (i = 0; i < num_rcv_urbs; i++) {
 		struct usbatm_receiver *rcv = &(instance->receivers[i]);
 
-		if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) {
+		if (!(rcv->urb = usb_alloc_urb(nb_frames, GFP_KERNEL))) {
 			dev_dbg(&intf->dev, "no memory for receive urb %d!\n", i);
 			goto fail;
 		}
@@ -1102,8 +1199,7 @@
 	for (i = 0; i < num_rcv_bufs; i++) {
 		struct usbatm_receive_buffer *buf = &(instance->receive_buffers[i]);
 
-		buf->base = kmalloc(rcv_buf_size * (ATM_CELL_SIZE + instance->rx_padding),
-				    GFP_KERNEL);
+		buf->base = kmalloc(urb_size, GFP_KERNEL);
 		if (!buf->base) {
 			dev_dbg(&intf->dev, "no memory for receive buffer %d!\n", i);
 			goto fail;
@@ -1292,6 +1388,7 @@
 	    || (num_rcv_bufs > UDSL_MAX_RCV_BUFS)
 	    || (num_snd_bufs > UDSL_MAX_SND_BUFS)
 	    || (rcv_buf_size > UDSL_MAX_RCV_BUF_SIZE)
+	    || (rcv_buf_per_urb > UDSL_MAX_RCV_BUF_PER_URB)
 	    || (snd_buf_size > UDSL_MAX_SND_BUF_SIZE))
 		return -EINVAL;
 
Index: usbatm.h
===================================================================
RCS file: /home/cvs/usbatm/usbatm.h,v
retrieving revision 1.8
diff -u -r1.8 usbatm.h
--- usbatm.h	1 Feb 2005 23:20:49 -0000	1.8
+++ usbatm.h	7 Feb 2005 15:32:37 -0000
@@ -88,6 +88,7 @@
 
 	unsigned rx_padding;
 	unsigned tx_padding;
+	unsigned iso_frame_size; /* if using iso urb, the size of a frame */
 };
 
 extern int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
@@ -103,19 +104,26 @@
 #define UDSL_MAX_SND_BUFS		8
 #define UDSL_MAX_RCV_BUF_SIZE		1024	/* ATM cells */
 #define UDSL_MAX_SND_BUF_SIZE		1024	/* ATM cells */
+#define UDSL_MAX_RCV_BUF_PER_URB	20
 #define UDSL_DEFAULT_RCV_URBS		2
 #define UDSL_DEFAULT_SND_URBS		2
 #define UDSL_DEFAULT_RCV_BUFS		4
 #define UDSL_DEFAULT_SND_BUFS		4
 #define UDSL_DEFAULT_RCV_BUF_SIZE	64	/* ATM cells */
 #define UDSL_DEFAULT_SND_BUF_SIZE	64	/* ATM cells */
+#define UDSL_DEFAULT_RCV_BUF_PER_URB	16
 
 
 /* receive */
+struct udsl_receive_iso_frame {
+	unsigned int filled_cells;
+	int status;
+};
 
 struct usbatm_receive_buffer {
 	struct list_head list;
 	unsigned char *base;
+	struct udsl_receive_iso_frame frames[UDSL_MAX_RCV_BUF_PER_URB];
 	unsigned int filled_cells;
 };
 
@@ -167,6 +175,7 @@
 	int rx_endpoint;
 	int tx_padding;
 	int rx_padding;
+	unsigned iso_frame_size;
 
 	/* ATM device part */
 	struct atm_dev *atm_dev;


More information about the Usbatm mailing list