diff options
| author | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
|---|---|---|
| committer | Dmitry Torokhov <[email protected]> | 2023-08-30 16:06:38 -0700 | 
| commit | 1ac731c529cd4d6adbce134754b51ff7d822b145 (patch) | |
| tree | 143ab3f35ca5f3b69f583c84e6964b17139c2ec1 /drivers/tty/serial/serial_core.c | |
| parent | 07b4c950f27bef0362dc6ad7ee713aab61d58149 (diff) | |
| parent | 54116d442e001e1b6bd482122043b1870998a1f3 (diff) | |
Merge branch 'next' into for-linus
Prepare input updates for 6.6 merge window.
Diffstat (limited to 'drivers/tty/serial/serial_core.c')
| -rw-r--r-- | drivers/tty/serial/serial_core.c | 125 | 
1 files changed, 64 insertions, 61 deletions
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 2bd32c8ece39..54e82f476a2c 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -15,6 +15,7 @@  #include <linux/init.h>  #include <linux/console.h>  #include <linux/gpio/consumer.h> +#include <linux/kernel.h>  #include <linux/of.h>  #include <linux/proc_fs.h>  #include <linux/seq_file.h> @@ -48,9 +49,6 @@ static struct lock_class_key port_lock_key;   */  #define RS485_MAX_RTS_DELAY	100 /* msecs */ -static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, -			      const struct ktermios *old_termios); -static void uart_wait_until_sent(struct tty_struct *tty, int timeout);  static void uart_change_pm(struct uart_state *state,  			   enum uart_pm_state pm_state); @@ -137,7 +135,7 @@ static void __uart_start(struct tty_struct *tty)  	struct uart_state *state = tty->driver_data;  	struct uart_port *port = state->uart_port; -	if (port && !uart_tx_stopped(port)) +	if (port && !(port->flags & UPF_DEAD) && !uart_tx_stopped(port))  		port->ops->start_tx(port);  } @@ -177,6 +175,51 @@ static void uart_port_dtr_rts(struct uart_port *uport, bool active)  		uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);  } +/* Caller holds port mutex */ +static void uart_change_line_settings(struct tty_struct *tty, struct uart_state *state, +				      const struct ktermios *old_termios) +{ +	struct uart_port *uport = uart_port_check(state); +	struct ktermios *termios; +	bool old_hw_stopped; + +	/* +	 * If we have no tty, termios, or the port does not exist, +	 * then we can't set the parameters for this port. +	 */ +	if (!tty || uport->type == PORT_UNKNOWN) +		return; + +	termios = &tty->termios; +	uport->ops->set_termios(uport, termios, old_termios); + +	/* +	 * Set modem status enables based on termios cflag +	 */ +	spin_lock_irq(&uport->lock); +	if (termios->c_cflag & CRTSCTS) +		uport->status |= UPSTAT_CTS_ENABLE; +	else +		uport->status &= ~UPSTAT_CTS_ENABLE; + +	if (termios->c_cflag & CLOCAL) +		uport->status &= ~UPSTAT_DCD_ENABLE; +	else +		uport->status |= UPSTAT_DCD_ENABLE; + +	/* reset sw-assisted CTS flow control based on (possibly) new mode */ +	old_hw_stopped = uport->hw_stopped; +	uport->hw_stopped = uart_softcts_mode(uport) && +			    !(uport->ops->get_mctrl(uport) & TIOCM_CTS); +	if (uport->hw_stopped != old_hw_stopped) { +		if (!old_hw_stopped) +			uport->ops->stop_tx(uport); +		else +			__uart_start(tty); +	} +	spin_unlock_irq(&uport->lock); +} +  /*   * Startup the port.  This will be called once per open.  All calls   * will be serialised by the per-port mutex. @@ -232,7 +275,7 @@ static int uart_port_startup(struct tty_struct *tty, struct uart_state *state,  		/*  		 * Initialise the hardware port settings.  		 */ -		uart_change_speed(tty, state, NULL); +		uart_change_line_settings(tty, state, NULL);  		/*  		 * Setup the RTS and DTR signals once the @@ -485,52 +528,6 @@ uart_get_divisor(struct uart_port *port, unsigned int baud)  }  EXPORT_SYMBOL(uart_get_divisor); -/* Caller holds port mutex */ -static void uart_change_speed(struct tty_struct *tty, struct uart_state *state, -			      const struct ktermios *old_termios) -{ -	struct uart_port *uport = uart_port_check(state); -	struct ktermios *termios; -	int hw_stopped; - -	/* -	 * If we have no tty, termios, or the port does not exist, -	 * then we can't set the parameters for this port. -	 */ -	if (!tty || uport->type == PORT_UNKNOWN) -		return; - -	termios = &tty->termios; -	uport->ops->set_termios(uport, termios, old_termios); - -	/* -	 * Set modem status enables based on termios cflag -	 */ -	spin_lock_irq(&uport->lock); -	if (termios->c_cflag & CRTSCTS) -		uport->status |= UPSTAT_CTS_ENABLE; -	else -		uport->status &= ~UPSTAT_CTS_ENABLE; - -	if (termios->c_cflag & CLOCAL) -		uport->status &= ~UPSTAT_DCD_ENABLE; -	else -		uport->status |= UPSTAT_DCD_ENABLE; - -	/* reset sw-assisted CTS flow control based on (possibly) new mode */ -	hw_stopped = uport->hw_stopped; -	uport->hw_stopped = uart_softcts_mode(uport) && -				!(uport->ops->get_mctrl(uport) & TIOCM_CTS); -	if (uport->hw_stopped) { -		if (!hw_stopped) -			uport->ops->stop_tx(uport); -	} else { -		if (hw_stopped) -			__uart_start(tty); -	} -	spin_unlock_irq(&uport->lock); -} -  static int uart_put_char(struct tty_struct *tty, unsigned char c)  {  	struct uart_state *state = tty->driver_data; @@ -994,7 +991,7 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,  				      current->comm,  				      tty_name(port->tty));  			} -			uart_change_speed(tty, state, NULL); +			uart_change_line_settings(tty, state, NULL);  		}  	} else {  		retval = uart_startup(tty, state, true); @@ -1491,7 +1488,7 @@ static int uart_set_iso7816_config(struct uart_port *port,  	 * There are 5 words reserved for future use. Check that userspace  	 * doesn't put stuff in there to prevent breakages in the future.  	 */ -	for (i = 0; i < 5; i++) +	for (i = 0; i < ARRAY_SIZE(iso7816.reserved); i++)  		if (iso7816.reserved[i])  			return -EINVAL; @@ -1552,7 +1549,7 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)  		goto out;  	/* rs485_config requires more locking than others */ -	if (cmd == TIOCGRS485) +	if (cmd == TIOCSRS485)  		down_write(&tty->termios_rwsem);  	mutex_lock(&port->mutex); @@ -1595,7 +1592,7 @@ uart_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)  	}  out_up:  	mutex_unlock(&port->mutex); -	if (cmd == TIOCGRS485) +	if (cmd == TIOCSRS485)  		up_write(&tty->termios_rwsem);  out:  	return ret; @@ -1656,15 +1653,15 @@ static void uart_set_termios(struct tty_struct *tty,  		goto out;  	} -	uart_change_speed(tty, state, old_termios); +	uart_change_line_settings(tty, state, old_termios);  	/* reload cflag from termios; port driver may have overridden flags */  	cflag = tty->termios.c_cflag;  	/* Handle transition to B0 status */ -	if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) +	if (((old_termios->c_cflag & CBAUD) != B0) && ((cflag & CBAUD) == B0))  		uart_clear_mctrl(uport, TIOCM_RTS | TIOCM_DTR);  	/* Handle transition away from B0 status */ -	else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { +	else if (((old_termios->c_cflag & CBAUD) == B0) && ((cflag & CBAUD) != B0)) {  		unsigned int mask = TIOCM_DTR;  		if (!(cflag & CRTSCTS) || !tty_throttled(tty)) @@ -2452,7 +2449,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)  			ret = ops->startup(uport);  			if (ret == 0) {  				if (tty) -					uart_change_speed(tty, state, NULL); +					uart_change_line_settings(tty, state, NULL);  				spin_lock_irq(&uport->lock);  				if (!(uport->rs485.flags & SER_RS485_ENABLED))  					ops->set_mctrl(uport, uport->mctrl); @@ -2593,6 +2590,7 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)  {  	struct uart_driver *drv = driver->driver_state;  	struct uart_state *state = drv->state + line; +	enum uart_pm_state pm_state;  	struct tty_port *tport;  	struct uart_port *port;  	int baud = 9600; @@ -2610,6 +2608,9 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)  		goto out;  	} +	pm_state = state->pm_state; +	uart_change_pm(state, UART_PM_STATE_ON); +  	if (port->ops->poll_init) {  		/*  		 * We don't set initialized as we only initialized the hw, @@ -2626,6 +2627,8 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)  		console_list_unlock();  	}  out: +	if (ret) +		uart_change_pm(state, pm_state);  	mutex_unlock(&tport->mutex);  	return ret;  } @@ -3305,13 +3308,13 @@ void uart_handle_cts_change(struct uart_port *uport, bool active)  	if (uart_softcts_mode(uport)) {  		if (uport->hw_stopped) {  			if (active) { -				uport->hw_stopped = 0; +				uport->hw_stopped = false;  				uport->ops->start_tx(uport);  				uart_write_wakeup(uport);  			}  		} else {  			if (!active) { -				uport->hw_stopped = 1; +				uport->hw_stopped = true;  				uport->ops->stop_tx(uport);  			}  		}  |