Hi,
I've been looking at these issue in usb serial drivers. It seems to me
that kill_traffic() should be enhanced. If this is coupled with the
enhancements of the anchor stuff I posted recently this removes all races
in the drivers not using the standard URBs.
Additionally this modification will make implementations of suspen/resume
and eventually autosuspend easier for the subdrivers.
Thoughts?
Regards
Oliver
--- linux-2.6.24-sierra/include/linux/usb/serial.h.alt 2008-01-30
12:43:25.000000000 +0100
+++ linux-2.6.24-sierra/include/linux/usb/serial.h 2008-01-30
12:50:26.000000000 +0100
@@ -64,6 +64,7 @@ struct usb_serial_port {
struct usb_serial * serial;
struct tty_struct * tty;
spinlock_t lock;
+ struct usb_anchor additional_urbs;
struct mutex mutex;
unsigned char number;
--- linux-2.6.24-sierra/drivers/usb/serial/usb-serial.c.alt 2008-01-30
12:48:34.000000000 +0100
+++ linux-2.6.24-sierra/drivers/usb/serial/usb-serial.c 2008-01-30
12:50:22.000000000 +0100
@@ -593,6 +593,13 @@ static void kill_traffic(struct usb_seri
usb_kill_urb(port->read_urb);
usb_kill_urb(port->interrupt_in_urb);
usb_kill_urb(port->interrupt_out_urb);
+
+ /*
+ * This kills any additional URBs the subdrivers
+ * have anchored. This is needed for soft disconnect
+ */
+ usb_kill_anchored_urbs(&port->additional_urbs);
+
}
static void port_free(struct usb_serial_port *port)
@@ -879,6 +886,7 @@ int usb_serial_probe(struct usb_interfac
port->serial = serial;
spin_lock_init(&port->lock);
mutex_init(&port->mutex);
+ init_usb_anchor(&port->additional_urbs);
INIT_WORK(&port->work, usb_serial_port_work);
serial->port[i] = port;
}
--- linux-2.6.24-sierra/drivers/usb/serial/airprime.c.alt 2008-01-30
13:06:38.000000000 +0100
+++ linux-2.6.24-sierra/drivers/usb/serial/airprime.c 2008-01-30
13:22:38.000000000 +0100
@@ -98,10 +98,13 @@ static void airprime_read_bulk_callback(
tty_flip_buffer_push (tty);
}
+ usb_anchor_urb(urb, &port->additional_urbs);
result = usb_submit_urb (urb, GFP_ATOMIC);
- if (result)
+ if (result) {
dev_err(&port->dev, "%s - failed resubmitting read urb, error
%d\n",
__FUNCTION__, result);
+ usb_unanchor_urb(urb);
+ }
return;
}
@@ -174,8 +177,10 @@ static int airprime_open(struct usb_seri
port->bulk_out_endpointAddress),
buffer, buffer_size,
airprime_read_bulk_callback, port);
+ usb_anchor_urb(urb, &port->additional_urbs);
result = usb_submit_urb(urb, GFP_KERNEL);
if (result) {
+ usb_unanchor_urb(urb);
usb_free_urb(urb);
kfree(buffer);
dev_err(&port->dev,
@@ -198,9 +203,10 @@ static int airprime_open(struct usb_seri
while (i-- != 0) {
urb = priv->read_urbp[i];
buffer = urb->transfer_buffer;
- usb_kill_urb (urb);
- usb_free_urb (urb);
- kfree (buffer);
+ usb_kill_urb(urb);
+ usb_unanchor_urb(urb);
+ usb_free_urb(urb);
+ kfree(buffer);
}
out:
@@ -268,6 +274,7 @@ static int airprime_write(struct usb_ser
port->bulk_out_endpointAddress),
buffer, count,
airprime_write_bulk_callback, port);
+ usb_anchor_urb(urb, &port->additional_urbs);
/* send it down the pipe */
status = usb_submit_urb(urb, GFP_ATOMIC);
@@ -276,6 +283,7 @@ static int airprime_write(struct usb_ser
"%s - usb_submit_urb(write bulk) failed with status =
%d\n",
__FUNCTION__, status);
count = status;
+ usb_unanchor_urb(urb);
kfree (buffer);
} else {
spin_lock_irqsave(&priv->lock, flags);
-
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html