Commit 15ee89c3 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman
Browse files

USB: mos7840: fix DMA to stack



Fix regression introduced by commit 0eafe4de ("USB: serial: mos7840:
add support for MCS7810 devices") which used stack-allocated buffers for
control messages.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarJohan Hovold <jhovold@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 72ea18a5
Loading
Loading
Loading
Loading
+27 −8
Original line number Diff line number Diff line
@@ -2142,13 +2142,21 @@ static int mos7840_ioctl(struct tty_struct *tty,
static int mos7810_check(struct usb_serial *serial)
{
	int i, pass_count = 0;
	u8 *buf;
	__u16 data = 0, mcr_data = 0;
	__u16 test_pattern = 0x55AA;
	int res;

	buf = kmalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
	if (!buf)
		return 0;	/* failed to identify 7810 */

	/* Store MCR setting */
	usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
	res = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
		MCS_RDREQ, MCS_RD_RTYPE, 0x0300, MODEM_CONTROL_REGISTER,
		&mcr_data, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
		buf, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
	if (res == VENDOR_READ_LENGTH)
		mcr_data = *buf;

	for (i = 0; i < 16; i++) {
		/* Send the 1-bit test pattern out to MCS7810 test pin */
@@ -2158,9 +2166,12 @@ static int mos7810_check(struct usb_serial *serial)
			MODEM_CONTROL_REGISTER, NULL, 0, MOS_WDR_TIMEOUT);

		/* Read the test pattern back */
		usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
			MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &data,
		res = usb_control_msg(serial->dev,
				usb_rcvctrlpipe(serial->dev, 0), MCS_RDREQ,
				MCS_RD_RTYPE, 0, GPIO_REGISTER, buf,
				VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
		if (res == VENDOR_READ_LENGTH)
			data = *buf;

		/* If this is a MCS7810 device, both test patterns must match */
		if (((test_pattern >> i) ^ (~data >> 1)) & 0x0001)
@@ -2174,6 +2185,8 @@ static int mos7810_check(struct usb_serial *serial)
		MCS_WR_RTYPE, 0x0300 | mcr_data, MODEM_CONTROL_REGISTER, NULL,
		0, MOS_WDR_TIMEOUT);

	kfree(buf);

	if (pass_count == 16)
		return 1;

@@ -2183,11 +2196,17 @@ static int mos7810_check(struct usb_serial *serial)
static int mos7840_calc_num_ports(struct usb_serial *serial)
{
	__u16 data = 0x00;
	u8 *buf;
	int mos7840_num_ports;

	buf = kzalloc(VENDOR_READ_LENGTH, GFP_KERNEL);
	if (buf) {
		usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
		MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &data,
			MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, buf,
			VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
		data = *buf;
		kfree(buf);
	}

	if (serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7810 ||
		serial->dev->descriptor.idProduct == MOSCHIP_DEVICE_ID_7820) {