Implement break control for F81232/F81534
Subsystems (2)
cover Implement break control for F81232/F81534
The following 2 patches makes break control available for Fintek F81232/F81534.
Ji-Ze Hong (Peter Hong) (2):
usb:serial: Implement Fintek F81232 break on/off usb:serial: Implement Fintek f81534 break on/off
drivers/usb/serial/f81232.c | 40 ++++++++++++++++++++++++++++++++++------ drivers/usb/serial/f81534.c | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 6 deletions(-)
Signature · 1 line
1.9.1
PATCH 1/2 usb:serial: Implement Fintek F81232 break on/off
Implement Fintek F81232 break on/off with LCR register, it's the same with 16550A LCR register layout.
--- drivers/usb/serial/f81232.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-)
drivers/usb/serial/f81232.c +34 -6
@@ -131,6 +131,21 @@ static int f81232_set_register(struct usb_serial_port *port, u16 reg, u8 val)return status; } +static int f81232_set_mask_register (struct usb_serial_port *port,u16 reg, +u8 mask,u8 val) +{ +int status; +u8 tmp; + + status =f81232_get_register (port, reg, &tmp); +if (status) +return status; + + tmp = (tmp & ~mask) | (val & mask); + +return f81232_set_register (port, reg, tmp); +} +static void f81232_read_msr (struct usb_serial_port *port) {int status;
@@ -335,15 +350,27 @@ static void f81232_process_read_urb(struct urb *urb)tty_flip_buffer_push (&port->port); } +static void f81232_set_break (struct usb_serial_port *port,bool enable) +{ +int status; +u8 tmp =0 ; + +if (enable) + tmp =UART_LCR_SBC ; + + status =f81232_set_mask_register (port,LINE_CONTROL_REGISTER , +UART_LCR_SBC , tmp); +if (status) { +dev_err (&port->dev,"%s: set break failed: %x\n" , __func__, + status); + } +} +static void f81232_break_ctl (struct tty_struct *tty,int break_state) { -/* FIXME - Stubbed out for now */ +struct usb_serial_port *port = tty->driver_data; -/* -* break_state = -1 to turn on break, and 0 to turn off break -* see drivers/char/tty_io.c to see it used. -* last_set_data_urb_value NEVER has the break bit set in it. -*/ +f81232_set_break (port, break_state); }static void f81232_set_baudrate (struct usb_serial_port *port,speed_t baudrate)
@@ -563,6 +590,7 @@ static void f81232_close(struct usb_serial_port *port)f81232_port_disable (port);usb_serial_generic_close (port);usb_kill_urb (port->interrupt_in_urb); +f81232_set_break (port, false); }static void f81232_dtr_rts (struct usb_serial_port *port,int on)
Signature · 1 line
1.9.1
Johan Hovold
maintainerRe: [PATCH V1 1/2] usb:serial: Implement Fintek F81232 break on/off
Quoted 40 lines · Ji-Ze Hong (Peter Hong)
Implement Fintek F81232 break on/off with LCR register, it's the same with 16550A LCR register layout.
Signed-off-by Ji-Ze Hong (Peter Hong) <[email protected]>--- drivers/usb/serial/f81232.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-)drivers/usb/serial/f81232.c +17
-0@@ -131,6 +131,21 @@ static int f81232_set_register(struct usb_serial_port *port, u16 reg, u8 val)return status; } +static int f81232_set_mask_register (struct usb_serial_port *port,u16 reg, +u8 mask,u8 val) +{ +int status; +u8 tmp; + + status =f81232_get_register (port, reg, &tmp); +if (status) +return status; + + tmp = (tmp & ~mask) | (val & mask); + +return f81232_set_register (port, reg, tmp); +} +static void f81232_read_msr (struct usb_serial_port *port) {int status;@@ -335,15 +350,27 @@ static void f81232_process_read_urb(struct urb *urb)tty_flip_buffer_push (&port->port); } +static void f81232_set_break (struct usb_serial_port *port,bool enable) +{
drivers/usb/serial/f81232.c static void f81232_process_read_urb(struct urb *urb) · line 364
Quoted 10 lines
drivers/usb/serial/f81232.c +10
-0+int status; +u8 tmp =0 ; + +if (enable) + tmp =UART_LCR_SBC ; + + status =f81232_set_mask_register (port,LINE_CONTROL_REGISTER , +UART_LCR_SBC , tmp); +if (status) { + dev_err(&port->dev, "%s: set break failed: %x\n", __func__,
You want %d here.
And you can drop the __func__ prefix.
drivers/usb/serial/f81232.c static void f81232_process_read_urb(struct urb *urb) · line 366
Quoted 2 lines
drivers/usb/serial/f81232.c +2
-0+ status); + }
You should also coordinate this with the LCR update in set_termios, otherwise changing line settings would clear break etc.
Quoted 17 lines
drivers/usb/serial/f81232.c +4
-6+} +static void f81232_break_ctl (struct tty_struct *tty,int break_state) { -/* FIXME - Stubbed out for now */ +struct usb_serial_port *port = tty->driver_data; -/* -* break_state = -1 to turn on break, and 0 to turn off break -* see drivers/char/tty_io.c to see it used. -* last_set_data_urb_value NEVER has the break bit set in it. -*/ +f81232_set_break (port, break_state); }static void f81232_set_baudrate (struct usb_serial_port *port,speed_t baudrate)
drivers/usb/serial/f81232.c static void f81232_close(struct usb_serial_port *port) · line 593
Quoted 4 lines
drivers/usb/serial/f81232.c +1
-0@@ -563,6 +590,7 @@ static void f81232_close(struct usb_serial_port *port)f81232_port_disable (port);usb_serial_generic_close (port);usb_kill_urb (port->interrupt_in_urb); +f81232_set_break (port, false);
I don't think this is needed, and then you can fold set_break into break_ctl above as well.
drivers/usb/serial/f81232.c static void f81232_close(struct usb_serial_port *port) · line 596
Quoted 3 lines
drivers/usb/serial/f81232.c +0
-0}static void f81232_dtr_rts (struct usb_serial_port *port,int on)
Thanks,
Johan
PATCH 2/2 usb:serial: Implement Fintek f81534 break on/off
In reply to Ji-Ze Hong (Peter Hong)Implement Fintek f81534 break on/off with LCR register It's the same with 16550A LCR register layout
We'll add a shadow LCR variable to save the final LCR we had set due to the "read ep0" operations maybe slow down all the serial ports performance.
--- drivers/usb/serial/f81534.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
drivers/usb/serial/f81534.c +40 -0
@@ -126,8 +126,10 @@ struct f81534_serial_private {struct f81534_port_private {struct mutex mcr_mutex; +struct mutex lcr_mutex;unsigned long tx_empty;spinlock_t msr_lock; +u8 shadow_lcr;u8 shadow_mcr;u8 shadow_msr;u8 phy_num;
@@ -683,6 +685,7 @@ static void f81534_set_termios(struct tty_struct *tty,struct usb_serial_port *port, struct ktermios *old_termios) { + struct f81534_port_private *port_priv = usb_get_serial_port_data(port);u8 new_lcr =0 ;int status;u32 baud;
@@ -721,6 +724,10 @@ static void f81534_set_termios(struct tty_struct *tty,break ; } +mutex_lock (&port_priv->lcr_mutex); + port_priv->shadow_lcr = new_lcr; +mutex_unlock (&port_priv->lcr_mutex); + baud =tty_get_baud_rate (tty);if (!baud)return ;
@@ -812,6 +819,35 @@ static int f81534_read_msr(struct usb_serial_port *port)return 0 ; } +static void f81534_set_break (struct usb_serial_port *port,bool enable) +{ +struct f81534_port_private *port_priv =usb_get_serial_port_data (port); +int status; + +mutex_lock (&port_priv->lcr_mutex); + +if (enable) + port_priv->shadow_lcr |=UART_LCR_SBC ; +else + port_priv->shadow_lcr &= ~UART_LCR_SBC ; + + status =f81534_set_port_register (port,F81534_LINE_CONTROL_REG , + port_priv->shadow_lcr); +if (status) { +dev_err (&port->dev,"%s: set break failed: %x\n" , __func__, + status); + } + +mutex_unlock (&port_priv->lcr_mutex); +} + +static void f81534_break_ctl (struct tty_struct *tty,int break_state) +{ +struct usb_serial_port *port = tty->driver_data; + +f81534_set_break (port, break_state); +} +static int f81534_open (struct tty_struct *tty,struct usb_serial_port *port) { struct f81534_serial_private *serial_priv =
@@ -877,6 +913,8 @@ static void f81534_close(struct usb_serial_port *port) }mutex_unlock (&serial_priv->urb_mutex); + +f81534_set_break (port, false); } static int f81534_get_serial_info(struct usb_serial_port *port,
@@ -1244,6 +1282,7 @@ static int f81534_port_probe(struct usb_serial_port *port)spin_lock_init (&port_priv->msr_lock);mutex_init (&port_priv->mcr_mutex); +mutex_init (&port_priv->lcr_mutex);/* Assign logic-to-phy mapping */ port_priv->phy_num =f81534_logic_to_phy_port (port->serial, port);
@@ -1389,6 +1428,7 @@ static int f81534_resume(struct usb_serial *serial) .dtr_rts = f81534_dtr_rts, .process_read_urb = f81534_process_read_urb, .ioctl = f81534_ioctl, + .break_ctl = f81534_break_ctl, .tiocmget = f81534_tiocmget, .tiocmset = f81534_tiocmset, .write_bulk_callback = f81534_write_usb_callback,
Signature · 1 line
1.9.1
Johan Hovold
maintainerRe: [PATCH V1 2/2] usb:serial: Implement Fintek f81534 break on/off
Quoted 17 lines · Ji-Ze Hong (Peter Hong)
Implement Fintek f81534 break on/off with LCR register It's the same with 16550A LCR register layout
We'll add a shadow LCR variable to save the final LCR we had set due to the "read ep0" operations maybe slow down all the serial ports performance.
Signed-off-by Ji-Ze Hong (Peter Hong) <[email protected]>--- drivers/usb/serial/f81534.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)drivers/usb/serial/f81534.c +0
-0
drivers/usb/serial/f81534.c struct f81534_serial_private { · line 129
Quoted 4 lines
drivers/usb/serial/f81534.c +1
-0@@ -126,8 +126,10 @@ struct f81534_serial_private {struct f81534_port_private {struct mutex mcr_mutex; +struct mutex lcr_mutex;
Using a single mutex is preferred.
Quoted 15 lines
drivers/usb/serial/f81534.c +2
-0unsigned long tx_empty;spinlock_t msr_lock; +u8 shadow_lcr;u8 shadow_mcr;u8 shadow_msr;u8 phy_num;@@ -683,6 +685,7 @@ static void f81534_set_termios(struct tty_struct *tty,struct usb_serial_port *port, struct ktermios *old_termios) { + struct f81534_port_private *port_priv = usb_get_serial_port_data(port);u8 new_lcr =0 ;int status;u32 baud;
drivers/usb/serial/f81534.c static void f81534_set_termios(struct tty_struct *tty, · line 729
Quoted 6 lines
drivers/usb/serial/f81534.c +3
-0@@ -721,6 +724,10 @@ static void f81534_set_termios(struct tty_struct *tty,break ; } +mutex_lock (&port_priv->lcr_mutex); + port_priv->shadow_lcr = new_lcr; +mutex_unlock (&port_priv->lcr_mutex);
And this is not sufficient to prevent races with break_ctl. Hold the mutex while updating LCR in set_port_config at least (and honour the break state).
Quoted 15 lines
drivers/usb/serial/f81534.c +8
-0+ baud =tty_get_baud_rate (tty);if (!baud)return ;@@ -812,6 +819,35 @@ static int f81534_read_msr(struct usb_serial_port *port)return 0 ; } +static void f81534_set_break (struct usb_serial_port *port,bool enable) +{ +struct f81534_port_private *port_priv =usb_get_serial_port_data (port); +int status; + +mutex_lock (&port_priv->lcr_mutex); +
drivers/usb/serial/f81534.c static int f81534_read_msr(struct usb_serial_port *port) · line 838
Quoted 10 lines
drivers/usb/serial/f81534.c +10
-0+if (enable) + port_priv->shadow_lcr |=UART_LCR_SBC ; +else + port_priv->shadow_lcr &= ~UART_LCR_SBC ; + + status =f81534_set_port_register (port,F81534_LINE_CONTROL_REG , + port_priv->shadow_lcr); +if (status) { +dev_err (&port->dev,"%s: set break failed: %x\n" , __func__, + status);
%d, __func__ not needed.
Quoted 16 lines
drivers/usb/serial/f81534.c +12
-0+ } + +mutex_unlock (&port_priv->lcr_mutex); +} + +static void f81534_break_ctl (struct tty_struct *tty,int break_state) +{ +struct usb_serial_port *port = tty->driver_data; + +f81534_set_break (port, break_state); +} +static int f81534_open (struct tty_struct *tty,struct usb_serial_port *port) { struct f81534_serial_private *serial_priv =
drivers/usb/serial/f81534.c static void f81534_close(struct usb_serial_port *port) · line 917
Quoted 5 lines
drivers/usb/serial/f81534.c +2
-0@@ -877,6 +913,8 @@ static void f81534_close(struct usb_serial_port *port) }mutex_unlock (&serial_priv->urb_mutex); + +f81534_set_break (port, false);
Drop this too, and fold set_break into break_ctl above.
Quoted 12 lines
drivers/usb/serial/f81534.c +1
-0} static int f81534_get_serial_info(struct usb_serial_port *port,@@ -1244,6 +1282,7 @@ static int f81534_port_probe(struct usb_serial_port *port)spin_lock_init (&port_priv->msr_lock);mutex_init (&port_priv->mcr_mutex); +mutex_init (&port_priv->lcr_mutex);/* Assign logic-to-phy mapping */ port_priv->phy_num =f81534_logic_to_phy_port (port->serial, port);
drivers/usb/serial/f81534.c static int f81534_resume(struct usb_serial *serial) · line 1434
Quoted 7 lines
drivers/usb/serial/f81534.c +1
-0@@ -1389,6 +1428,7 @@ static int f81534_resume(struct usb_serial *serial) .dtr_rts = f81534_dtr_rts, .process_read_urb = f81534_process_read_urb, .ioctl = f81534_ioctl, + .break_ctl = f81534_break_ctl, .tiocmget = f81534_tiocmget, .tiocmset = f81534_tiocmset, .write_bulk_callback = f81534_write_usb_callback,
Thanks,
Johan