Commit 50de36f7 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

USB: serial: fix up urb->status usage



Some of the usb-serial drivers are starting to use urb->status in ways
they should not be doing.  This fixes up some of them to prevent that.

Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 6013bbba
Loading
Loading
Loading
Loading
+10 −18
Original line number Diff line number Diff line
@@ -635,8 +635,7 @@ static int digi_write_oob_command(struct usb_serial_port *port,

	spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
	while (count > 0) {
		while (oob_port->write_urb->status == -EINPROGRESS
			|| oob_priv->dp_write_urb_in_use) {
		while (oob_priv->dp_write_urb_in_use) {
			cond_wait_interruptible_timeout_irqrestore(
				&oob_port->write_wait, DIGI_RETRY_TIMEOUT,
				&oob_priv->dp_port_lock, flags);
@@ -699,9 +698,8 @@ static int digi_write_inb_command(struct usb_serial_port *port,

	spin_lock_irqsave(&priv->dp_port_lock, flags);
	while (count > 0 && ret == 0) {
		while ((port->write_urb->status == -EINPROGRESS
				|| priv->dp_write_urb_in_use)
					&& time_before(jiffies, timeout)) {
		while (priv->dp_write_urb_in_use &&
		       time_before(jiffies, timeout)) {
			cond_wait_interruptible_timeout_irqrestore(
				&port->write_wait, DIGI_RETRY_TIMEOUT,
				&priv->dp_port_lock, flags);
@@ -779,8 +777,7 @@ static int digi_set_modem_signals(struct usb_serial_port *port,
	spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
	spin_lock(&port_priv->dp_port_lock);

	while (oob_port->write_urb->status == -EINPROGRESS ||
					oob_priv->dp_write_urb_in_use) {
	while (oob_priv->dp_write_urb_in_use) {
		spin_unlock(&port_priv->dp_port_lock);
		cond_wait_interruptible_timeout_irqrestore(
			&oob_port->write_wait, DIGI_RETRY_TIMEOUT,
@@ -1168,12 +1165,10 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port,

	/* be sure only one write proceeds at a time */
	/* there are races on the port private buffer */
	/* and races to check write_urb->status */
	spin_lock_irqsave(&priv->dp_port_lock, flags);

	/* wait for urb status clear to submit another urb */
	if (port->write_urb->status == -EINPROGRESS ||
					priv->dp_write_urb_in_use) {
	if (priv->dp_write_urb_in_use) {
		/* buffer data if count is 1 (probably put_char) if possible */
		if (count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE) {
			priv->dp_out_buf[priv->dp_out_buf_len++] = *buf;
@@ -1236,7 +1231,7 @@ static void digi_write_bulk_callback(struct urb *urb)
	int ret = 0;
	int status = urb->status;

	dbg("digi_write_bulk_callback: TOP, urb->status=%d", status);
	dbg("digi_write_bulk_callback: TOP, status=%d", status);

	/* port and serial sanity check */
	if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
@@ -1266,8 +1261,7 @@ static void digi_write_bulk_callback(struct urb *urb)
	/* try to send any buffered data on this port, if it is open */
	spin_lock(&priv->dp_port_lock);
	priv->dp_write_urb_in_use = 0;
	if (port->port.count && port->write_urb->status != -EINPROGRESS
	    && priv->dp_out_buf_len > 0) {
	if (port->port.count && priv->dp_out_buf_len > 0) {
		*((unsigned char *)(port->write_urb->transfer_buffer))
			= (unsigned char)DIGI_CMD_SEND_DATA;
		*((unsigned char *)(port->write_urb->transfer_buffer) + 1)
@@ -1305,8 +1299,7 @@ static int digi_write_room(struct tty_struct *tty)

	spin_lock_irqsave(&priv->dp_port_lock, flags);

	if (port->write_urb->status == -EINPROGRESS ||
					priv->dp_write_urb_in_use)
	if (priv->dp_write_urb_in_use)
		room = 0;
	else
		room = port->bulk_out_size - 2 - priv->dp_out_buf_len;
@@ -1322,8 +1315,7 @@ static int digi_chars_in_buffer(struct tty_struct *tty)
	struct usb_serial_port *port = tty->driver_data;
	struct digi_port *priv = usb_get_serial_port_data(port);

	if (port->write_urb->status == -EINPROGRESS
	    || priv->dp_write_urb_in_use) {
	if (priv->dp_write_urb_in_use) {
		dbg("digi_chars_in_buffer: port=%d, chars=%d",
			priv->dp_port_num, port->bulk_out_size - 2);
		/* return(port->bulk_out_size - 2); */
@@ -1702,7 +1694,7 @@ static int digi_read_inb_callback(struct urb *urb)
	/* short/multiple packet check */
	if (urb->actual_length != len + 2) {
		dev_err(&port->dev, "%s: INCOMPLETE OR MULTIPLE PACKET, "
			"urb->status=%d, port=%d, opcode=%d, len=%d, "
			"status=%d, port=%d, opcode=%d, len=%d, "
			"actual_length=%d, status=%d\n", __func__, status,
			priv->dp_port_num, opcode, len, urb->actual_length,
			port_status);
+1 −1
Original line number Diff line number Diff line
@@ -1056,7 +1056,7 @@ static void garmin_write_bulk_callback(struct urb *urb)

		if (status) {
			dbg("%s - nonzero write bulk status received: %d",
			    __func__, urb->status);
			    __func__, status);
			spin_lock_irqsave(&garmin_data_p->lock, flags);
			garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
			spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+21 −17
Original line number Diff line number Diff line
@@ -190,10 +190,12 @@ static void iuu_rxcmd(struct urb *urb)
{
	struct usb_serial_port *port = urb->context;
	int result;
	int status = urb->status;

	dbg("%s - enter", __func__);

	if (urb->status) {
		dbg("%s - urb->status = %d", __func__, urb->status);
	if (status) {
		dbg("%s - status = %d", __func__, status);
		/* error stop all */
		return;
	}
@@ -245,10 +247,12 @@ static void iuu_update_status_callback(struct urb *urb)
	struct usb_serial_port *port = urb->context;
	struct iuu_private *priv = usb_get_serial_port_data(port);
	u8 *st;
	int status = urb->status;

	dbg("%s - enter", __func__);

	if (urb->status) {
		dbg("%s - urb->status = %d", __func__, urb->status);
	if (status) {
		dbg("%s - status = %d", __func__, status);
		/* error stop all */
		return;
	}
@@ -274,9 +278,9 @@ static void iuu_status_callback(struct urb *urb)
{
	struct usb_serial_port *port = urb->context;
	int result;
	dbg("%s - enter", __func__);
	int status = urb->status;

	dbg("%s - urb->status = %d", __func__, urb->status);
	dbg("%s - status = %d", __func__, status);
	usb_fill_bulk_urb(port->read_urb, port->serial->dev,
			  usb_rcvbulkpipe(port->serial->dev,
					  port->bulk_in_endpointAddress),
@@ -618,11 +622,12 @@ static void read_buf_callback(struct urb *urb)
	struct usb_serial_port *port = urb->context;
	unsigned char *data = urb->transfer_buffer;
	struct tty_struct *tty;
	dbg("%s - urb->status = %d", __func__, urb->status);
	int status = urb->status;

	if (urb->status) {
		dbg("%s - urb->status = %d", __func__, urb->status);
		if (urb->status == -EPROTO) {
	dbg("%s - status = %d", __func__, status);

	if (status) {
		if (status == -EPROTO) {
			/* reschedule needed */
		}
		return;
@@ -695,7 +700,7 @@ static void iuu_uart_read_callback(struct urb *urb)
	struct usb_serial_port *port = urb->context;
	struct iuu_private *priv = usb_get_serial_port_data(port);
	unsigned long flags;
	int status;
	int status = urb->status;
	int error = 0;
	int len = 0;
	unsigned char *data = urb->transfer_buffer;
@@ -703,8 +708,8 @@ static void iuu_uart_read_callback(struct urb *urb)

	dbg("%s - enter", __func__);

	if (urb->status) {
		dbg("%s - urb->status = %d", __func__, urb->status);
	if (status) {
		dbg("%s - status = %d", __func__, status);
		/* error stop all */
		return;
	}
@@ -782,12 +787,11 @@ static void read_rxcmd_callback(struct urb *urb)
{
	struct usb_serial_port *port = urb->context;
	int result;
	dbg("%s - enter", __func__);
	int status = urb->status;

	dbg("%s - urb->status = %d", __func__, urb->status);
	dbg("%s - status = %d", __func__, status);

	if (urb->status) {
		dbg("%s - urb->status = %d", __func__, urb->status);
	if (status) {
		/* error stop all */
		return;
	}
+25 −13
Original line number Diff line number Diff line
@@ -214,6 +214,7 @@ struct moschip_port {
	spinlock_t pool_lock;
	struct urb *write_urb_pool[NUM_URBS];
	char busy[NUM_URBS];
	bool read_urb_busy;
};


@@ -679,26 +680,30 @@ static void mos7840_bulk_in_callback(struct urb *urb)
	struct tty_struct *tty;
	int status = urb->status;

	if (status) {
		dbg("nonzero read bulk status received: %d", status);
		return;
	}

	mos7840_port = urb->context;
	if (!mos7840_port) {
		dbg("%s", "NULL mos7840_port pointer \n");
		mos7840_port->read_urb_busy = false;
		return;
	}

	if (status) {
		dbg("nonzero read bulk status received: %d", status);
		mos7840_port->read_urb_busy = false;
		return;
	}

	port = (struct usb_serial_port *)mos7840_port->port;
	if (mos7840_port_paranoia_check(port, __func__)) {
		dbg("%s", "Port Paranoia failed \n");
		mos7840_port->read_urb_busy = false;
		return;
	}

	serial = mos7840_get_usb_serial(port, __func__);
	if (!serial) {
		dbg("%s\n", "Bad serial pointer ");
		mos7840_port->read_urb_busy = false;
		return;
	}

@@ -725,17 +730,19 @@ static void mos7840_bulk_in_callback(struct urb *urb)

	if (!mos7840_port->read_urb) {
		dbg("%s", "URB KILLED !!!\n");
		mos7840_port->read_urb_busy = false;
		return;
	}


	mos7840_port->read_urb->dev = serial->dev;

	mos7840_port->read_urb_busy = true;
	retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);

	if (retval) {
		dbg(" usb_submit_urb(read bulk) failed, retval = %d",
		 retval);
		dbg("usb_submit_urb(read bulk) failed, retval = %d", retval);
		mos7840_port->read_urb_busy = false;
	}
}

@@ -1055,10 +1062,12 @@ static int mos7840_open(struct tty_struct *tty,

	dbg("mos7840_open: bulkin endpoint is %d\n",
	    port->bulk_in_endpointAddress);
	mos7840_port->read_urb_busy = true;
	response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL);
	if (response) {
		dev_err(&port->dev, "%s - Error %d submitting control urb\n",
			__func__, response);
		mos7840_port->read_urb_busy = false;
	}

	/* initialize our wait queues */
@@ -1227,6 +1236,7 @@ static void mos7840_close(struct tty_struct *tty,
		if (mos7840_port->read_urb) {
			dbg("%s", "Shutdown bulk read\n");
			usb_kill_urb(mos7840_port->read_urb);
			mos7840_port->read_urb_busy = false;
		}
		if ((&mos7840_port->control_urb)) {
			dbg("%s", "Shutdown control read\n");
@@ -2043,14 +2053,14 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
	Data = 0x0c;
	mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data);

	if (mos7840_port->read_urb->status != -EINPROGRESS) {
	if (mos7840_port->read_urb_busy == false) {
		mos7840_port->read_urb->dev = serial->dev;

		mos7840_port->read_urb_busy = true;
		status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);

		if (status) {
			dbg("usb_submit_urb(read bulk) failed, status = %d",
			    status);
			mos7840_port->read_urb_busy = false;
		}
	}
	wake_up(&mos7840_port->delta_msr_wait);
@@ -2117,12 +2127,14 @@ static void mos7840_set_termios(struct tty_struct *tty,
		return;
	}

	if (mos7840_port->read_urb->status != -EINPROGRESS) {
	if (mos7840_port->read_urb_busy == false) {
		mos7840_port->read_urb->dev = serial->dev;
		mos7840_port->read_urb_busy = true;
		status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC);
		if (status) {
			dbg("usb_submit_urb(read bulk) failed, status = %d",
			    status);
			mos7840_port->read_urb_busy = false;
		}
	}
	return;
+1 −6
Original line number Diff line number Diff line
@@ -654,10 +654,6 @@ static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
			usb_unlink_urb(this_urb);
			continue;
		}
		if (this_urb->status != 0)
			dbg("usb_write %p failed (err=%d)",
				this_urb, this_urb->status);

		dbg("%s: endpoint %d buf %d", __func__,
			usb_pipeendpoint(this_urb->pipe), i);

@@ -669,8 +665,7 @@ static int option_write(struct tty_struct *tty, struct usb_serial_port *port,
		err = usb_submit_urb(this_urb, GFP_ATOMIC);
		if (err) {
			dbg("usb_submit_urb %p (write bulk) failed "
				"(%d, has %d)", this_urb,
				err, this_urb->status);
				"(%d)", this_urb, err);
			clear_bit(i, &portdata->out_busy);
			continue;
		}
Loading