From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756150AbcANQa4 (ORCPT ); Thu, 14 Jan 2016 11:30:56 -0500 Received: from bhuna.collabora.co.uk ([46.235.227.227]:42389 "EHLO bhuna.collabora.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753386AbcANQay (ORCPT ); Thu, 14 Jan 2016 11:30:54 -0500 Message-ID: <5697CD37.4090504@collabora.co.uk> Date: Thu, 14 Jan 2016 16:30:47 +0000 From: Martyn Welch User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Icedove/31.8.0 MIME-Version: 1.0 Newsgroups: gmane.linux.kernel,gmane.linux.usb.general To: Konstantin Shkolnyy , johan@kernel.org CC: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v2 1/3 RESEND] USB: serial: cp210x: New 16-bit register access functions. References: <1450836867-27120-1-git-send-email-konstantin.shkolnyy@gmail.com> In-Reply-To: <1450836867-27120-1-git-send-email-konstantin.shkolnyy@gmail.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 23/12/15 02:14, Konstantin Shkolnyy wrote: > cp210x_get_config and cp210x_set_config are cumbersome to use. This change > introduces new register access functions for 16-bit values, instead of > the above functions. > > Signed-off-by: Konstantin Shkolnyy > --- > drivers/usb/serial/cp210x.c | 155 +++++++++++++++++++++++++++++++------------- > 1 file changed, 111 insertions(+), 44 deletions(-) > > diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c > index fd67958..fd7c4f4 100644 > --- a/drivers/usb/serial/cp210x.c > +++ b/drivers/usb/serial/cp210x.c > @@ -422,14 +422,88 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, > } > > /* > - * cp210x_set_config_single > - * Convenience function for calling cp210x_set_config on single data values > - * without requiring an integer pointer > + * Reads a variable-sized block of CP210X_ registers, identified by req. > + * Returns data into buf in native USB byte order. > */ > -static inline int cp210x_set_config_single(struct usb_serial_port *port, > - u8 request, unsigned int data) > +static int cp210x_read_reg_block(struct usb_serial_port *port, u8 req, > + void *buf, int bufsize) > { > - return cp210x_set_config(port, request, &data, 2); > + struct usb_serial *serial = port->serial; > + struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); > + void *dmabuf; > + int result; > + > + dmabuf = kmalloc(bufsize, GFP_KERNEL); > + if (!dmabuf) { > + /* > + * FIXME Some callers don't bother to check for error, > + * at least give them consistent junk until they are fixed > + */ > + memset(buf, 0, bufsize); > + return -ENOMEM; > + } > + > + result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), > + req, REQTYPE_INTERFACE_TO_HOST, 0, > + port_priv->bInterfaceNumber, dmabuf, bufsize, > + USB_CTRL_SET_TIMEOUT); > + if (result == bufsize) { > + memcpy(buf, dmabuf, bufsize); > + result = 0; I could be wrong, but isn't dmabuf a little-endian stream (hence the byte order swapping in the existing set and get functions). Won't this break on big endian systems due to the lack of byte swapping? Martyn > + } else { > + dev_err(&port->dev, "failed get req 0x%x size %d status: %d\n", > + req, bufsize, result); > + if (result >= 0) > + result = -EPROTO; > + > + /* > + * FIXME Some callers don't bother to check for error, > + * at least give them consistent junk until they are fixed > + */ > + memset(buf, 0, bufsize); > + } > + > + kfree(dmabuf); > + > + return result; > +} > + > +/* > + * Reads any 16-bit CP210X_ register identified by req. > + */ > +static int cp210x_read_u16_reg(struct usb_serial_port *port, u8 req, u16 *val) > +{ > + __le16 le16_val; > + int err; > + > + err = cp210x_read_reg_block(port, req, &le16_val, sizeof(le16_val)); > + if (err) > + return err; > + > + *val = le16_to_cpu(le16_val); > + return 0; > +} > + > +/* > + * Writes any 16-bit CP210X_ register (req) whose value is passed > + * entirely in the wValue field of the USB request. > + */ > +static int cp210x_write_u16_reg(struct usb_serial_port *port, u8 req, u16 val) > +{ > + struct usb_serial *serial = port->serial; > + struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); > + int result; > + > + result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), > + req, REQTYPE_HOST_TO_INTERFACE, val, > + port_priv->bInterfaceNumber, NULL, 0, > + USB_CTRL_SET_TIMEOUT); > + if (result < 0) { > + dev_err(&port->dev, "failed set request 0x%x status: %d\n", > + req, result); > + } > + > + return result; > } > > /* > @@ -441,48 +515,47 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port, > static int cp210x_detect_swapped_line_ctl(struct usb_serial_port *port) > { > struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); > - unsigned int line_ctl_save; > - unsigned int line_ctl_test; > + u16 line_ctl_save; > + u16 line_ctl_test; > int err; > > - err = cp210x_get_config(port, CP210X_GET_LINE_CTL, &line_ctl_save, 2); > + err = cp210x_read_u16_reg(port, CP210X_GET_LINE_CTL, &line_ctl_save); > if (err) > return err; > > - line_ctl_test = 0x800; > - err = cp210x_set_config(port, CP210X_SET_LINE_CTL, &line_ctl_test, 2); > + err = cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, 0x800); > if (err) > return err; > > - err = cp210x_get_config(port, CP210X_GET_LINE_CTL, &line_ctl_test, 2); > + err = cp210x_read_u16_reg(port, CP210X_GET_LINE_CTL, &line_ctl_test); > if (err) > return err; > > /* has_swapped_line_ctl is 0 here because port_priv was kzalloced */ > if (line_ctl_test == 8) { > port_priv->has_swapped_line_ctl = true; > - line_ctl_save = swab16((u16)line_ctl_save); > + line_ctl_save = swab16(line_ctl_save); > } > > - return cp210x_set_config(port, CP210X_SET_LINE_CTL, &line_ctl_save, 2); > + return cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, line_ctl_save); > } > > /* > - * Must always be called instead of cp210x_get_config(CP210X_GET_LINE_CTL) > + * Must always be called instead of cp210x_read_u16_reg(CP210X_GET_LINE_CTL) > * to workaround cp2108 bug and get correct value. > */ > -static int cp210x_get_line_ctl(struct usb_serial_port *port, unsigned int *ctl) > +static int cp210x_get_line_ctl(struct usb_serial_port *port, u16 *ctl) > { > struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); > int err; > > - err = cp210x_get_config(port, CP210X_GET_LINE_CTL, ctl, 2); > + err = cp210x_read_u16_reg(port, CP210X_GET_LINE_CTL, ctl); > if (err) > return err; > > /* Workaround swapped bytes in 16-bit value from CP210X_GET_LINE_CTL */ > if (port_priv->has_swapped_line_ctl) > - *ctl = swab16((u16)(*ctl)); > + *ctl = swab16(*ctl); > > return 0; > } > @@ -531,14 +604,11 @@ static unsigned int cp210x_quantise_baudrate(unsigned int baud) > > static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port) > { > - int result; > + int err; > > - result = cp210x_set_config_single(port, CP210X_IFC_ENABLE, > - UART_ENABLE); > - if (result) { > - dev_err(&port->dev, "%s - Unable to enable UART\n", __func__); > - return result; > - } > + err = cp210x_write_u16_reg(port, CP210X_IFC_ENABLE, UART_ENABLE); > + if (err) > + return err; > > /* Configure the termios structure */ > cp210x_get_termios(tty, port); > @@ -552,15 +622,12 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port) > > static void cp210x_close(struct usb_serial_port *port) > { > - unsigned int purge_ctl; > - > usb_serial_generic_close(port); > > /* Clear both queues; cp2108 needs this to avoid an occasional hang */ > - purge_ctl = PURGE_ALL; > - cp210x_set_config(port, CP210X_PURGE, &purge_ctl, 2); > + cp210x_write_u16_reg(port, CP210X_PURGE, PURGE_ALL); > > - cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE); > + cp210x_write_u16_reg(port, CP210X_IFC_ENABLE, UART_DISABLE); > } > > /* > @@ -640,7 +707,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, > struct device *dev = &port->dev; > unsigned int cflag, modem_ctl[4]; > unsigned int baud; > - unsigned int bits; > + u16 bits; > > cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4); > > @@ -673,14 +740,14 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, > cflag |= CS8; > bits &= ~BITS_DATA_MASK; > bits |= BITS_DATA_8; > - cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); > + cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits); > break; > default: > dev_dbg(dev, "%s - Unknown number of data bits, using 8\n", __func__); > cflag |= CS8; > bits &= ~BITS_DATA_MASK; > bits |= BITS_DATA_8; > - cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); > + cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits); > break; > } > > @@ -711,7 +778,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, > dev_dbg(dev, "%s - Unknown parity mode, disabling parity\n", __func__); > cflag &= ~PARENB; > bits &= ~BITS_PARITY_MASK; > - cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); > + cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits); > break; > } > > @@ -723,7 +790,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, > case BITS_STOP_1_5: > dev_dbg(dev, "%s - stop bits = 1.5 (not supported, using 1 stop bit)\n", __func__); > bits &= ~BITS_STOP_MASK; > - cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); > + cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits); > break; > case BITS_STOP_2: > dev_dbg(dev, "%s - stop bits = 2\n", __func__); > @@ -732,7 +799,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, > default: > dev_dbg(dev, "%s - Unknown number of stop bits, using 1 stop bit\n", __func__); > bits &= ~BITS_STOP_MASK; > - cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); > + cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits); > break; > } > > @@ -806,7 +873,7 @@ static void cp210x_set_termios(struct tty_struct *tty, > { > struct device *dev = &port->dev; > unsigned int cflag, old_cflag; > - unsigned int bits; > + u16 bits; > unsigned int modem_ctl[4]; > > cflag = tty->termios.c_cflag; > @@ -845,7 +912,7 @@ static void cp210x_set_termios(struct tty_struct *tty, > bits |= BITS_DATA_8; > break; > } > - if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) > + if (cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits)) > dev_dbg(dev, "Number of data bits requested not supported by device\n"); > } > > @@ -872,7 +939,7 @@ static void cp210x_set_termios(struct tty_struct *tty, > } > } > } > - if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) > + if (cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits)) > dev_dbg(dev, "Parity mode not supported by device\n"); > } > > @@ -886,7 +953,7 @@ static void cp210x_set_termios(struct tty_struct *tty, > bits |= BITS_STOP_1; > dev_dbg(dev, "%s - stop bits = 1\n", __func__); > } > - if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) > + if (cp210x_write_u16_reg(port, CP210X_SET_LINE_CTL, bits)) > dev_dbg(dev, "Number of stop bits requested not supported by device\n"); > } > > @@ -926,7 +993,7 @@ static int cp210x_tiocmset(struct tty_struct *tty, > static int cp210x_tiocmset_port(struct usb_serial_port *port, > unsigned int set, unsigned int clear) > { > - unsigned int control = 0; > + u16 control = 0; > > if (set & TIOCM_RTS) { > control |= CONTROL_RTS; > @@ -947,7 +1014,7 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, > > dev_dbg(&port->dev, "%s - control = 0x%.4x\n", __func__, control); > > - return cp210x_set_config(port, CP210X_SET_MHS, &control, 2); > + return cp210x_write_u16_reg(port, CP210X_SET_MHS, control); > } > > static void cp210x_dtr_rts(struct usb_serial_port *p, int on) > @@ -981,7 +1048,7 @@ static int cp210x_tiocmget(struct tty_struct *tty) > static void cp210x_break_ctl(struct tty_struct *tty, int break_state) > { > struct usb_serial_port *port = tty->driver_data; > - unsigned int state; > + u16 state; > > if (break_state == 0) > state = BREAK_OFF; > @@ -989,7 +1056,7 @@ static void cp210x_break_ctl(struct tty_struct *tty, int break_state) > state = BREAK_ON; > dev_dbg(&port->dev, "%s - turning break %s\n", __func__, > state == BREAK_OFF ? "off" : "on"); > - cp210x_set_config(port, CP210X_SET_BREAK, &state, 2); > + cp210x_write_u16_reg(port, CP210X_SET_BREAK, state); > } > > static int cp210x_port_probe(struct usb_serial_port *port) >