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

Commit 60d5794f authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge tag 'usb-serial-4.7-rc1' of...

Merge tag 'usb-serial-4.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/johan/usb-serial

 into usb-next

Johan writes:

USB-serial updates for v4.7-rc1

These updates fixes a number of issues where resources were not properly
released on probe errors. Included is also a fix for hardware
flow-control disable for cp210x.

Support for Moxa UPort 11x0 is added to the ti_usb_3410_5052 driver, and
included are also some general code clean ups.

Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
parents 13069bd9 b923c6c6
Loading
Loading
Loading
Loading
+74 −28
Original line number Diff line number Diff line
@@ -331,6 +331,42 @@ struct cp210x_comm_status {
 */
#define PURGE_ALL		0x000f

/* CP210X_GET_FLOW/CP210X_SET_FLOW read/write these 0x10 bytes */
struct cp210x_flow_ctl {
	__le32	ulControlHandshake;
	__le32	ulFlowReplace;
	__le32	ulXonLimit;
	__le32	ulXoffLimit;
} __packed;

/* cp210x_flow_ctl::ulControlHandshake */
#define CP210X_SERIAL_DTR_MASK		GENMASK(1, 0)
#define CP210X_SERIAL_DTR_SHIFT(_mode)	(_mode)
#define CP210X_SERIAL_CTS_HANDSHAKE	BIT(3)
#define CP210X_SERIAL_DSR_HANDSHAKE	BIT(4)
#define CP210X_SERIAL_DCD_HANDSHAKE	BIT(5)
#define CP210X_SERIAL_DSR_SENSITIVITY	BIT(6)

/* values for cp210x_flow_ctl::ulControlHandshake::CP210X_SERIAL_DTR_MASK */
#define CP210X_SERIAL_DTR_INACTIVE	0
#define CP210X_SERIAL_DTR_ACTIVE	1
#define CP210X_SERIAL_DTR_FLOW_CTL	2

/* cp210x_flow_ctl::ulFlowReplace */
#define CP210X_SERIAL_AUTO_TRANSMIT	BIT(0)
#define CP210X_SERIAL_AUTO_RECEIVE	BIT(1)
#define CP210X_SERIAL_ERROR_CHAR	BIT(2)
#define CP210X_SERIAL_NULL_STRIPPING	BIT(3)
#define CP210X_SERIAL_BREAK_CHAR	BIT(4)
#define CP210X_SERIAL_RTS_MASK		GENMASK(7, 6)
#define CP210X_SERIAL_RTS_SHIFT(_mode)	(_mode << 6)
#define CP210X_SERIAL_XOFF_CONTINUE	BIT(31)

/* values for cp210x_flow_ctl::ulFlowReplace::CP210X_SERIAL_RTS_MASK */
#define CP210X_SERIAL_RTS_INACTIVE	0
#define CP210X_SERIAL_RTS_ACTIVE	1
#define CP210X_SERIAL_RTS_FLOW_CTL	2

/*
 * Reads a variable-sized block of CP210X_ registers, identified by req.
 * Returns data into buf in native USB byte order.
@@ -698,9 +734,10 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
{
	struct device *dev = &port->dev;
	unsigned int cflag;
	u8 modem_ctl[16];
	struct cp210x_flow_ctl flow_ctl;
	u32 baud;
	u16 bits;
	u32 ctl_hs;

	cp210x_read_u32_reg(port, CP210X_GET_BAUDRATE, &baud);

@@ -796,9 +833,10 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
		break;
	}

	cp210x_read_reg_block(port, CP210X_GET_FLOW, modem_ctl,
			sizeof(modem_ctl));
	if (modem_ctl[0] & 0x08) {
	cp210x_read_reg_block(port, CP210X_GET_FLOW, &flow_ctl,
			sizeof(flow_ctl));
	ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake);
	if (ctl_hs & CP210X_SERIAL_CTS_HANDSHAKE) {
		dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__);
		cflag |= CRTSCTS;
	} else {
@@ -867,7 +905,6 @@ static void cp210x_set_termios(struct tty_struct *tty,
	struct device *dev = &port->dev;
	unsigned int cflag, old_cflag;
	u16 bits;
	u8 modem_ctl[16];

	cflag = tty->termios.c_cflag;
	old_cflag = old_termios->c_cflag;
@@ -951,35 +988,44 @@ static void cp210x_set_termios(struct tty_struct *tty,
	}

	if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {

		/* Only bytes 0, 4 and 7 out of first 8 have functional bits */

		cp210x_read_reg_block(port, CP210X_GET_FLOW, modem_ctl,
				sizeof(modem_ctl));
		dev_dbg(dev, "%s - read modem controls = %02x .. .. .. %02x .. .. %02x\n",
			__func__, modem_ctl[0], modem_ctl[4], modem_ctl[7]);

		struct cp210x_flow_ctl flow_ctl;
		u32 ctl_hs;
		u32 flow_repl;

		cp210x_read_reg_block(port, CP210X_GET_FLOW, &flow_ctl,
				sizeof(flow_ctl));
		ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake);
		flow_repl = le32_to_cpu(flow_ctl.ulFlowReplace);
		dev_dbg(dev, "%s - read ulControlHandshake=0x%08x, ulFlowReplace=0x%08x\n",
				__func__, ctl_hs, flow_repl);

		ctl_hs &= ~CP210X_SERIAL_DSR_HANDSHAKE;
		ctl_hs &= ~CP210X_SERIAL_DCD_HANDSHAKE;
		ctl_hs &= ~CP210X_SERIAL_DSR_SENSITIVITY;
		ctl_hs &= ~CP210X_SERIAL_DTR_MASK;
		ctl_hs |= CP210X_SERIAL_DTR_SHIFT(CP210X_SERIAL_DTR_ACTIVE);
		if (cflag & CRTSCTS) {
			modem_ctl[0] &= ~0x7B;
			modem_ctl[0] |= 0x09;
			modem_ctl[4] = 0x80;
			/* FIXME - why clear reserved bits just read? */
			modem_ctl[5] = 0;
			modem_ctl[6] = 0;
			modem_ctl[7] = 0;
			ctl_hs |= CP210X_SERIAL_CTS_HANDSHAKE;

			flow_repl &= ~CP210X_SERIAL_RTS_MASK;
			flow_repl |= CP210X_SERIAL_RTS_SHIFT(
					CP210X_SERIAL_RTS_FLOW_CTL);
			dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__);
		} else {
			modem_ctl[0] &= ~0x7B;
			modem_ctl[0] |= 0x01;
			/* FIXME - OR here instead of assignment looks wrong */
			modem_ctl[4] |= 0x40;
			ctl_hs &= ~CP210X_SERIAL_CTS_HANDSHAKE;

			flow_repl &= ~CP210X_SERIAL_RTS_MASK;
			flow_repl |= CP210X_SERIAL_RTS_SHIFT(
					CP210X_SERIAL_RTS_ACTIVE);
			dev_dbg(dev, "%s - flow control = NONE\n", __func__);
		}

		dev_dbg(dev, "%s - write modem controls = %02x .. .. .. %02x .. .. %02x\n",
			__func__, modem_ctl[0], modem_ctl[4], modem_ctl[7]);
		cp210x_write_reg_block(port, CP210X_SET_FLOW, modem_ctl,
				sizeof(modem_ctl));
		dev_dbg(dev, "%s - write ulControlHandshake=0x%08x, ulFlowReplace=0x%08x\n",
				__func__, ctl_hs, flow_repl);
		flow_ctl.ulControlHandshake = cpu_to_le32(ctl_hs);
		flow_ctl.ulFlowReplace = cpu_to_le32(flow_repl);
		cp210x_write_reg_block(port, CP210X_SET_FLOW, &flow_ctl,
				sizeof(flow_ctl));
	}

}
+8 −8
Original line number Diff line number Diff line
@@ -93,27 +93,27 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial);
static void  ftdi_USB_UIRT_setup(struct ftdi_private *priv);
static void  ftdi_HE_TIRA1_setup(struct ftdi_private *priv);

static struct ftdi_sio_quirk ftdi_jtag_quirk = {
static const struct ftdi_sio_quirk ftdi_jtag_quirk = {
	.probe	= ftdi_jtag_probe,
};

static struct ftdi_sio_quirk ftdi_NDI_device_quirk = {
static const struct ftdi_sio_quirk ftdi_NDI_device_quirk = {
	.probe	= ftdi_NDI_device_setup,
};

static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
static const struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = {
	.port_probe = ftdi_USB_UIRT_setup,
};

static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
static const struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = {
	.port_probe = ftdi_HE_TIRA1_setup,
};

static struct ftdi_sio_quirk ftdi_stmclite_quirk = {
static const struct ftdi_sio_quirk ftdi_stmclite_quirk = {
	.probe	= ftdi_stmclite_probe,
};

static struct ftdi_sio_quirk ftdi_8u2232c_quirk = {
static const struct ftdi_sio_quirk ftdi_8u2232c_quirk = {
	.probe	= ftdi_8u2232c_probe,
};

@@ -1775,7 +1775,7 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
static int ftdi_sio_probe(struct usb_serial *serial,
					const struct usb_device_id *id)
{
	struct ftdi_sio_quirk *quirk =
	const struct ftdi_sio_quirk *quirk =
				(struct ftdi_sio_quirk *)id->driver_info;

	if (quirk && quirk->probe) {
@@ -1792,7 +1792,7 @@ static int ftdi_sio_probe(struct usb_serial *serial,
static int ftdi_sio_port_probe(struct usb_serial_port *port)
{
	struct ftdi_private *priv;
	struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);
	const struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial);


	priv = kzalloc(sizeof(struct ftdi_private), GFP_KERNEL);
+38 −18
Original line number Diff line number Diff line
@@ -2849,14 +2849,16 @@ static int edge_startup(struct usb_serial *serial)
				/* not set up yet, so do it now */
				edge_serial->interrupt_read_urb =
						usb_alloc_urb(0, GFP_KERNEL);
				if (!edge_serial->interrupt_read_urb)
					return -ENOMEM;
				if (!edge_serial->interrupt_read_urb) {
					response = -ENOMEM;
					break;
				}

				edge_serial->interrupt_in_buffer =
					kmalloc(buffer_size, GFP_KERNEL);
				if (!edge_serial->interrupt_in_buffer) {
					usb_free_urb(edge_serial->interrupt_read_urb);
					return -ENOMEM;
					response = -ENOMEM;
					break;
				}
				edge_serial->interrupt_in_endpoint =
						endpoint->bEndpointAddress;
@@ -2884,14 +2886,16 @@ static int edge_startup(struct usb_serial *serial)
				/* not set up yet, so do it now */
				edge_serial->read_urb =
						usb_alloc_urb(0, GFP_KERNEL);
				if (!edge_serial->read_urb)
					return -ENOMEM;
				if (!edge_serial->read_urb) {
					response = -ENOMEM;
					break;
				}

				edge_serial->bulk_in_buffer =
					kmalloc(buffer_size, GFP_KERNEL);
				if (!edge_serial->bulk_in_buffer) {
					usb_free_urb(edge_serial->read_urb);
					return -ENOMEM;
					response = -ENOMEM;
					break;
				}
				edge_serial->bulk_in_endpoint =
						endpoint->bEndpointAddress;
@@ -2917,9 +2921,22 @@ static int edge_startup(struct usb_serial *serial)
			}
		}

		if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) {
			dev_err(ddev, "Error - the proper endpoints were not found!\n");
			return -ENODEV;
		if (response || !interrupt_in_found || !bulk_in_found ||
							!bulk_out_found) {
			if (!response) {
				dev_err(ddev, "expected endpoints not found\n");
				response = -ENODEV;
			}

			usb_free_urb(edge_serial->interrupt_read_urb);
			kfree(edge_serial->interrupt_in_buffer);

			usb_free_urb(edge_serial->read_urb);
			kfree(edge_serial->bulk_in_buffer);

			kfree(edge_serial);

			return response;
		}

		/* start interrupt read for this edgeport this interrupt will
@@ -2942,16 +2959,9 @@ static void edge_disconnect(struct usb_serial *serial)
{
	struct edgeport_serial *edge_serial = usb_get_serial_data(serial);

	/* stop reads and writes on all ports */
	/* free up our endpoint stuff */
	if (edge_serial->is_epic) {
		usb_kill_urb(edge_serial->interrupt_read_urb);
		usb_free_urb(edge_serial->interrupt_read_urb);
		kfree(edge_serial->interrupt_in_buffer);

		usb_kill_urb(edge_serial->read_urb);
		usb_free_urb(edge_serial->read_urb);
		kfree(edge_serial->bulk_in_buffer);
	}
}

@@ -2964,6 +2974,16 @@ static void edge_release(struct usb_serial *serial)
{
	struct edgeport_serial *edge_serial = usb_get_serial_data(serial);

	if (edge_serial->is_epic) {
		usb_kill_urb(edge_serial->interrupt_read_urb);
		usb_free_urb(edge_serial->interrupt_read_urb);
		kfree(edge_serial->interrupt_in_buffer);

		usb_kill_urb(edge_serial->read_urb);
		usb_free_urb(edge_serial->read_urb);
		kfree(edge_serial->bulk_in_buffer);
	}

	kfree(edge_serial);
}

+39 −33
Original line number Diff line number Diff line
@@ -255,7 +255,7 @@ static int keyspan_write(struct tty_struct *tty,
			return count;
		}

		dev_dbg(&port->dev, "%s - endpoint %d flip %d\n",
		dev_dbg(&port->dev, "%s - endpoint %x flip %d\n",
			__func__, usb_pipeendpoint(this_urb->pipe), flip);

		if (this_urb->status == -EINPROGRESS) {
@@ -300,7 +300,7 @@ static void usa26_indat_callback(struct urb *urb)
	endpoint = usb_pipeendpoint(urb->pipe);

	if (status) {
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
		dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
			__func__, status, endpoint);
		return;
	}
@@ -393,7 +393,8 @@ static void usa26_instat_callback(struct urb *urb)
	serial =  urb->context;

	if (status) {
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
				__func__, status);
		return;
	}
	if (urb->actual_length != 9) {
@@ -452,7 +453,7 @@ static void usa28_indat_callback(struct urb *urb)

	do {
		if (status) {
			dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
			dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
				__func__, status, usb_pipeendpoint(urb->pipe));
			return;
		}
@@ -511,7 +512,8 @@ static void usa28_instat_callback(struct urb *urb)
	serial =  urb->context;

	if (status) {
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
				__func__, status);
		return;
	}

@@ -591,7 +593,8 @@ static void usa49_instat_callback(struct urb *urb)
	serial =  urb->context;

	if (status) {
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
				__func__, status);
		return;
	}

@@ -646,7 +649,7 @@ static void usa49_indat_callback(struct urb *urb)
	endpoint = usb_pipeendpoint(urb->pipe);

	if (status) {
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
		dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
			__func__, status, endpoint);
		return;
	}
@@ -698,7 +701,8 @@ static void usa49wg_indat_callback(struct urb *urb)
	serial = urb->context;

	if (status) {
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
				__func__, status);
		return;
	}

@@ -774,7 +778,7 @@ static void usa90_indat_callback(struct urb *urb)
	endpoint = usb_pipeendpoint(urb->pipe);

	if (status) {
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n",
		dev_dbg(&urb->dev->dev, "%s - nonzero status %d on endpoint %x\n",
			__func__, status, endpoint);
		return;
	}
@@ -847,7 +851,8 @@ static void usa90_instat_callback(struct urb *urb)
	serial =  urb->context;

	if (status) {
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
				__func__, status);
		return;
	}
	if (urb->actual_length < 14) {
@@ -912,7 +917,8 @@ static void usa67_instat_callback(struct urb *urb)
	serial = urb->context;

	if (status) {
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status);
		dev_dbg(&urb->dev->dev, "%s - nonzero status: %d\n",
				__func__, status);
		return;
	}

@@ -1082,12 +1088,6 @@ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port)
	return 0;
}

static inline void stop_urb(struct urb *urb)
{
	if (urb && urb->status == -EINPROGRESS)
		usb_kill_urb(urb);
}

static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
{
	struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
@@ -1114,10 +1114,10 @@ static void keyspan_close(struct usb_serial_port *port)
	p_priv->out_flip = 0;
	p_priv->in_flip = 0;

	stop_urb(p_priv->inack_urb);
	usb_kill_urb(p_priv->inack_urb);
	for (i = 0; i < 2; i++) {
		stop_urb(p_priv->in_urbs[i]);
		stop_urb(p_priv->out_urbs[i]);
		usb_kill_urb(p_priv->in_urbs[i]);
		usb_kill_urb(p_priv->out_urbs[i]);
	}
}

@@ -1221,8 +1221,8 @@ static struct usb_endpoint_descriptor const *find_ep(struct usb_serial const *se
		if (ep->bEndpointAddress == endpoint)
			return ep;
	}
	dev_warn(&serial->interface->dev, "found no endpoint descriptor for "
		 "endpoint %x\n", endpoint);
	dev_warn(&serial->interface->dev, "found no endpoint descriptor for endpoint %x\n",
			endpoint);
	return NULL;
}

@@ -1237,7 +1237,8 @@ static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint,
	if (endpoint == -1)
		return NULL;		/* endpoint not needed */

	dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d.\n", __func__, endpoint);
	dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %x\n",
			__func__, endpoint);
	urb = usb_alloc_urb(0, GFP_KERNEL);		/* No ISO */
	if (!urb)
		return NULL;
@@ -1572,7 +1573,8 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial,
		return -1;
	}

	dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe));
	dev_dbg(&port->dev, "%s - endpoint %x\n",
			__func__, usb_pipeendpoint(this_urb->pipe));

	/* Save reset port val for resend.
	   Don't overwrite resend for open/close condition. */
@@ -1838,7 +1840,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial,
		return -1;
	}

	dev_dbg(&port->dev, "%s - endpoint %d (%d)\n",
	dev_dbg(&port->dev, "%s - endpoint %x (%d)\n",
		__func__, usb_pipeendpoint(this_urb->pipe), device_port);

	/* Save reset port val for resend.
@@ -2365,9 +2367,9 @@ static void keyspan_disconnect(struct usb_serial *serial)

	s_priv = usb_get_serial_data(serial);

	stop_urb(s_priv->instat_urb);
	stop_urb(s_priv->glocont_urb);
	stop_urb(s_priv->indat_urb);
	usb_kill_urb(s_priv->instat_urb);
	usb_kill_urb(s_priv->glocont_urb);
	usb_kill_urb(s_priv->indat_urb);
}

static void keyspan_release(struct usb_serial *serial)
@@ -2376,6 +2378,10 @@ static void keyspan_release(struct usb_serial *serial)

	s_priv = usb_get_serial_data(serial);

	/* Make sure to unlink the URBs submitted in attach. */
	usb_kill_urb(s_priv->instat_urb);
	usb_kill_urb(s_priv->indat_urb);

	usb_free_urb(s_priv->instat_urb);
	usb_free_urb(s_priv->indat_urb);
	usb_free_urb(s_priv->glocont_urb);
@@ -2491,11 +2497,11 @@ static int keyspan_port_remove(struct usb_serial_port *port)

	p_priv = usb_get_serial_port_data(port);

	stop_urb(p_priv->inack_urb);
	stop_urb(p_priv->outcont_urb);
	usb_kill_urb(p_priv->inack_urb);
	usb_kill_urb(p_priv->outcont_urb);
	for (i = 0; i < 2; i++) {
		stop_urb(p_priv->in_urbs[i]);
		stop_urb(p_priv->out_urbs[i]);
		usb_kill_urb(p_priv->in_urbs[i]);
		usb_kill_urb(p_priv->out_urbs[i]);
	}

	usb_free_urb(p_priv->inack_urb);
+10 −0
Original line number Diff line number Diff line
@@ -1259,6 +1259,15 @@ static int mxuport_attach(struct usb_serial *serial)
	return 0;
}

static void mxuport_release(struct usb_serial *serial)
{
	struct usb_serial_port *port0 = serial->port[0];
	struct usb_serial_port *port1 = serial->port[1];

	usb_serial_generic_close(port1);
	usb_serial_generic_close(port0);
}

static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port)
{
	struct mxuport_port *mxport = usb_get_serial_port_data(port);
@@ -1361,6 +1370,7 @@ static struct usb_serial_driver mxuport_device = {
	.probe			= mxuport_probe,
	.port_probe		= mxuport_port_probe,
	.attach			= mxuport_attach,
	.release		= mxuport_release,
	.calc_num_ports		= mxuport_calc_num_ports,
	.open			= mxuport_open,
	.close			= mxuport_close,
Loading