ChangeSet 1.1595.7.8, 2003/07/30 12:52:21-07:00, greg@kroah.com

[PATCH] USB: bluetty: remove write_urb_pool logic, fixing locking issues.

Now we just throw urbs at the device as fast as we can.


 drivers/usb/class/bluetty.c |  178 +++++++++++++-------------------------------
 1 files changed, 55 insertions(+), 123 deletions(-)


diff -Nru a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
--- a/drivers/usb/class/bluetty.c	Fri Aug  1 10:55:40 2003
+++ b/drivers/usb/class/bluetty.c	Fri Aug  1 10:55:40 2003
@@ -190,7 +190,6 @@
 	int			bulk_in_buffer_size;
 
 	int			bulk_out_buffer_size;
-	struct urb *		write_urb_pool[NUM_BULK_URBS];
 	__u8			bulk_out_endpointAddress;
 
 	wait_queue_head_t	write_wait;
@@ -408,7 +407,6 @@
 static void bluetooth_close (struct tty_struct *tty, struct file * filp)
 {
 	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-	int i;
 
 	if (!bluetooth) {
 		return;
@@ -427,9 +425,7 @@
 	if (bluetooth->open_count <= 0) {
 		bluetooth->open_count = 0;
 
-		/* shutdown any bulk reads and writes that might be going on */
-		for (i = 0; i < NUM_BULK_URBS; ++i)
-			usb_unlink_urb (bluetooth->write_urb_pool[i]);
+		/* shutdown any in-flight urbs that we know about */
 		usb_unlink_urb (bluetooth->read_urb);
 		usb_unlink_urb (bluetooth->interrupt_in_urb);
 	}
@@ -443,9 +439,7 @@
 	struct urb *urb = NULL;
 	unsigned char *temp_buffer = NULL;
 	const unsigned char *current_buffer;
-	const unsigned char *current_position;
-	int bytes_sent;
-	int buffer_size;
+	unsigned char *urb_buffer;
 	int i;
 	int retval = 0;
 
@@ -506,54 +500,46 @@
 			break;
 
 		case ACL_PKT:
-			current_position = current_buffer;
-			++current_position;
+			++current_buffer;
 			--count;
-			bytes_sent = 0;
 
-			while (count > 0) {
-				urb = NULL;
+			urb_buffer = kmalloc (count, GFP_ATOMIC);
+			if (!urb_buffer) {
+				dev_err(&bluetooth->dev->dev, "out of memory\n");
+				retval = -ENOMEM;
+				goto exit;
+			}
 
-				/* try to find a free urb in our list */
-				for (i = 0; i < NUM_BULK_URBS; ++i) {
-					if (bluetooth->write_urb_pool[i]->status != -EINPROGRESS) {
-						urb = bluetooth->write_urb_pool[i];
-						break;
-					}
-				}
-				if (urb == NULL) {
-					dbg ("%s - no free urbs", __FUNCTION__);
-					retval = bytes_sent;
-					goto exit;
-				}
-				
-
-				buffer_size = min (count, bluetooth->bulk_out_buffer_size);
-				memcpy (urb->transfer_buffer, current_position, buffer_size);
-
-				/* build up our urb */
-				usb_fill_bulk_urb (urb, bluetooth->dev, usb_sndbulkpipe(bluetooth->dev, bluetooth->bulk_out_endpointAddress),
-						urb->transfer_buffer, buffer_size, bluetooth_write_bulk_callback, bluetooth);
-
-				/* send it down the pipe */
-				retval = usb_submit_urb(urb, GFP_KERNEL);
-				if (retval) {
-					dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, retval);
-					goto exit;
-				}
-#ifdef BTBUGGYHARDWARE
-				/* A workaround for the stalled data bug */
-				/* May or may not be needed...*/
-				if (count != 0) {
-					udelay(500);
-				}
-#endif
-				current_position += buffer_size;
-				bytes_sent += buffer_size;
-				count -= buffer_size;
+			urb = usb_alloc_urb(0, GFP_ATOMIC);
+			if (!urb) {
+				dev_err(&bluetooth->dev->dev, "no more free urbs\n");
+				kfree(urb_buffer);
+				retval = -ENOMEM;
+				goto exit;
 			}
+			memcpy (urb_buffer, current_buffer, count);
+
+			/* build up our urb */
+			usb_fill_bulk_urb(urb, bluetooth->dev, 
+					  usb_sndbulkpipe(bluetooth->dev,
+						  	  bluetooth->bulk_out_endpointAddress),
+					  urb_buffer,
+					  count,
+					  bluetooth_write_bulk_callback,
+					  bluetooth);
 
-			retval = bytes_sent + 1;
+
+			/* send it down the pipe */
+			retval = usb_submit_urb(urb, GFP_KERNEL);
+			if (retval) {
+				dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, retval);
+				goto exit;
+			}
+
+			/* we are done with this urb, so let the host driver
+			 * really free it when it is finished with it */
+			usb_free_urb (urb);
+			retval = count + 1;
 			break;
 		
 		default :
@@ -563,8 +549,7 @@
 	}
 
 exit:
-	if (temp_buffer != NULL)
-		kfree (temp_buffer);
+	kfree (temp_buffer);
 
 	return retval;
 } 
@@ -572,55 +557,28 @@
 
 static int bluetooth_write_room (struct tty_struct *tty) 
 {
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-	int room = 0;
-	int i;
-
-	if (!bluetooth) {
-		return -ENODEV;
-	}
-
 	dbg("%s", __FUNCTION__);
 
-	if (!bluetooth->open_count) {
-		dbg ("%s - device not open", __FUNCTION__);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < NUM_BULK_URBS; ++i) {
-		if (bluetooth->write_urb_pool[i]->status != -EINPROGRESS) {
-			room += bluetooth->bulk_out_buffer_size;
-		}
-	}
-
-	dbg("%s - returns %d", __FUNCTION__, room);
-	return room;
+	/*
+	 * We really can take anything the user throws at us
+	 * but let's pick a nice big number to tell the tty
+	 * layer that we have lots of free space
+	 */
+	return 2048;
 }
 
 
 static int bluetooth_chars_in_buffer (struct tty_struct *tty) 
 {
-	struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
-	int chars = 0;
-	int i;
-
-	if (!bluetooth) {
-		return -ENODEV;
-	}
-
-	if (!bluetooth->open_count) {
-		dbg ("%s - device not open", __FUNCTION__);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < NUM_BULK_URBS; ++i) {
-		if (bluetooth->write_urb_pool[i]->status == -EINPROGRESS) {
-			chars += bluetooth->write_urb_pool[i]->transfer_buffer_length;
-		}
-	}
+	dbg("%s", __FUNCTION__);
 
-	dbg ("%s - returns %d", __FUNCTION__, chars);
-	return chars;
+	/* 
+	 * We can't really account for how much data we
+	 * have sent out, but hasn't made it through to the
+	 * device, so just tell the tty layer that everything
+	 * is flushed.
+	 */
+	return 0;
 }
 
 
@@ -1009,6 +967,9 @@
 
 	dbg("%s", __FUNCTION__);
 
+	/* free up the transfer buffer, as usb_free_urb() does not do this */
+	kfree(urb->transfer_buffer);
+
 	if (!bluetooth) {
 		dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
 		return;
@@ -1161,21 +1122,6 @@
 	bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress;
 	bluetooth->bulk_out_buffer_size = endpoint->wMaxPacketSize * 2;
 
-	/* create our write urb pool */ 
-	for (i = 0; i < NUM_BULK_URBS; ++i) {
-		struct urb  *urb = usb_alloc_urb(0, GFP_KERNEL);
-		if (urb == NULL) {
-			err("No free urbs available");
-			goto probe_error;
-		}
-		urb->transfer_buffer = kmalloc (bluetooth->bulk_out_buffer_size, GFP_KERNEL);
-		if (urb->transfer_buffer == NULL) {
-			err("out of memory");
-			goto probe_error;
-		}
-		bluetooth->write_urb_pool[i] = urb;
-	}
-
 	endpoint = interrupt_in_endpoint[0];
 	bluetooth->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!bluetooth->interrupt_in_urb) {
@@ -1213,12 +1159,6 @@
 		usb_free_urb (bluetooth->interrupt_in_urb);
 	if (bluetooth->interrupt_in_buffer)
 		kfree (bluetooth->interrupt_in_buffer);
-	for (i = 0; i < NUM_BULK_URBS; ++i)
-		if (bluetooth->write_urb_pool[i]) {
-			if (bluetooth->write_urb_pool[i]->transfer_buffer)
-				kfree (bluetooth->write_urb_pool[i]->transfer_buffer);
-			usb_free_urb (bluetooth->write_urb_pool[i]);
-		}
 	for (i = 0; i < NUM_CONTROL_URBS; ++i) 
 		if (bluetooth->control_urb_pool[i]) {
 			if (bluetooth->control_urb_pool[i]->transfer_buffer)
@@ -1262,14 +1202,6 @@
 
 		tty_unregister_device (bluetooth_tty_driver, bluetooth->minor);
 
-		for (i = 0; i < NUM_BULK_URBS; ++i) {
-			if (bluetooth->write_urb_pool[i]) {
-				usb_unlink_urb (bluetooth->write_urb_pool[i]);
-				if (bluetooth->write_urb_pool[i]->transfer_buffer)
-					kfree (bluetooth->write_urb_pool[i]->transfer_buffer);
-				usb_free_urb (bluetooth->write_urb_pool[i]);
-			}
-		}
 		for (i = 0; i < NUM_CONTROL_URBS; ++i) {
 			if (bluetooth->control_urb_pool[i]) {
 				usb_unlink_urb (bluetooth->control_urb_pool[i]);
