Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 507ca9bc authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

[PATCH] USB: add ability for usb-serial drivers to determine if their write...


[PATCH] USB: add ability for usb-serial drivers to determine if their write urb is currently being used.

This removes a lot of racy and buggy code by trying to check the status of the urb.

Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent f4df0e33
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -213,10 +213,14 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
		return (0);
	}

	if (port->write_urb->status == -EINPROGRESS) {
	spin_lock(&port->lock);
	if (port->write_urb_busy) {
		spin_unlock(&port->lock);
		dbg("%s - already writing", __FUNCTION__);
		return (0);
		return 0;
	}
	port->write_urb_busy = 1;
	spin_unlock(&port->lock);

	spin_lock_irqsave(&priv->lock, flags);

@@ -224,6 +228,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
		/* To much data for buffer. Reset buffer. */
		priv->wrfilled=0;
		spin_unlock_irqrestore(&priv->lock, flags);
		port->write_urb_busy = 0;
		return (0);
	}

@@ -268,6 +273,7 @@ static int cyberjack_write (struct usb_serial_port *port, const unsigned char *b
			priv->wrfilled=0;
			priv->wrsent=0;
			spin_unlock_irqrestore(&priv->lock, flags);
			port->write_urb_busy = 0;
			return 0;
		}

@@ -413,6 +419,7 @@ static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs

	dbg("%s - port %d", __FUNCTION__, port->number);

	port->write_urb_busy = 0;
	if (urb->status) {
		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
		return;
@@ -424,12 +431,6 @@ static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs
	if( priv->wrfilled ) {
		int length, blksize, result;

		if (port->write_urb->status == -EINPROGRESS) {
			dbg("%s - already writing", __FUNCTION__);
			spin_unlock(&priv->lock);
			return;
		}

		dbg("%s - transmitting data (frame n)", __FUNCTION__);

		length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ?
+16 −8
Original line number Diff line number Diff line
@@ -174,10 +174,14 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *

	/* only do something if we have a bulk out endpoint */
	if (serial->num_bulk_out) {
		if (port->write_urb->status == -EINPROGRESS) {
		spin_lock(&port->lock);
		if (port->write_urb_busy) {
			spin_unlock(&port->lock);
			dbg("%s - already writing", __FUNCTION__);
			return (0);
			return 0;
		}
		port->write_urb_busy = 1;
		spin_unlock(&port->lock);

		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;

@@ -195,17 +199,20 @@ int usb_serial_generic_write(struct usb_serial_port *port, const unsigned char *
				     usb_serial_generic_write_bulk_callback), port);

		/* send the data out the bulk port */
		port->write_urb_busy = 1;
		result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
		if (result)
		if (result) {
			dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
		else
			/* don't have to grab the lock here, as we will retry if != 0 */
			port->write_urb_busy = 0;
		} else
			result = count;

		return result;
	}

	/* no bulk out, so return 0 bytes written */
	return (0);
	return 0;
}

int usb_serial_generic_write_room (struct usb_serial_port *port)
@@ -216,7 +223,7 @@ int usb_serial_generic_write_room (struct usb_serial_port *port)
	dbg("%s - port %d", __FUNCTION__, port->number);

	if (serial->num_bulk_out) {
		if (port->write_urb->status != -EINPROGRESS)
		if (port->write_urb_busy)
			room = port->bulk_out_size;
	}

@@ -232,7 +239,7 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
	dbg("%s - port %d", __FUNCTION__, port->number);

	if (serial->num_bulk_out) {
		if (port->write_urb->status == -EINPROGRESS)
		if (port->write_urb_busy)
			chars = port->write_urb->transfer_buffer_length;
	}

@@ -291,6 +298,7 @@ void usb_serial_generic_write_bulk_callback (struct urb *urb, struct pt_regs *re

	dbg("%s - port %d", __FUNCTION__, port->number);

	port->write_urb_busy = 0;
	if (urb->status) {
		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
		return;
+0 −5
Original line number Diff line number Diff line
@@ -818,11 +818,6 @@ static void ipaq_write_gather(struct usb_serial_port *port)
	struct ipaq_packet	*pkt, *tmp;
	struct urb		*urb = port->write_urb;

	if (urb->status == -EINPROGRESS) {
		/* Should never happen */
		err("%s - flushing while urb is active !", __FUNCTION__);
		return;
	}
	room = URBDATA_SIZE;
	list_for_each_entry_safe(pkt, tmp, &priv->queue, list) {
		count = min(room, (int)(pkt->len - pkt->written));
+10 −4
Original line number Diff line number Diff line
@@ -400,9 +400,14 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int
		return 0;
	}

	/* Racy and broken, FIXME properly! */
	if (port->write_urb->status == -EINPROGRESS)
	spin_lock(&port->lock);
	if (port->write_urb_busy) {
		spin_unlock(&port->lock);
		dbg("%s - already writing", __FUNCTION__);
		return 0;
	}
	port->write_urb_busy = 1;
	spin_unlock(&port->lock);

	count = min(count, port->bulk_out_size);
	memcpy(port->bulk_out_buffer, buf, count);
@@ -418,6 +423,7 @@ static int ipw_write(struct usb_serial_port *port, const unsigned char *buf, int

	ret = usb_submit_urb(port->write_urb, GFP_ATOMIC);
	if (ret != 0) {
		port->write_urb_busy = 0;
		dbg("%s - usb_submit_urb(write bulk) failed with error = %d", __FUNCTION__, ret);
		return ret;
	}
+11 −5
Original line number Diff line number Diff line
@@ -341,10 +341,14 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
	if (count == 0)
		return 0;

	if (port->write_urb->status == -EINPROGRESS) {
	spin_lock(&port->lock);
	if (port->write_urb_busy) {
		spin_unlock(&port->lock);
		dbg("%s - already writing", __FUNCTION__);
		return 0;
	}
	port->write_urb_busy = 1;
	spin_unlock(&port->lock);

	transfer_buffer = port->write_urb->transfer_buffer;
	transfer_size = min(count, port->bulk_out_size - 1);
@@ -374,9 +378,10 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int
	port->write_urb->transfer_flags = URB_ZERO_PACKET;

	result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
	if (result)
	if (result) {
		port->write_urb_busy = 0;
		dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
	else
	} else
		result = transfer_size;

	return result;
@@ -388,6 +393,7 @@ static void ir_write_bulk_callback (struct urb *urb, struct pt_regs *regs)

	dbg("%s - port %d", __FUNCTION__, port->number);

	port->write_urb_busy = 0;
	if (urb->status) {
		dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
		return;
Loading