Commit 38ab367b authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

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

Now we just throw urbs at the device as fast as we can.
parent 7b971170
...@@ -190,7 +190,6 @@ struct usb_bluetooth { ...@@ -190,7 +190,6 @@ struct usb_bluetooth {
int bulk_in_buffer_size; int bulk_in_buffer_size;
int bulk_out_buffer_size; int bulk_out_buffer_size;
struct urb * write_urb_pool[NUM_BULK_URBS];
__u8 bulk_out_endpointAddress; __u8 bulk_out_endpointAddress;
wait_queue_head_t write_wait; wait_queue_head_t write_wait;
...@@ -408,7 +407,6 @@ static int bluetooth_open (struct tty_struct *tty, struct file * filp) ...@@ -408,7 +407,6 @@ static int bluetooth_open (struct tty_struct *tty, struct file * filp)
static void bluetooth_close (struct tty_struct *tty, struct file * filp) 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__); struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__);
int i;
if (!bluetooth) { if (!bluetooth) {
return; return;
...@@ -427,9 +425,7 @@ static void bluetooth_close (struct tty_struct *tty, struct file * filp) ...@@ -427,9 +425,7 @@ static void bluetooth_close (struct tty_struct *tty, struct file * filp)
if (bluetooth->open_count <= 0) { if (bluetooth->open_count <= 0) {
bluetooth->open_count = 0; bluetooth->open_count = 0;
/* shutdown any bulk reads and writes that might be going on */ /* shutdown any in-flight urbs that we know about */
for (i = 0; i < NUM_BULK_URBS; ++i)
usb_unlink_urb (bluetooth->write_urb_pool[i]);
usb_unlink_urb (bluetooth->read_urb); usb_unlink_urb (bluetooth->read_urb);
usb_unlink_urb (bluetooth->interrupt_in_urb); usb_unlink_urb (bluetooth->interrupt_in_urb);
} }
...@@ -443,9 +439,7 @@ static int bluetooth_write (struct tty_struct * tty, int from_user, const unsign ...@@ -443,9 +439,7 @@ static int bluetooth_write (struct tty_struct * tty, int from_user, const unsign
struct urb *urb = NULL; struct urb *urb = NULL;
unsigned char *temp_buffer = NULL; unsigned char *temp_buffer = NULL;
const unsigned char *current_buffer; const unsigned char *current_buffer;
const unsigned char *current_position; unsigned char *urb_buffer;
int bytes_sent;
int buffer_size;
int i; int i;
int retval = 0; int retval = 0;
...@@ -506,54 +500,46 @@ static int bluetooth_write (struct tty_struct * tty, int from_user, const unsign ...@@ -506,54 +500,46 @@ static int bluetooth_write (struct tty_struct * tty, int from_user, const unsign
break; break;
case ACL_PKT: case ACL_PKT:
current_position = current_buffer; ++current_buffer;
++current_position;
--count; --count;
bytes_sent = 0;
urb_buffer = kmalloc (count, GFP_ATOMIC);
while (count > 0) { if (!urb_buffer) {
urb = NULL; dev_err(&bluetooth->dev->dev, "out of memory\n");
retval = -ENOMEM;
/* try to find a free urb in our list */ goto exit;
for (i = 0; i < NUM_BULK_URBS; ++i) { }
if (bluetooth->write_urb_pool[i]->status != -EINPROGRESS) {
urb = bluetooth->write_urb_pool[i]; urb = usb_alloc_urb(0, GFP_ATOMIC);
break; if (!urb) {
} dev_err(&bluetooth->dev->dev, "no more free urbs\n");
} kfree(urb_buffer);
if (urb == NULL) { retval = -ENOMEM;
dbg ("%s - no free urbs", __FUNCTION__); goto exit;
retval = bytes_sent; }
goto exit; memcpy (urb_buffer, current_buffer, count);
}
/* build up our urb */
usb_fill_bulk_urb(urb, bluetooth->dev,
buffer_size = min (count, bluetooth->bulk_out_buffer_size); usb_sndbulkpipe(bluetooth->dev,
memcpy (urb->transfer_buffer, current_position, buffer_size); bluetooth->bulk_out_endpointAddress),
urb_buffer,
/* build up our urb */ count,
usb_fill_bulk_urb (urb, bluetooth->dev, usb_sndbulkpipe(bluetooth->dev, bluetooth->bulk_out_endpointAddress), bluetooth_write_bulk_callback,
urb->transfer_buffer, buffer_size, bluetooth_write_bulk_callback, bluetooth); bluetooth);
/* send it down the pipe */
retval = usb_submit_urb(urb, GFP_KERNEL); /* send it down the pipe */
if (retval) { retval = usb_submit_urb(urb, GFP_KERNEL);
dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, retval); if (retval) {
goto exit; 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;
} }
retval = bytes_sent + 1; /* 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; break;
default : default :
...@@ -563,8 +549,7 @@ static int bluetooth_write (struct tty_struct * tty, int from_user, const unsign ...@@ -563,8 +549,7 @@ static int bluetooth_write (struct tty_struct * tty, int from_user, const unsign
} }
exit: exit:
if (temp_buffer != NULL) kfree (temp_buffer);
kfree (temp_buffer);
return retval; return retval;
} }
...@@ -572,55 +557,28 @@ static int bluetooth_write (struct tty_struct * tty, int from_user, const unsign ...@@ -572,55 +557,28 @@ static int bluetooth_write (struct tty_struct * tty, int from_user, const unsign
static int bluetooth_write_room (struct tty_struct *tty) 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__); dbg("%s", __FUNCTION__);
if (!bluetooth->open_count) { /*
dbg ("%s - device not open", __FUNCTION__); * We really can take anything the user throws at us
return -EINVAL; * but let's pick a nice big number to tell the tty
} * layer that we have lots of free space
*/
for (i = 0; i < NUM_BULK_URBS; ++i) { return 2048;
if (bluetooth->write_urb_pool[i]->status != -EINPROGRESS) {
room += bluetooth->bulk_out_buffer_size;
}
}
dbg("%s - returns %d", __FUNCTION__, room);
return room;
} }
static int bluetooth_chars_in_buffer (struct tty_struct *tty) static int bluetooth_chars_in_buffer (struct tty_struct *tty)
{ {
struct usb_bluetooth *bluetooth = get_usb_bluetooth ((struct usb_bluetooth *)tty->driver_data, __FUNCTION__); dbg("%s", __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 - 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 @@ static void bluetooth_write_bulk_callback (struct urb *urb, struct pt_regs *regs ...@@ -1009,6 +967,9 @@ static void bluetooth_write_bulk_callback (struct urb *urb, struct pt_regs *regs
dbg("%s", __FUNCTION__); dbg("%s", __FUNCTION__);
/* free up the transfer buffer, as usb_free_urb() does not do this */
kfree(urb->transfer_buffer);
if (!bluetooth) { if (!bluetooth) {
dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__); dbg("%s - bad bluetooth pointer, exiting", __FUNCTION__);
return; return;
...@@ -1161,21 +1122,6 @@ static int usb_bluetooth_probe (struct usb_interface *intf, ...@@ -1161,21 +1122,6 @@ static int usb_bluetooth_probe (struct usb_interface *intf,
bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress; bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress;
bluetooth->bulk_out_buffer_size = endpoint->wMaxPacketSize * 2; 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]; endpoint = interrupt_in_endpoint[0];
bluetooth->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); bluetooth->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!bluetooth->interrupt_in_urb) { if (!bluetooth->interrupt_in_urb) {
...@@ -1213,12 +1159,6 @@ static int usb_bluetooth_probe (struct usb_interface *intf, ...@@ -1213,12 +1159,6 @@ static int usb_bluetooth_probe (struct usb_interface *intf,
usb_free_urb (bluetooth->interrupt_in_urb); usb_free_urb (bluetooth->interrupt_in_urb);
if (bluetooth->interrupt_in_buffer) if (bluetooth->interrupt_in_buffer)
kfree (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) for (i = 0; i < NUM_CONTROL_URBS; ++i)
if (bluetooth->control_urb_pool[i]) { if (bluetooth->control_urb_pool[i]) {
if (bluetooth->control_urb_pool[i]->transfer_buffer) if (bluetooth->control_urb_pool[i]->transfer_buffer)
...@@ -1262,14 +1202,6 @@ static void usb_bluetooth_disconnect(struct usb_interface *intf) ...@@ -1262,14 +1202,6 @@ static void usb_bluetooth_disconnect(struct usb_interface *intf)
tty_unregister_device (bluetooth_tty_driver, bluetooth->minor); 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) { for (i = 0; i < NUM_CONTROL_URBS; ++i) {
if (bluetooth->control_urb_pool[i]) { if (bluetooth->control_urb_pool[i]) {
usb_unlink_urb (bluetooth->control_urb_pool[i]); usb_unlink_urb (bluetooth->control_urb_pool[i]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment