Commit 9a583d70 authored by Stuart MacDonald's avatar Stuart MacDonald Committed by Linus Torvalds

[PATCH] USB Whiteheat driver patches

A couple patches on 2.5.41; issues discovered during QA.

1: The hack to get around the unlinking bug. You said this was also in
2.5.x, so I've included this.

2: filp is NULL when called from usb_serial_disconnect. Fixes an oops.

3: In the case where the module is reloaded; the endpoints in the
usbsubsystem don't go away. So when the module comes back, the
endpoints still have the unlink thing, and also need to be cleared.
Otherwise the firmware appears not respond to the version nubmer query
and the driver doesn't attach, and you have no device.
parent f7353c67
...@@ -334,6 +334,12 @@ static int whiteheat_attach (struct usb_serial *serial) ...@@ -334,6 +334,12 @@ static int whiteheat_attach (struct usb_serial *serial)
command_port = &serial->port[COMMAND_PORT]; command_port = &serial->port[COMMAND_PORT];
pipe = usb_sndbulkpipe (serial->dev, command_port->bulk_out_endpointAddress); pipe = usb_sndbulkpipe (serial->dev, command_port->bulk_out_endpointAddress);
/*
* When the module is reloaded the firmware is still there and
* the endpoints are still in the usb core unchanged. This is the
* unlinking bug in disguise. Same for the call below.
*/
usb_clear_halt(serial->dev, pipe);
ret = usb_bulk_msg (serial->dev, pipe, command, sizeof(command), &alen, COMMAND_TIMEOUT); ret = usb_bulk_msg (serial->dev, pipe, command, sizeof(command), &alen, COMMAND_TIMEOUT);
if (ret) { if (ret) {
err("%s: Couldn't send command [%d]", serial->type->name, ret); err("%s: Couldn't send command [%d]", serial->type->name, ret);
...@@ -344,6 +350,8 @@ static int whiteheat_attach (struct usb_serial *serial) ...@@ -344,6 +350,8 @@ static int whiteheat_attach (struct usb_serial *serial)
} }
pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress); pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress);
/* See the comment on the usb_clear_halt() above */
usb_clear_halt(serial->dev, pipe);
ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(result), &alen, COMMAND_TIMEOUT); ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(result), &alen, COMMAND_TIMEOUT);
if (ret) { if (ret) {
err("%s: Couldn't get results [%d]", serial->type->name, ret); err("%s: Couldn't get results [%d]", serial->type->name, ret);
...@@ -438,6 +446,10 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp) ...@@ -438,6 +446,10 @@ static int whiteheat_open (struct usb_serial_port *port, struct file *filp)
if (retval) if (retval)
goto exit; goto exit;
/* Work around HCD bugs */
usb_clear_halt(port->serial->dev, port->read_urb->pipe);
usb_clear_halt(port->serial->dev, port->write_urb->pipe);
/* Start reading from the device */ /* Start reading from the device */
port->read_urb->dev = port->serial->dev; port->read_urb->dev = port->serial->dev;
retval = usb_submit_urb(port->read_urb, GFP_KERNEL); retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
...@@ -489,7 +501,8 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp) ...@@ -489,7 +501,8 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp)
{ {
dbg("%s - port %d", __FUNCTION__, port->number); dbg("%s - port %d", __FUNCTION__, port->number);
if (tty_hung_up_p(filp)) { /* filp is NULL when called from usb_serial_disconnect */
if (filp && (tty_hung_up_p(filp))) {
return; return;
} }
...@@ -1145,6 +1158,9 @@ static int start_command_port(struct usb_serial *serial) ...@@ -1145,6 +1158,9 @@ static int start_command_port(struct usb_serial *serial)
command_info = (struct whiteheat_command_private *)command_port->private; command_info = (struct whiteheat_command_private *)command_port->private;
spin_lock_irqsave(&command_info->lock, flags); spin_lock_irqsave(&command_info->lock, flags);
if (!command_info->port_running) { if (!command_info->port_running) {
/* Work around HCD bugs */
usb_clear_halt(serial->dev, command_port->read_urb->pipe);
command_port->read_urb->dev = serial->dev; command_port->read_urb->dev = serial->dev;
retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL); retval = usb_submit_urb(command_port->read_urb, GFP_KERNEL);
if (retval) { if (retval) {
......
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