diff options
Diffstat (limited to 'drivers/tty')
64 files changed, 2230 insertions, 1652 deletions
| diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig index a312cb33a99b..2dff93d7a501 100644 --- a/drivers/tty/Kconfig +++ b/drivers/tty/Kconfig @@ -137,7 +137,6 @@ config LEGACY_PTYS  	  security.  This option enables these legacy devices; on most  	  systems, it is safe to say N. -  config LEGACY_PTY_COUNT  	int "Maximum number of legacy PTY in use"  	depends on LEGACY_PTYS @@ -151,6 +150,31 @@ config LEGACY_PTY_COUNT  	  When not in use, each legacy PTY occupies 12 bytes on 32-bit  	  architectures and 24 bytes on 64-bit architectures. +config LDISC_AUTOLOAD +	bool "Automatically load TTY Line Disciplines" +	default y +	help +	  Historically the kernel has always automatically loaded any +	  line discipline that is in a kernel module when a user asks +	  for it to be loaded with the TIOCSETD ioctl, or through other +	  means.  This is not always the best thing to do on systems +	  where you know you will not be using some of the more +	  "ancient" line disciplines, so prevent the kernel from doing +	  this unless the request is coming from a process with the +	  CAP_SYS_MODULE permissions. + +	  Say 'Y' here if you trust your userspace users to do the right +	  thing, or if you have only provided the line disciplines that +	  you know you will be using, or if you wish to continue to use +	  the traditional method of on-demand loading of these modules +	  by any user. + +	  This functionality can be changed at runtime with the +	  dev.tty.ldisc_autoload sysctl, this configuration option will +	  only set the default value of this functionality. + +source "drivers/tty/serial/Kconfig" +  config SERIAL_NONSTANDARD  	bool "Non-standard serial port support"  	depends on HAS_IOMEM @@ -270,16 +294,6 @@ config SYNCLINK_GT  	  synchronous and asynchronous serial adapters  	  manufactured by Microgate Systems, Ltd. (www.microgate.com) -config NOZOMI -	tristate "HSDPA Broadband Wireless Data Card - Globe Trotter" -	depends on PCI -	help -	  If you have a HSDPA driver Broadband Wireless Data Card - -	  Globe Trotter PCMCIA card, say Y here. - -	  To compile this driver as a module, choose M here, the module -	  will be called nozomi. -  config ISI  	tristate "Multi-Tech multiport card support"  	depends on SERIAL_NONSTANDARD && PCI @@ -302,43 +316,6 @@ config N_HDLC  	  The module will be called n_hdlc. If you want to do that, say M  	  here. -config N_GSM -	tristate "GSM MUX line discipline support (EXPERIMENTAL)" -	depends on NET -	help -	  This line discipline provides support for the GSM MUX protocol and -	  presents the mux as a set of 61 individual tty devices. - -config TRACE_ROUTER -	tristate "Trace data router for MIPI P1149.7 cJTAG standard" -	depends on TRACE_SINK -	help -	  The trace router uses the Linux tty line discipline framework to -	  route trace data coming from a tty port (say UART for example) to -	  the trace sink line discipline driver and to another tty port (say -	  USB). This is part of a solution for the MIPI P1149.7, compact JTAG, -	  standard, which is for debugging mobile devices. The PTI driver in -	  drivers/misc/pti.c defines the majority of this MIPI solution. - -	  You should select this driver if the target kernel is meant for -	  a mobile device containing a modem.  Then you will need to select -	  "Trace data sink for MIPI P1149.7 cJTAG standard" line discipline -	  driver. - -config TRACE_SINK -	tristate "Trace data sink for MIPI P1149.7 cJTAG standard" -	help -	  The trace sink uses the Linux line discipline framework to receive -	  trace data coming from the trace router line discipline driver -	  to a user-defined tty port target, like USB. -	  This is to provide a way to extract modem trace data on -	  devices that do not have a PTI HW module, or just need modem -	  trace data to come out of a different HW output port. -	  This is part of a solution for the P1149.7, compact JTAG, standard. - -	  If you select this option, you need to select -	  "Trace data router for MIPI P1149.7 cJTAG standard". -  config PPC_EPAPR_HV_BYTECHAN  	bool "ePAPR hypervisor byte channel driver"  	depends on PPC @@ -374,20 +351,6 @@ config PPC_EARLY_DEBUG_EHV_BC_HANDLE  	  there simply will be no early console output.  This is true also  	  if you don't boot under a hypervisor at all. -config NULL_TTY -	tristate "NULL TTY driver" -	help -	  Say Y here if you want a NULL TTY which simply discards messages. - -	  This is useful to allow userspace applications which expect a console -	  device to work without modifications even when no console is -	  available or desired. - -	  In order to use this driver, you should redirect the console to this -	  TTY, or boot the kernel with console=ttynull. - -	  If unsure, say N. -  config GOLDFISH_TTY  	tristate "Goldfish TTY Driver"  	depends on GOLDFISH @@ -401,6 +364,23 @@ config GOLDFISH_TTY_EARLY_CONSOLE  	default y if GOLDFISH_TTY=y  	select SERIAL_EARLYCON +config N_GSM +	tristate "GSM MUX line discipline support (EXPERIMENTAL)" +	depends on NET +	help +	  This line discipline provides support for the GSM MUX protocol and +	  presents the mux as a set of 61 individual tty devices. + +config NOZOMI +	tristate "HSDPA Broadband Wireless Data Card - Globe Trotter" +	depends on PCI +	help +	  If you have a HSDPA driver Broadband Wireless Data Card - +	  Globe Trotter PCMCIA card, say Y here. + +	  To compile this driver as a module, choose M here, the module +	  will be called nozomi. +  config MIPS_EJTAG_FDC_TTY  	bool "MIPS EJTAG Fast Debug Channel TTY"  	depends on MIPS_CDMM @@ -448,33 +428,58 @@ config MIPS_EJTAG_FDC_KGDB_CHAN  	help  	  FDC channel number to use for KGDB. +config NULL_TTY +	tristate "NULL TTY driver" +	help +	  Say Y here if you want a NULL TTY which simply discards messages. + +	  This is useful to allow userspace applications which expect a console +	  device to work without modifications even when no console is +	  available or desired. + +	  In order to use this driver, you should redirect the console to this +	  TTY, or boot the kernel with console=ttynull. + +	  If unsure, say N. + +config TRACE_ROUTER +	tristate "Trace data router for MIPI P1149.7 cJTAG standard" +	depends on TRACE_SINK +	help +	  The trace router uses the Linux tty line discipline framework to +	  route trace data coming from a tty port (say UART for example) to +	  the trace sink line discipline driver and to another tty port (say +	  USB). This is part of a solution for the MIPI P1149.7, compact JTAG, +	  standard, which is for debugging mobile devices. The PTI driver in +	  drivers/misc/pti.c defines the majority of this MIPI solution. + +	  You should select this driver if the target kernel is meant for +	  a mobile device containing a modem.  Then you will need to select +	  "Trace data sink for MIPI P1149.7 cJTAG standard" line discipline +	  driver. + +config TRACE_SINK +	tristate "Trace data sink for MIPI P1149.7 cJTAG standard" +	help +	  The trace sink uses the Linux line discipline framework to receive +	  trace data coming from the trace router line discipline driver +	  to a user-defined tty port target, like USB. +	  This is to provide a way to extract modem trace data on +	  devices that do not have a PTI HW module, or just need modem +	  trace data to come out of a different HW output port. +	  This is part of a solution for the P1149.7, compact JTAG, standard. + +	  If you select this option, you need to select +	  "Trace data router for MIPI P1149.7 cJTAG standard". +  config VCC  	tristate "Sun Virtual Console Concentrator"  	depends on SUN_LDOMS  	help  	  Support for Sun logical domain consoles. -config LDISC_AUTOLOAD -	bool "Automatically load TTY Line Disciplines" -	default y -	help -	  Historically the kernel has always automatically loaded any -	  line discipline that is in a kernel module when a user asks -	  for it to be loaded with the TIOCSETD ioctl, or through other -	  means.  This is not always the best thing to do on systems -	  where you know you will not be using some of the more -	  "ancient" line disciplines, so prevent the kernel from doing -	  this unless the request is coming from a process with the -	  CAP_SYS_MODULE permissions. - -	  Say 'Y' here if you trust your userspace users to do the right -	  thing, or if you have only provided the line disciplines that -	  you know you will be using, or if you wish to continue to use -	  the traditional method of on-demand loading of these modules -	  by any user. - -	  This functionality can be changed at runtime with the -	  dev.tty.ldisc_autoload sysctl, this configuration option will -	  only set the default value of this functionality. +source "drivers/tty/hvc/Kconfig"  endif # TTY + +source "drivers/tty/serdev/Kconfig" diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c index 769e0a5d1dfc..3c6dd06ec5fb 100644 --- a/drivers/tty/ehv_bytechan.c +++ b/drivers/tty/ehv_bytechan.c @@ -136,6 +136,21 @@ static int find_console_handle(void)  	return 1;  } +static unsigned int local_ev_byte_channel_send(unsigned int handle, +					       unsigned int *count, +					       const char *p) +{ +	char buffer[EV_BYTE_CHANNEL_MAX_BYTES]; +	unsigned int c = *count; + +	if (c < sizeof(buffer)) { +		memcpy(buffer, p, c); +		memset(&buffer[c], 0, sizeof(buffer) - c); +		p = buffer; +	} +	return ev_byte_channel_send(handle, count, p); +} +  /*************************** EARLY CONSOLE DRIVER ***************************/  #ifdef CONFIG_PPC_EARLY_DEBUG_EHV_BC @@ -154,7 +169,7 @@ static void byte_channel_spin_send(const char data)  	do {  		count = 1; -		ret = ev_byte_channel_send(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE, +		ret = local_ev_byte_channel_send(CONFIG_PPC_EARLY_DEBUG_EHV_BC_HANDLE,  					   &count, &data);  	} while (ret == EV_EAGAIN);  } @@ -221,7 +236,7 @@ static int ehv_bc_console_byte_channel_send(unsigned int handle, const char *s,  	while (count) {  		len = min_t(unsigned int, count, EV_BYTE_CHANNEL_MAX_BYTES);  		do { -			ret = ev_byte_channel_send(handle, &len, s); +			ret = local_ev_byte_channel_send(handle, &len, s);  		} while (ret == EV_EAGAIN);  		count -= len;  		s += len; @@ -401,7 +416,7 @@ static void ehv_bc_tx_dequeue(struct ehv_bc_data *bc)  			    CIRC_CNT_TO_END(bc->head, bc->tail, BUF_SIZE),  			    EV_BYTE_CHANNEL_MAX_BYTES); -		ret = ev_byte_channel_send(bc->handle, &len, bc->buf + bc->tail); +		ret = local_ev_byte_channel_send(bc->handle, &len, bc->buf + bc->tail);  		/* 'len' is valid only if the return code is 0 or EV_EAGAIN */  		if (!ret || (ret == EV_EAGAIN)) diff --git a/drivers/tty/hvc/Kconfig b/drivers/tty/hvc/Kconfig index 6a3c97d345a0..d1b27b0522a3 100644 --- a/drivers/tty/hvc/Kconfig +++ b/drivers/tty/hvc/Kconfig @@ -1,5 +1,4 @@  # SPDX-License-Identifier: GPL-2.0 -if TTY  config HVC_DRIVER  	bool @@ -89,7 +88,7 @@ config HVC_DCC  config HVC_RISCV_SBI  	bool "RISC-V SBI console support" -	depends on RISCV_SBI +	depends on RISCV_SBI_V01  	select HVC_DRIVER  	help  	  This enables support for console output via RISC-V SBI calls, which @@ -113,5 +112,3 @@ config HVCS  	  will depend on arch specific APIs exported from hvcserver.ko  	  which will also be compiled when this driver is built as a  	  module. - -endif # TTY diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index 27284a2dcd2b..436cc51c92c3 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -302,10 +302,6 @@ int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops)  	vtermnos[index] = vtermno;  	cons_ops[index] = ops; -	/* reserve all indices up to and including this index */ -	if (last_hvc < index) -		last_hvc = index; -  	/* check if we need to re-register the kernel console */  	hvc_check_console(index); @@ -960,13 +956,22 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,  		    cons_ops[i] == hp->ops)  			break; -	/* no matching slot, just use a counter */ -	if (i >= MAX_NR_HVC_CONSOLES) -		i = ++last_hvc; +	if (i >= MAX_NR_HVC_CONSOLES) { + +		/* find 'empty' slot for console */ +		for (i = 0; i < MAX_NR_HVC_CONSOLES && vtermnos[i] != -1; i++) { +		} + +		/* no matching slot, just use a counter */ +		if (i == MAX_NR_HVC_CONSOLES) +			i = ++last_hvc + MAX_NR_HVC_CONSOLES; +	}  	hp->index = i; -	cons_ops[i] = ops; -	vtermnos[i] = vtermno; +	if (i < MAX_NR_HVC_CONSOLES) { +		cons_ops[i] = ops; +		vtermnos[i] = vtermno; +	}  	list_add_tail(&(hp->next), &hvc_structs);  	mutex_unlock(&hvc_structs_mutex); diff --git a/drivers/tty/hvc/hvc_console.h b/drivers/tty/hvc/hvc_console.h index e9319954c832..18d005814e4b 100644 --- a/drivers/tty/hvc/hvc_console.h +++ b/drivers/tty/hvc/hvc_console.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */  /*   * hvc_console.h   * Copyright (C) 2005 IBM Corporation diff --git a/drivers/tty/mips_ejtag_fdc.c b/drivers/tty/mips_ejtag_fdc.c index 620d8488b83e..21e76a2ec182 100644 --- a/drivers/tty/mips_ejtag_fdc.c +++ b/drivers/tty/mips_ejtag_fdc.c @@ -243,6 +243,7 @@ done:  		/* Fall back to a 3 byte encoding */  		word.bytes = 3;  		word.word &= 0x00ffffff; +		/* Fall through */  	case 3:  		/* 3 byte encoding */  		word.word |= 0x82000000; diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index f1c90fa2978e..d77ed82a4840 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -97,7 +97,19 @@ struct gsm_msg {  	u8 ctrl;		/* Control byte + flags */  	unsigned int len;	/* Length of data block (can be zero) */  	unsigned char *data;	/* Points into buffer but not at the start */ -	unsigned char buffer[0]; +	unsigned char buffer[]; +}; + +enum gsm_dlci_state { +	DLCI_CLOSED, +	DLCI_OPENING,		/* Sending SABM not seen UA */ +	DLCI_OPEN,		/* SABM/UA complete */ +	DLCI_CLOSING,		/* Sending DISC not seen UA/DM */ +}; + +enum gsm_dlci_mode { +	DLCI_MODE_ABM,		/* Normal Asynchronous Balanced Mode */ +	DLCI_MODE_ADM,		/* Asynchronous Disconnected Mode */  };  /* @@ -113,32 +125,25 @@ struct gsm_msg {  struct gsm_dlci {  	struct gsm_mux *gsm;  	int addr; -	int state; -#define DLCI_CLOSED		0 -#define DLCI_OPENING		1	/* Sending SABM not seen UA */ -#define DLCI_OPEN		2	/* SABM/UA complete */ -#define DLCI_CLOSING		3	/* Sending DISC not seen UA/DM */ +	enum gsm_dlci_state state;  	struct mutex mutex;  	/* Link layer */ -	int mode; -#define DLCI_MODE_ABM		0	/* Normal Asynchronous Balanced Mode */ -#define DLCI_MODE_ADM		1	/* Asynchronous Disconnected Mode */ +	enum gsm_dlci_mode mode;  	spinlock_t lock;	/* Protects the internal state */  	struct timer_list t1;	/* Retransmit timer for SABM and UA */  	int retries;  	/* Uplink tty if active */  	struct tty_port port;	/* The tty bound to this DLCI if there is one */ -	struct kfifo *fifo;	/* Queue fifo for the DLCI */ -	struct kfifo _fifo;	/* For new fifo API porting only */ +	struct kfifo fifo;	/* Queue fifo for the DLCI */  	int adaption;		/* Adaption layer in use */  	int prev_adaption;  	u32 modem_rx;		/* Our incoming virtual modem lines */  	u32 modem_tx;		/* Our outgoing modem lines */ -	int dead;		/* Refuse re-open */ +	bool dead;		/* Refuse re-open */  	/* Flow control */ -	int throttled;		/* Private copy of throttle state */ -	int constipated;	/* Throttle status for outgoing */ +	bool throttled;		/* Private copy of throttle state */ +	bool constipated;	/* Throttle status for outgoing */  	/* Packetised I/O */  	struct sk_buff *skb;	/* Frame being sent */  	struct sk_buff_head skb_list;	/* Queued frames */ @@ -168,6 +173,20 @@ struct gsm_control {  	int error;	/* Error if any */  }; +enum gsm_mux_state { +	GSM_SEARCH, +	GSM_START, +	GSM_ADDRESS, +	GSM_CONTROL, +	GSM_LEN, +	GSM_DATA, +	GSM_FCS, +	GSM_OVERRUN, +	GSM_LEN0, +	GSM_LEN1, +	GSM_SSOF, +}; +  /*   *	Each GSM mux we have is represented by this structure. If we are   *	operating as an ldisc then we use this structure as our ldisc @@ -192,22 +211,11 @@ struct gsm_mux {  	/* Framing Layer */  	unsigned char *buf; -	int state; -#define GSM_SEARCH		0 -#define GSM_START		1 -#define GSM_ADDRESS		2 -#define GSM_CONTROL		3 -#define GSM_LEN			4 -#define GSM_DATA		5 -#define GSM_FCS			6 -#define GSM_OVERRUN		7 -#define GSM_LEN0		8 -#define GSM_LEN1		9 -#define GSM_SSOF		10 +	enum gsm_mux_state state;  	unsigned int len;  	unsigned int address;  	unsigned int count; -	int escape; +	bool escape;  	int encoding;  	u8 control;  	u8 fcs; @@ -224,9 +232,9 @@ struct gsm_mux {  	unsigned int mru;  	unsigned int mtu;  	int initiator;			/* Did we initiate connection */ -	int dead;			/* Has the mux been shut down */ +	bool dead;			/* Has the mux been shut down */  	struct gsm_dlci *dlci[NUM_DLCI]; -	int constipated;		/* Asked by remote to shut up */ +	bool constipated;		/* Asked by remote to shut up */  	spinlock_t tx_lock;  	unsigned int tx_bytes;		/* TX data outstanding */ @@ -796,7 +804,7 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci)  	total_size = 0;  	while (1) { -		len = kfifo_len(dlci->fifo); +		len = kfifo_len(&dlci->fifo);  		if (len == 0)  			return total_size; @@ -820,7 +828,7 @@ static int gsm_dlci_data_output(struct gsm_mux *gsm, struct gsm_dlci *dlci)  			*dp++ = gsm_encode_modem(dlci);  			break;  		} -		WARN_ON(kfifo_out_locked(dlci->fifo, dp , len, &dlci->lock) != len); +		WARN_ON(kfifo_out_locked(&dlci->fifo, dp , len, &dlci->lock) != len);  		__gsm_data_queue(dlci, msg);  		total_size += size;  	} @@ -1034,9 +1042,9 @@ static void gsm_process_modem(struct tty_struct *tty, struct gsm_dlci *dlci,  	fc = (modem & MDM_FC) || !(modem & MDM_RTR);  	if (fc && !dlci->constipated) {  		/* Need to throttle our output on this device */ -		dlci->constipated = 1; +		dlci->constipated = true;  	} else if (!fc && dlci->constipated) { -		dlci->constipated = 0; +		dlci->constipated = false;  		gsm_dlci_data_kick(dlci);  	} @@ -1199,8 +1207,8 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,  		struct gsm_dlci *dlci = gsm->dlci[0];  		/* Modem wishes to close down */  		if (dlci) { -			dlci->dead = 1; -			gsm->dead = 1; +			dlci->dead = true; +			gsm->dead = true;  			gsm_dlci_begin_close(dlci);  		}  		} @@ -1211,7 +1219,7 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,  		break;  	case CMD_FCON:  		/* Modem can accept data again */ -		gsm->constipated = 0; +		gsm->constipated = false;  		gsm_control_reply(gsm, CMD_FCON, NULL, 0);  		/* Kick the link in case it is idling */  		spin_lock_irqsave(&gsm->tx_lock, flags); @@ -1220,7 +1228,7 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command,  		break;  	case CMD_FCOFF:  		/* Modem wants us to STFU */ -		gsm->constipated = 1; +		gsm->constipated = true;  		gsm_control_reply(gsm, CMD_FCOFF, NULL, 0);  		break;  	case CMD_MSC: @@ -1424,9 +1432,9 @@ static void gsm_dlci_close(struct gsm_dlci *dlci)  	dlci->state = DLCI_CLOSED;  	if (dlci->addr != 0) {  		tty_port_tty_hangup(&dlci->port, false); -		kfifo_reset(dlci->fifo); +		kfifo_reset(&dlci->fifo);  	} else -		dlci->gsm->dead = 1; +		dlci->gsm->dead = true;  	wake_up(&dlci->gsm->event);  	/* A DLCI 0 close is a MUX termination so we need to kick that  	   back to userspace somehow */ @@ -1496,6 +1504,9 @@ static void gsm_dlci_t1(struct timer_list *t)  		} else  			gsm_dlci_close(dlci);  		break; +	default: +		pr_debug("%s: unhandled state: %d\n", __func__, dlci->state); +		break;  	}  } @@ -1645,8 +1656,7 @@ static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *gsm, int addr)  		return NULL;  	spin_lock_init(&dlci->lock);  	mutex_init(&dlci->mutex); -	dlci->fifo = &dlci->_fifo; -	if (kfifo_alloc(&dlci->_fifo, 4096, GFP_KERNEL) < 0) { +	if (kfifo_alloc(&dlci->fifo, 4096, GFP_KERNEL) < 0) {  		kfree(dlci);  		return NULL;  	} @@ -1681,7 +1691,7 @@ static void gsm_dlci_free(struct tty_port *port)  	del_timer_sync(&dlci->t1);  	dlci->gsm->dlci[dlci->addr] = NULL; -	kfifo_free(dlci->fifo); +	kfifo_free(&dlci->fifo);  	while ((dlci->skb = skb_dequeue(&dlci->skb_list)))  		dev_kfree_skb(dlci->skb);  	kfree(dlci); @@ -1810,6 +1820,10 @@ static void gsm_queue(struct gsm_mux *gsm)  		case DLCI_OPENING:  			gsm_dlci_open(dlci);  			break; +		default: +			pr_debug("%s: unhandled state: %d\n", __func__, +					dlci->state); +			break;  		}  		break;  	case DM:	/* DM can be valid unsolicited */ @@ -1923,6 +1937,9 @@ static void gsm0_receive(struct gsm_mux *gsm, unsigned char c)  			break;  		}  		break; +	default: +		pr_debug("%s: unhandled state: %d\n", __func__, gsm->state); +		break;  	}  } @@ -1959,7 +1976,7 @@ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c)  	}  	if (c == GSM1_ESCAPE) { -		gsm->escape = 1; +		gsm->escape = true;  		return;  	} @@ -1969,7 +1986,7 @@ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c)  	if (gsm->escape) {  		c ^= GSM1_ESCAPE_BITS; -		gsm->escape = 0; +		gsm->escape = false;  	}  	switch (gsm->state) {  	case GSM_START:		/* First byte after SOF */ @@ -1997,6 +2014,9 @@ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c)  		break;  	case GSM_OVERRUN:	/* Over-long - eg a dropped SOF */  		break; +	default: +		pr_debug("%s: unhandled state: %d\n", __func__, gsm->state); +		break;  	}  } @@ -2061,7 +2081,7 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm)  	struct gsm_dlci *dlci = gsm->dlci[0];  	struct gsm_msg *txq, *ntxq; -	gsm->dead = 1; +	gsm->dead = true;  	spin_lock(&gsm_mux_lock);  	for (i = 0; i < MAX_MUX; i++) { @@ -2078,7 +2098,7 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm)  	del_timer_sync(&gsm->t2_timer);  	/* Now we are sure T2 has stopped */  	if (dlci) -		dlci->dead = 1; +		dlci->dead = true;  	/* Free up any link layer users */  	mutex_lock(&gsm->mutex); @@ -2132,7 +2152,7 @@ static int gsm_activate_mux(struct gsm_mux *gsm)  	dlci = gsm_dlci_alloc(gsm, 0);  	if (dlci == NULL)  		return -ENOMEM; -	gsm->dead = 0;		/* Tty opens are now permissible */ +	gsm->dead = false;		/* Tty opens are now permissible */  	return 0;  } @@ -2216,7 +2236,7 @@ static struct gsm_mux *gsm_alloc_mux(void)  	gsm->encoding = 1;  	gsm->mru = 64;	/* Default to encoding 1 so these should be 64 */  	gsm->mtu = 64; -	gsm->dead = 1;	/* Avoid early tty opens */ +	gsm->dead = true;	/* Avoid early tty opens */  	return gsm;  } @@ -2618,11 +2638,11 @@ static int gsmld_ioctl(struct tty_struct *tty, struct file *file,  	switch (cmd) {  	case GSMIOC_GETCONF:  		gsm_copy_config_values(gsm, &c); -		if (copy_to_user((void *)arg, &c, sizeof(c))) +		if (copy_to_user((void __user *)arg, &c, sizeof(c)))  			return -EFAULT;  		return 0;  	case GSMIOC_SETCONF: -		if (copy_from_user(&c, (void *)arg, sizeof(c))) +		if (copy_from_user(&c, (void __user *)arg, sizeof(c)))  			return -EFAULT;  		return gsm_config(gsm, &c);  	case GSMIOC_GETFIRST: @@ -2769,7 +2789,7 @@ static void gsm_destroy_network(struct gsm_dlci *dlci)  {  	struct gsm_mux_net *mux_net; -	pr_debug("destroy network interface"); +	pr_debug("destroy network interface\n");  	if (!dlci->net)  		return;  	mux_net = netdev_priv(dlci->net); @@ -2798,7 +2818,7 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc)  	if (nc->adaption != 3 && nc->adaption != 4)  		return -EPROTONOSUPPORT; -	pr_debug("create network interface"); +	pr_debug("create network interface\n");  	netname = "gsm%d";  	if (nc->if_name[0] != '\0') @@ -2806,7 +2826,7 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc)  	net = alloc_netdev(sizeof(struct gsm_mux_net), netname,  			   NET_NAME_UNKNOWN, gsm_mux_net_init);  	if (!net) { -		pr_err("alloc_netdev failed"); +		pr_err("alloc_netdev failed\n");  		return -ENOMEM;  	}  	net->mtu = dlci->gsm->mtu; @@ -2824,7 +2844,7 @@ static int gsm_create_network(struct gsm_dlci *dlci, struct gsm_netconfig *nc)  	dlci->data = gsm_mux_rx_netchar;  	dlci->net = net; -	pr_debug("register netdev"); +	pr_debug("register netdev\n");  	retval = register_netdev(net);  	if (retval) {  		pr_err("network register fail %d\n", retval); @@ -3030,7 +3050,7 @@ static int gsmtty_write(struct tty_struct *tty, const unsigned char *buf,  	if (dlci->state == DLCI_CLOSED)  		return -EINVAL;  	/* Stuff the bytes into the fifo queue */ -	sent = kfifo_in_locked(dlci->fifo, buf, len, &dlci->lock); +	sent = kfifo_in_locked(&dlci->fifo, buf, len, &dlci->lock);  	/* Need to kick the channel */  	gsm_dlci_data_kick(dlci);  	return sent; @@ -3041,7 +3061,7 @@ static int gsmtty_write_room(struct tty_struct *tty)  	struct gsm_dlci *dlci = tty->driver_data;  	if (dlci->state == DLCI_CLOSED)  		return -EINVAL; -	return TX_SIZE - kfifo_len(dlci->fifo); +	return TX_SIZE - kfifo_len(&dlci->fifo);  }  static int gsmtty_chars_in_buffer(struct tty_struct *tty) @@ -3049,7 +3069,7 @@ static int gsmtty_chars_in_buffer(struct tty_struct *tty)  	struct gsm_dlci *dlci = tty->driver_data;  	if (dlci->state == DLCI_CLOSED)  		return -EINVAL; -	return kfifo_len(dlci->fifo); +	return kfifo_len(&dlci->fifo);  }  static void gsmtty_flush_buffer(struct tty_struct *tty) @@ -3061,7 +3081,7 @@ static void gsmtty_flush_buffer(struct tty_struct *tty)  	   then the data being transmitted can't simply be junked once  	   it has first hit the stack. Until then we can just blow it  	   away */ -	kfifo_reset(dlci->fifo); +	kfifo_reset(&dlci->fifo);  	/* Need to unhook this DLCI from the transmit queue logic */  } @@ -3152,7 +3172,7 @@ static void gsmtty_throttle(struct tty_struct *tty)  		return;  	if (C_CRTSCTS(tty))  		dlci->modem_tx &= ~TIOCM_DTR; -	dlci->throttled = 1; +	dlci->throttled = true;  	/* Send an MSC with DTR cleared */  	gsmtty_modem_update(dlci, 0);  } @@ -3164,7 +3184,7 @@ static void gsmtty_unthrottle(struct tty_struct *tty)  		return;  	if (C_CRTSCTS(tty))  		dlci->modem_tx |= TIOCM_DTR; -	dlci->throttled = 0; +	dlci->throttled = false;  	/* Send an MSC with DTR set */  	gsmtty_modem_update(dlci, 0);  } diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index 27b506bf03ce..991f49ee4026 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -18,7 +18,7 @@   * All HDLC data is frame oriented which means:   *   * 1. tty write calls represent one complete transmit frame of data - *    The device driver should accept the complete frame or none of  + *    The device driver should accept the complete frame or none of   *    the frame (busy) in the write method. Each write call should have   *    a byte count in the range of 2-65535 bytes (2 is min HDLC frame   *    with 1 addr byte and 1 ctrl byte). The max byte count of 65535 @@ -39,7 +39,7 @@   *    tty read calls.   *   * 3. tty read calls returns an entire frame of data or nothing. - *     + *   * 4. all send and receive data is considered raw. No processing   *    or translation is performed by the line discipline, regardless   *    of the tty flags @@ -87,9 +87,6 @@  #include <linux/interrupt.h>  #include <linux/ptrace.h> -#undef VERSION -#define VERSION(major,minor,patch) (((((major)<<8)+(minor))<<8)+(patch)) -  #include <linux/poll.h>  #include <linux/in.h>  #include <linux/ioctl.h> @@ -107,7 +104,7 @@  /*   * Buffers for individual HDLC frames   */ -#define MAX_HDLC_FRAME_SIZE 65535  +#define MAX_HDLC_FRAME_SIZE 65535  #define DEFAULT_RX_BUF_COUNT 10  #define MAX_RX_BUF_COUNT 60  #define DEFAULT_TX_BUF_COUNT 3 @@ -127,11 +124,8 @@ struct n_hdlc_buf_list {  /**   * struct n_hdlc - per device instance data structure   * @magic - magic value for structure - * @flags - miscellaneous control flags - * @tty - ptr to TTY structure - * @backup_tty - TTY to use if tty gets closed   * @tbusy - reentrancy flag for tx wakeup code - * @woke_up - FIXME: describe this field + * @woke_up - tx wakeup needs to be run again as it was called while @tbusy   * @tx_buf_list - list of pending transmit frame buffers   * @rx_buf_list - list of received frame buffers   * @tx_free_buf_list - list unused transmit frame buffers @@ -139,11 +133,8 @@ struct n_hdlc_buf_list {   */  struct n_hdlc {  	int			magic; -	__u32			flags; -	struct tty_struct	*tty; -	struct tty_struct	*backup_tty; -	int			tbusy; -	int			woke_up; +	bool			tbusy; +	bool			woke_up;  	struct n_hdlc_buf_list	tx_buf_list;  	struct n_hdlc_buf_list	rx_buf_list;  	struct n_hdlc_buf_list	tx_free_buf_list; @@ -161,39 +152,14 @@ static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *list);  /* Local functions */ -static struct n_hdlc *n_hdlc_alloc (void); - -/* debug level can be set by insmod for debugging purposes */ -#define DEBUG_LEVEL_INFO	1 -static int debuglevel; +static struct n_hdlc *n_hdlc_alloc(void);  /* max frame size for memory allocations */  static int maxframe = 4096; -/* TTY callbacks */ - -static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, -			   __u8 __user *buf, size_t nr); -static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, -			    const unsigned char *buf, size_t nr); -static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, -			    unsigned int cmd, unsigned long arg); -static __poll_t n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, -				    poll_table *wait); -static int n_hdlc_tty_open(struct tty_struct *tty); -static void n_hdlc_tty_close(struct tty_struct *tty); -static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *cp, -			       char *fp, int count); -static void n_hdlc_tty_wakeup(struct tty_struct *tty); - -#define bset(p,b)	((p)[(b) >> 5] |= (1 << ((b) & 0x1f))) - -#define tty2n_hdlc(tty)	((struct n_hdlc *) ((tty)->disc_data)) -#define n_hdlc2tty(n_hdlc)	((n_hdlc)->tty) -  static void flush_rx_queue(struct tty_struct *tty)  { -	struct n_hdlc *n_hdlc = tty2n_hdlc(tty); +	struct n_hdlc *n_hdlc = tty->disc_data;  	struct n_hdlc_buf *buf;  	while ((buf = n_hdlc_buf_get(&n_hdlc->rx_buf_list))) @@ -202,79 +168,22 @@ static void flush_rx_queue(struct tty_struct *tty)  static void flush_tx_queue(struct tty_struct *tty)  { -	struct n_hdlc *n_hdlc = tty2n_hdlc(tty); +	struct n_hdlc *n_hdlc = tty->disc_data;  	struct n_hdlc_buf *buf;  	while ((buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list)))  		n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, buf);  } -static struct tty_ldisc_ops n_hdlc_ldisc = { -	.owner		= THIS_MODULE, -	.magic		= TTY_LDISC_MAGIC, -	.name		= "hdlc", -	.open		= n_hdlc_tty_open, -	.close		= n_hdlc_tty_close, -	.read		= n_hdlc_tty_read, -	.write		= n_hdlc_tty_write, -	.ioctl		= n_hdlc_tty_ioctl, -	.poll		= n_hdlc_tty_poll, -	.receive_buf	= n_hdlc_tty_receive, -	.write_wakeup	= n_hdlc_tty_wakeup, -	.flush_buffer   = flush_rx_queue, -}; - -/** - * n_hdlc_release - release an n_hdlc per device line discipline info structure - * @n_hdlc - per device line discipline info structure - */ -static void n_hdlc_release(struct n_hdlc *n_hdlc) +static void n_hdlc_free_buf_list(struct n_hdlc_buf_list *list)  { -	struct tty_struct *tty = n_hdlc2tty (n_hdlc);  	struct n_hdlc_buf *buf; -	 -	if (debuglevel >= DEBUG_LEVEL_INFO)	 -		printk("%s(%d)n_hdlc_release() called\n",__FILE__,__LINE__); -		 -	/* Ensure that the n_hdlcd process is not hanging on select()/poll() */ -	wake_up_interruptible (&tty->read_wait); -	wake_up_interruptible (&tty->write_wait); - -	if (tty->disc_data == n_hdlc) -		tty->disc_data = NULL;	/* Break the tty->n_hdlc link */ - -	/* Release transmit and receive buffers */ -	for(;;) { -		buf = n_hdlc_buf_get(&n_hdlc->rx_free_buf_list); -		if (buf) { -			kfree(buf); -		} else -			break; -	} -	for(;;) { -		buf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list); -		if (buf) { -			kfree(buf); -		} else -			break; -	} -	for(;;) { -		buf = n_hdlc_buf_get(&n_hdlc->rx_buf_list); -		if (buf) { -			kfree(buf); -		} else -			break; -	} -	for(;;) { -		buf = n_hdlc_buf_get(&n_hdlc->tx_buf_list); -		if (buf) { -			kfree(buf); -		} else -			break; -	} -	kfree(n_hdlc); -	 -}	/* end of n_hdlc_release() */ + +	do { +		buf = n_hdlc_buf_get(list); +		kfree(buf); +	} while (buf); +}  /**   * n_hdlc_tty_close - line discipline close @@ -285,34 +194,26 @@ static void n_hdlc_release(struct n_hdlc *n_hdlc)   */  static void n_hdlc_tty_close(struct tty_struct *tty)  { -	struct n_hdlc *n_hdlc = tty2n_hdlc (tty); - -	if (debuglevel >= DEBUG_LEVEL_INFO)	 -		printk("%s(%d)n_hdlc_tty_close() called\n",__FILE__,__LINE__); -		 -	if (n_hdlc != NULL) { -		if (n_hdlc->magic != HDLC_MAGIC) { -			printk (KERN_WARNING"n_hdlc: trying to close unopened tty!\n"); -			return; -		} +	struct n_hdlc *n_hdlc = tty->disc_data; + +	if (n_hdlc->magic != HDLC_MAGIC) { +		pr_warn("n_hdlc: trying to close unopened tty!\n"); +		return; +	}  #if defined(TTY_NO_WRITE_SPLIT) -		clear_bit(TTY_NO_WRITE_SPLIT,&tty->flags); +	clear_bit(TTY_NO_WRITE_SPLIT, &tty->flags);  #endif -		tty->disc_data = NULL; -		if (tty == n_hdlc->backup_tty) -			n_hdlc->backup_tty = NULL; -		if (tty != n_hdlc->tty) -			return; -		if (n_hdlc->backup_tty) { -			n_hdlc->tty = n_hdlc->backup_tty; -		} else { -			n_hdlc_release (n_hdlc); -		} -	} -	 -	if (debuglevel >= DEBUG_LEVEL_INFO)	 -		printk("%s(%d)n_hdlc_tty_close() success\n",__FILE__,__LINE__); -		 +	tty->disc_data = NULL; + +	/* Ensure that the n_hdlcd process is not hanging on select()/poll() */ +	wake_up_interruptible(&tty->read_wait); +	wake_up_interruptible(&tty->write_wait); + +	n_hdlc_free_buf_list(&n_hdlc->rx_free_buf_list); +	n_hdlc_free_buf_list(&n_hdlc->tx_free_buf_list); +	n_hdlc_free_buf_list(&n_hdlc->rx_buf_list); +	n_hdlc_free_buf_list(&n_hdlc->tx_buf_list); +	kfree(n_hdlc);  }	/* end of n_hdlc_tty_close() */  /** @@ -321,44 +222,35 @@ static void n_hdlc_tty_close(struct tty_struct *tty)   *   * Returns 0 if success, otherwise error code   */ -static int n_hdlc_tty_open (struct tty_struct *tty) +static int n_hdlc_tty_open(struct tty_struct *tty)  { -	struct n_hdlc *n_hdlc = tty2n_hdlc (tty); +	struct n_hdlc *n_hdlc = tty->disc_data; + +	pr_debug("%s() called (device=%s)\n", __func__, tty->name); -	if (debuglevel >= DEBUG_LEVEL_INFO)	 -		printk("%s(%d)n_hdlc_tty_open() called (device=%s)\n", -		__FILE__,__LINE__, -		tty->name); -		  	/* There should not be an existing table for this slot. */  	if (n_hdlc) { -		printk (KERN_ERR"n_hdlc_tty_open:tty already associated!\n" ); +		pr_err("%s: tty already associated!\n", __func__);  		return -EEXIST;  	} -	 +  	n_hdlc = n_hdlc_alloc();  	if (!n_hdlc) { -		printk (KERN_ERR "n_hdlc_alloc failed\n"); +		pr_err("%s: n_hdlc_alloc failed\n", __func__);  		return -ENFILE;  	} -		 +  	tty->disc_data = n_hdlc; -	n_hdlc->tty    = tty;  	tty->receive_room = 65536; -	 -#if defined(TTY_NO_WRITE_SPLIT) +  	/* change tty_io write() to not split large writes into 8K chunks */ -	set_bit(TTY_NO_WRITE_SPLIT,&tty->flags); -#endif -	 +	set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); +  	/* flush receive data from driver */  	tty_driver_flush_buffer(tty); -		 -	if (debuglevel >= DEBUG_LEVEL_INFO)	 -		printk("%s(%d)n_hdlc_tty_open() success\n",__FILE__,__LINE__); -		 +  	return 0; -	 +  }	/* end of n_tty_hdlc_open() */  /** @@ -376,26 +268,22 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)  	unsigned long flags;  	struct n_hdlc_buf *tbuf; -	if (debuglevel >= DEBUG_LEVEL_INFO)	 -		printk("%s(%d)n_hdlc_send_frames() called\n",__FILE__,__LINE__); - check_again: -		 - 	spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); +check_again: + +	spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags);  	if (n_hdlc->tbusy) { -		n_hdlc->woke_up = 1; - 		spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); +		n_hdlc->woke_up = true; +		spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);  		return;  	} -	n_hdlc->tbusy = 1; -	n_hdlc->woke_up = 0; +	n_hdlc->tbusy = true; +	n_hdlc->woke_up = false;  	spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);  	tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);  	while (tbuf) { -		if (debuglevel >= DEBUG_LEVEL_INFO)	 -			printk("%s(%d)sending frame %p, count=%d\n", -				__FILE__,__LINE__,tbuf,tbuf->count); -			 +		pr_debug("sending frame %p, count=%d\n", tbuf, tbuf->count); +  		/* Send the next block of data to device */  		set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);  		actual = tty->ops->write(tty, tbuf->buf, tbuf->count); @@ -409,24 +297,20 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)  		/* pretending it was accepted by driver */  		if (actual < 0)  			actual = tbuf->count; -		 +  		if (actual == tbuf->count) { -			if (debuglevel >= DEBUG_LEVEL_INFO)	 -				printk("%s(%d)frame %p completed\n", -					__FILE__,__LINE__,tbuf); -					 +			pr_debug("frame %p completed\n", tbuf); +  			/* free current transmit buffer */  			n_hdlc_buf_put(&n_hdlc->tx_free_buf_list, tbuf);  			/* wait up sleeping writers */  			wake_up_interruptible(&tty->write_wait); -	 +  			/* get next pending transmit buffer */  			tbuf = n_hdlc_buf_get(&n_hdlc->tx_buf_list);  		} else { -			if (debuglevel >= DEBUG_LEVEL_INFO)	 -				printk("%s(%d)frame %p pending\n", -					__FILE__,__LINE__,tbuf); +			pr_debug("frame %p pending\n", tbuf);  			/*  			 * the buffer was not accepted by driver, @@ -436,21 +320,17 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)  			break;  		}  	} -	 +  	if (!tbuf)  		clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); -	 +  	/* Clear the re-entry flag */  	spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); -	n_hdlc->tbusy = 0; -	spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);  -	 -        if (n_hdlc->woke_up) -	  goto check_again; - -	if (debuglevel >= DEBUG_LEVEL_INFO)	 -		printk("%s(%d)n_hdlc_send_frames() exit\n",__FILE__,__LINE__); -		 +	n_hdlc->tbusy = false; +	spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); + +	if (n_hdlc->woke_up) +		goto check_again;  }	/* end of n_hdlc_send_frames() */  /** @@ -461,21 +341,9 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)   */  static void n_hdlc_tty_wakeup(struct tty_struct *tty)  { -	struct n_hdlc *n_hdlc = tty2n_hdlc(tty); +	struct n_hdlc *n_hdlc = tty->disc_data; -	if (debuglevel >= DEBUG_LEVEL_INFO)	 -		printk("%s(%d)n_hdlc_tty_wakeup() called\n",__FILE__,__LINE__); -		 -	if (!n_hdlc) -		return; - -	if (tty != n_hdlc->tty) { -		clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); -		return; -	} - -	n_hdlc_send_frames (n_hdlc, tty); -		 +	n_hdlc_send_frames(n_hdlc, tty);  }	/* end of n_hdlc_tty_wakeup() */  /** @@ -491,59 +359,50 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty)  static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,  			       char *flags, int count)  { -	register struct n_hdlc *n_hdlc = tty2n_hdlc (tty); +	register struct n_hdlc *n_hdlc = tty->disc_data;  	register struct n_hdlc_buf *buf; -	if (debuglevel >= DEBUG_LEVEL_INFO)	 -		printk("%s(%d)n_hdlc_tty_receive() called count=%d\n", -			__FILE__,__LINE__, count); -		 -	/* This can happen if stuff comes in on the backup tty */ -	if (!n_hdlc || tty != n_hdlc->tty) -		return; -		 +	pr_debug("%s() called count=%d\n", __func__, count); +  	/* verify line is using HDLC discipline */  	if (n_hdlc->magic != HDLC_MAGIC) { -		printk("%s(%d) line not using HDLC discipline\n", -			__FILE__,__LINE__); +		pr_err("line not using HDLC discipline\n");  		return;  	} -	 -	if ( count>maxframe ) { -		if (debuglevel >= DEBUG_LEVEL_INFO)	 -			printk("%s(%d) rx count>maxframesize, data discarded\n", -			       __FILE__,__LINE__); + +	if (count > maxframe) { +		pr_debug("rx count>maxframesize, data discarded\n");  		return;  	} -	/* get a free HDLC buffer */	 +	/* get a free HDLC buffer */  	buf = n_hdlc_buf_get(&n_hdlc->rx_free_buf_list);  	if (!buf) { -		/* no buffers in free list, attempt to allocate another rx buffer */ -		/* unless the maximum count has been reached */ +		/* +		 * no buffers in free list, attempt to allocate another rx +		 * buffer unless the maximum count has been reached +		 */  		if (n_hdlc->rx_buf_list.count < MAX_RX_BUF_COUNT)  			buf = kmalloc(struct_size(buf, buf, maxframe),  				      GFP_ATOMIC);  	} -	 +  	if (!buf) { -		if (debuglevel >= DEBUG_LEVEL_INFO)	 -			printk("%s(%d) no more rx buffers, data discarded\n", -			       __FILE__,__LINE__); +		pr_debug("no more rx buffers, data discarded\n");  		return;  	} -		 +  	/* copy received data to HDLC buffer */ -	memcpy(buf->buf,data,count); -	buf->count=count; +	memcpy(buf->buf, data, count); +	buf->count = count;  	/* add HDLC buffer to list of received frames */  	n_hdlc_buf_put(&n_hdlc->rx_buf_list, buf); -	 +  	/* wake up any blocked reads and perform async signalling */ -	wake_up_interruptible (&tty->read_wait); -	if (n_hdlc->tty->fasync != NULL) -		kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN); +	wake_up_interruptible(&tty->read_wait); +	if (tty->fasync != NULL) +		kill_fasync(&tty->fasync, SIGIO, POLL_IN);  }	/* end of n_hdlc_tty_receive() */ @@ -553,28 +412,21 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,   * @file - pointer to open file object   * @buf - pointer to returned data buffer   * @nr - size of returned data buffer - * 	 + *   * Returns the number of bytes returned or error code.   */  static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,  			   __u8 __user *buf, size_t nr)  { -	struct n_hdlc *n_hdlc = tty2n_hdlc(tty); +	struct n_hdlc *n_hdlc = tty->disc_data;  	int ret = 0;  	struct n_hdlc_buf *rbuf;  	DECLARE_WAITQUEUE(wait, current); -	if (debuglevel >= DEBUG_LEVEL_INFO)	 -		printk("%s(%d)n_hdlc_tty_read() called\n",__FILE__,__LINE__); -		 -	/* Validate the pointers */ -	if (!n_hdlc) -		return -EIO; -  	/* verify user access to buffer */  	if (!access_ok(buf, nr)) { -		printk(KERN_WARNING "%s(%d) n_hdlc_tty_read() can't verify user " -		"buffer\n", __FILE__, __LINE__); +		pr_warn("%s(%d) %s() can't verify user buffer\n", +				__FILE__, __LINE__, __func__);  		return -EFAULT;  	} @@ -610,7 +462,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,  				n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf);  			break;  		} -			 +  		/* no data */  		if (tty_io_nonblock(tty, file)) {  			ret = -EAGAIN; @@ -629,7 +481,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,  	__set_current_state(TASK_RUNNING);  	return ret; -	 +  }	/* end of n_hdlc_tty_read() */  /** @@ -638,43 +490,34 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,   * @file - pointer to file object data   * @data - pointer to transmit data (one frame)   * @count - size of transmit frame in bytes - * 		 + *   * Returns the number of bytes written (or error code).   */  static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,  			    const unsigned char *data, size_t count)  { -	struct n_hdlc *n_hdlc = tty2n_hdlc (tty); +	struct n_hdlc *n_hdlc = tty->disc_data;  	int error = 0;  	DECLARE_WAITQUEUE(wait, current);  	struct n_hdlc_buf *tbuf; -	if (debuglevel >= DEBUG_LEVEL_INFO)	 -		printk("%s(%d)n_hdlc_tty_write() called count=%zd\n", -			__FILE__,__LINE__,count); -		 -	/* Verify pointers */ -	if (!n_hdlc) -		return -EIO; +	pr_debug("%s() called count=%zd\n", __func__, count);  	if (n_hdlc->magic != HDLC_MAGIC)  		return -EIO;  	/* verify frame size */ -	if (count > maxframe ) { -		if (debuglevel & DEBUG_LEVEL_INFO) -			printk (KERN_WARNING -				"n_hdlc_tty_write: truncating user packet " -				"from %lu to %d\n", (unsigned long) count, -				maxframe ); +	if (count > maxframe) { +		pr_debug("%s: truncating user packet from %zu to %d\n", +				__func__, count, maxframe);  		count = maxframe;  	} -	 +  	add_wait_queue(&tty->write_wait, &wait);  	for (;;) {  		set_current_state(TASK_INTERRUPTIBLE); -	 +  		tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list);  		if (tbuf)  			break; @@ -684,15 +527,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,  			break;  		}  		schedule(); -			 -		n_hdlc = tty2n_hdlc (tty); -		if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC ||  -		    tty != n_hdlc->tty) { -			printk("n_hdlc_tty_write: %p invalid after wait!\n", n_hdlc); -			error = -EIO; -			break; -		} -			 +  		if (signal_pending(current)) {  			error = -EINTR;  			break; @@ -702,18 +537,18 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,  	__set_current_state(TASK_RUNNING);  	remove_wait_queue(&tty->write_wait, &wait); -	if (!error) {		 +	if (!error) {  		/* Retrieve the user's buffer */  		memcpy(tbuf->buf, data, count);  		/* Send the data */  		tbuf->count = error = count; -		n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); -		n_hdlc_send_frames(n_hdlc,tty); +		n_hdlc_buf_put(&n_hdlc->tx_buf_list, tbuf); +		n_hdlc_send_frames(n_hdlc, tty);  	}  	return error; -	 +  }	/* end of n_hdlc_tty_write() */  /** @@ -728,32 +563,30 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,  static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,  			    unsigned int cmd, unsigned long arg)  { -	struct n_hdlc *n_hdlc = tty2n_hdlc (tty); +	struct n_hdlc *n_hdlc = tty->disc_data;  	int error = 0;  	int count;  	unsigned long flags;  	struct n_hdlc_buf *buf = NULL; -	if (debuglevel >= DEBUG_LEVEL_INFO)	 -		printk("%s(%d)n_hdlc_tty_ioctl() called %d\n", -			__FILE__,__LINE__,cmd); -		 +	pr_debug("%s() called %d\n", __func__, cmd); +  	/* Verify the status of the device */ -	if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC) +	if (n_hdlc->magic != HDLC_MAGIC)  		return -EBADF;  	switch (cmd) {  	case FIONREAD:  		/* report count of read data available */  		/* in next available frame (if any) */ -		spin_lock_irqsave(&n_hdlc->rx_buf_list.spinlock,flags); +		spin_lock_irqsave(&n_hdlc->rx_buf_list.spinlock, flags);  		buf = list_first_entry_or_null(&n_hdlc->rx_buf_list.list,  						struct n_hdlc_buf, list_item);  		if (buf)  			count = buf->count;  		else  			count = 0; -		spin_unlock_irqrestore(&n_hdlc->rx_buf_list.spinlock,flags); +		spin_unlock_irqrestore(&n_hdlc->rx_buf_list.spinlock, flags);  		error = put_user(count, (int __user *)arg);  		break; @@ -761,12 +594,12 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,  		/* get the pending tx byte count in the driver */  		count = tty_chars_in_buffer(tty);  		/* add size of next output frame in queue */ -		spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags); +		spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags);  		buf = list_first_entry_or_null(&n_hdlc->tx_buf_list.list,  						struct n_hdlc_buf, list_item);  		if (buf)  			count += buf->count; -		spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock,flags); +		spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags);  		error = put_user(count, (int __user *)arg);  		break; @@ -783,7 +616,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,  		break;  	}  	return error; -	 +  }	/* end of n_hdlc_tty_ioctl() */  /** @@ -791,7 +624,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,   * @tty - pointer to tty instance data   * @filp - pointer to open file object for device   * @poll_table - wait queue for operations - *  + *   * Determine which operations (read/write) will not block and return info   * to caller.   * Returns a bit mask containing info on which ops will not block. @@ -799,33 +632,50 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,  static __poll_t n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,  				    poll_table *wait)  { -	struct n_hdlc *n_hdlc = tty2n_hdlc (tty); +	struct n_hdlc *n_hdlc = tty->disc_data;  	__poll_t mask = 0; -	if (debuglevel >= DEBUG_LEVEL_INFO)	 -		printk("%s(%d)n_hdlc_tty_poll() called\n",__FILE__,__LINE__); -		 -	if (n_hdlc && n_hdlc->magic == HDLC_MAGIC && tty == n_hdlc->tty) { -		/* queue current process into any wait queue that */ -		/* may awaken in the future (read and write) */ - -		poll_wait(filp, &tty->read_wait, wait); -		poll_wait(filp, &tty->write_wait, wait); - -		/* set bits for operations that won't block */ -		if (!list_empty(&n_hdlc->rx_buf_list.list)) -			mask |= EPOLLIN | EPOLLRDNORM;	/* readable */ -		if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) -			mask |= EPOLLHUP; -		if (tty_hung_up_p(filp)) -			mask |= EPOLLHUP; -		if (!tty_is_writelocked(tty) && -				!list_empty(&n_hdlc->tx_free_buf_list.list)) -			mask |= EPOLLOUT | EPOLLWRNORM;	/* writable */ -	} +	if (n_hdlc->magic != HDLC_MAGIC) +		return 0; + +	/* +	 * queue the current process into any wait queue that may awaken in the +	 * future (read and write) +	 */ +	poll_wait(filp, &tty->read_wait, wait); +	poll_wait(filp, &tty->write_wait, wait); + +	/* set bits for operations that won't block */ +	if (!list_empty(&n_hdlc->rx_buf_list.list)) +		mask |= EPOLLIN | EPOLLRDNORM;	/* readable */ +	if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) +		mask |= EPOLLHUP; +	if (tty_hung_up_p(filp)) +		mask |= EPOLLHUP; +	if (!tty_is_writelocked(tty) && +			!list_empty(&n_hdlc->tx_free_buf_list.list)) +		mask |= EPOLLOUT | EPOLLWRNORM;	/* writable */ +  	return mask;  }	/* end of n_hdlc_tty_poll() */ +static void n_hdlc_alloc_buf(struct n_hdlc_buf_list *list, unsigned int count, +		const char *name) +{ +	struct n_hdlc_buf *buf; +	unsigned int i; + +	for (i = 0; i < count; i++) { +		buf = kmalloc(struct_size(buf, buf, maxframe), GFP_KERNEL); +		if (!buf) { +			pr_debug("%s(), kmalloc() failed for %s buffer %u\n", +					__func__, name, i); +			return; +		} +		n_hdlc_buf_put(list, buf); +	} +} +  /**   * n_hdlc_alloc - allocate an n_hdlc instance data structure   * @@ -833,8 +683,6 @@ static __poll_t n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,   */  static struct n_hdlc *n_hdlc_alloc(void)  { -	struct n_hdlc_buf *buf; -	int i;  	struct n_hdlc *n_hdlc = kzalloc(sizeof(*n_hdlc), GFP_KERNEL);  	if (!n_hdlc) @@ -850,30 +698,14 @@ static struct n_hdlc *n_hdlc_alloc(void)  	INIT_LIST_HEAD(&n_hdlc->rx_buf_list.list);  	INIT_LIST_HEAD(&n_hdlc->tx_buf_list.list); -	/* allocate free rx buffer list */ -	for(i=0;i<DEFAULT_RX_BUF_COUNT;i++) { -		buf = kmalloc(struct_size(buf, buf, maxframe), GFP_KERNEL); -		if (buf) -			n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,buf); -		else if (debuglevel >= DEBUG_LEVEL_INFO)	 -			printk("%s(%d)n_hdlc_alloc(), kalloc() failed for rx buffer %d\n",__FILE__,__LINE__, i); -	} -	 -	/* allocate free tx buffer list */ -	for(i=0;i<DEFAULT_TX_BUF_COUNT;i++) { -		buf = kmalloc(struct_size(buf, buf, maxframe), GFP_KERNEL); -		if (buf) -			n_hdlc_buf_put(&n_hdlc->tx_free_buf_list,buf); -		else if (debuglevel >= DEBUG_LEVEL_INFO)	 -			printk("%s(%d)n_hdlc_alloc(), kalloc() failed for tx buffer %d\n",__FILE__,__LINE__, i); -	} -	 +	n_hdlc_alloc_buf(&n_hdlc->rx_free_buf_list, DEFAULT_RX_BUF_COUNT, "rx"); +	n_hdlc_alloc_buf(&n_hdlc->tx_free_buf_list, DEFAULT_TX_BUF_COUNT, "tx"); +  	/* Initialize the control block */  	n_hdlc->magic  = HDLC_MAGIC; -	n_hdlc->flags  = 0; -	 +  	return n_hdlc; -	 +  }	/* end of n_hdlc_alloc() */  /** @@ -915,7 +747,7 @@ static void n_hdlc_buf_put(struct n_hdlc_buf_list *buf_list,  /**   * n_hdlc_buf_get - remove and return an HDLC buffer from list   * @buf_list - pointer to HDLC buffer list - *  + *   * Remove and return an HDLC buffer from the head of the specified HDLC buffer   * list.   * Returns a pointer to HDLC buffer if available, otherwise %NULL. @@ -938,44 +770,39 @@ static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list)  	return buf;  }	/* end of n_hdlc_buf_get() */ -static const char hdlc_banner[] __initconst = -	KERN_INFO "HDLC line discipline maxframe=%u\n"; -static const char hdlc_register_ok[] __initconst = -	KERN_INFO "N_HDLC line discipline registered.\n"; -static const char hdlc_register_fail[] __initconst = -	KERN_ERR "error registering line discipline: %d\n"; +static struct tty_ldisc_ops n_hdlc_ldisc = { +	.owner		= THIS_MODULE, +	.magic		= TTY_LDISC_MAGIC, +	.name		= "hdlc", +	.open		= n_hdlc_tty_open, +	.close		= n_hdlc_tty_close, +	.read		= n_hdlc_tty_read, +	.write		= n_hdlc_tty_write, +	.ioctl		= n_hdlc_tty_ioctl, +	.poll		= n_hdlc_tty_poll, +	.receive_buf	= n_hdlc_tty_receive, +	.write_wakeup	= n_hdlc_tty_wakeup, +	.flush_buffer   = flush_rx_queue, +};  static int __init n_hdlc_init(void)  {  	int status;  	/* range check maxframe arg */ -	if (maxframe < 4096) -		maxframe = 4096; -	else if (maxframe > 65535) -		maxframe = 65535; - -	printk(hdlc_banner, maxframe); +	maxframe = clamp(maxframe, 4096, MAX_HDLC_FRAME_SIZE);  	status = tty_register_ldisc(N_HDLC, &n_hdlc_ldisc);  	if (!status) -		printk(hdlc_register_ok); +		pr_info("N_HDLC line discipline registered with maxframe=%d\n", +				maxframe);  	else -		printk(hdlc_register_fail, status); +		pr_err("N_HDLC: error registering line discipline: %d\n", +				status);  	return status; -	 -}	/* end of init_module() */ - -#ifdef CONFIG_SPARC -#undef __exitdata -#define __exitdata -#endif -static const char hdlc_unregister_ok[] __exitdata = -	KERN_INFO "N_HDLC: line discipline unregistered\n"; -static const char hdlc_unregister_fail[] __exitdata = -	KERN_ERR "N_HDLC: can't unregister line discipline (err = %d)\n"; +}	/* end of init_module() */  static void __exit n_hdlc_exit(void)  { @@ -983,9 +810,10 @@ static void __exit n_hdlc_exit(void)  	int status = tty_unregister_ldisc(N_HDLC);  	if (status) -		printk(hdlc_unregister_fail, status); +		pr_err("N_HDLC: can't unregister line discipline (err = %d)\n", +				status);  	else -		printk(hdlc_unregister_ok); +		pr_info("N_HDLC: line discipline unregistered\n");  }  module_init(n_hdlc_init); @@ -993,6 +821,5 @@ module_exit(n_hdlc_exit);  MODULE_LICENSE("GPL");  MODULE_AUTHOR("Paul Fulghum [email protected]"); -module_param(debuglevel, int, 0);  module_param(maxframe, int, 0);  MODULE_ALIAS_LDISC(N_HDLC); diff --git a/drivers/tty/n_tracesink.h b/drivers/tty/n_tracesink.h index 1b846330c855..7031d515a700 100644 --- a/drivers/tty/n_tracesink.h +++ b/drivers/tty/n_tracesink.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */  /*   *  n_tracesink.h - Kernel driver API to route trace data in kernel space.   * diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index f9c584244f72..1794d84e7bf6 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -84,7 +84,7 @@  #ifdef N_TTY_TRACE  # define n_tty_trace(f, args...)	trace_printk(f, ##args)  #else -# define n_tty_trace(f, args...) +# define n_tty_trace(f, args...)	no_printk(f, ##args)  #endif  struct n_tty_data { @@ -654,9 +654,9 @@ static size_t __process_echoes(struct tty_struct *tty)  			op = echo_buf(ldata, tail + 1);  			switch (op) { +			case ECHO_OP_ERASE_TAB: {  				unsigned int num_chars, num_bs; -			case ECHO_OP_ERASE_TAB:  				if (MASK(ldata->echo_commit) == MASK(tail + 2))  					goto not_yet_stored;  				num_chars = echo_buf(ldata, tail + 2); @@ -687,7 +687,7 @@ static size_t __process_echoes(struct tty_struct *tty)  				}  				tail += 3;  				break; - +			}  			case ECHO_OP_SET_CANON_COL:  				ldata->canon_column = ldata->column;  				tail += 2; diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index ed99948f3b7f..d42b854cb7df 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c @@ -301,7 +301,7 @@ struct ctrl_dl {  	unsigned int DCD:1;  	unsigned int RI:1;  	unsigned int CTS:1; -	unsigned int reserverd:4; +	unsigned int reserved:4;  	u8 port;  } __attribute__ ((packed)); @@ -839,40 +839,39 @@ static char *interrupt2str(u16 interrupt)  	static char buf[TMP_BUF_MAX];  	char *p = buf; -	interrupt & MDM_DL1 ? p += snprintf(p, TMP_BUF_MAX, "MDM_DL1 ") : NULL; -	interrupt & MDM_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), -					"MDM_DL2 ") : NULL; - -	interrupt & MDM_UL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), -					"MDM_UL1 ") : NULL; -	interrupt & MDM_UL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), -					"MDM_UL2 ") : NULL; - -	interrupt & DIAG_DL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), -					"DIAG_DL1 ") : NULL; -	interrupt & DIAG_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf), -					"DIAG_DL2 ") : NULL; - -	interrupt & DIAG_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), -					"DIAG_UL ") : NULL; - -	interrupt & APP1_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), -					"APP1_DL ") : NULL; -	interrupt & APP2_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), -					"APP2_DL ") : NULL; - -	interrupt & APP1_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), -					"APP1_UL ") : NULL; -	interrupt & APP2_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), -					"APP2_UL ") : NULL; - -	interrupt & CTRL_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), -					"CTRL_DL ") : NULL; -	interrupt & CTRL_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf), -					"CTRL_UL ") : NULL; - -	interrupt & RESET ? p += snprintf(p, TMP_BUF_MAX - (p - buf), -					"RESET ") : NULL; +	if (interrupt & MDM_DL1) +		p += scnprintf(p, TMP_BUF_MAX, "MDM_DL1 "); +	if (interrupt & MDM_DL2) +		p += scnprintf(p, TMP_BUF_MAX - (p - buf), "MDM_DL2 "); +	if (interrupt & MDM_UL1) +		p += scnprintf(p, TMP_BUF_MAX - (p - buf), "MDM_UL1 "); +	if (interrupt & MDM_UL2) +		p += scnprintf(p, TMP_BUF_MAX - (p - buf), "MDM_UL2 "); +	if (interrupt & DIAG_DL1) +		p += scnprintf(p, TMP_BUF_MAX - (p - buf), "DIAG_DL1 "); +	if (interrupt & DIAG_DL2) +		p += scnprintf(p, TMP_BUF_MAX - (p - buf), "DIAG_DL2 "); + +	if (interrupt & DIAG_UL) +		p += scnprintf(p, TMP_BUF_MAX - (p - buf), "DIAG_UL "); + +	if (interrupt & APP1_DL) +		p += scnprintf(p, TMP_BUF_MAX - (p - buf), "APP1_DL "); +	if (interrupt & APP2_DL) +		p += scnprintf(p, TMP_BUF_MAX - (p - buf), "APP2_DL "); + +	if (interrupt & APP1_UL) +		p += scnprintf(p, TMP_BUF_MAX - (p - buf), "APP1_UL "); +	if (interrupt & APP2_UL) +		p += scnprintf(p, TMP_BUF_MAX - (p - buf), "APP2_UL "); + +	if (interrupt & CTRL_DL) +		p += scnprintf(p, TMP_BUF_MAX - (p - buf), "CTRL_DL "); +	if (interrupt & CTRL_UL) +		p += scnprintf(p, TMP_BUF_MAX - (p - buf), "CTRL_UL "); + +	if (interrupt & RESET) +		p += scnprintf(p, TMP_BUF_MAX - (p - buf), "RESET ");  	return buf;  } diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index fbaa4ec85560..e2138e7d5dc6 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -632,18 +632,21 @@ init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)  	tty_port_init(&info->port);  	info->port.ops = &rocket_port_ops;  	info->flags &= ~ROCKET_MODE_MASK; -	switch (pc104[board][line]) { -	case 422: -		info->flags |= ROCKET_MODE_RS422; -		break; -	case 485: -		info->flags |= ROCKET_MODE_RS485; -		break; -	case 232: -	default: +	if (board < ARRAY_SIZE(pc104) && line < ARRAY_SIZE(pc104_1)) +		switch (pc104[board][line]) { +		case 422: +			info->flags |= ROCKET_MODE_RS422; +			break; +		case 485: +			info->flags |= ROCKET_MODE_RS485; +			break; +		case 232: +		default: +			info->flags |= ROCKET_MODE_RS232; +			break; +		} +	else  		info->flags |= ROCKET_MODE_RS232; -		break; -	}  	info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR;  	if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) { diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 33ad9d6de532..52bb21205bb6 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */  /*   *  Driver for 8250/16550-type serial ports   * @@ -156,7 +156,9 @@ void serial8250_rpm_put(struct uart_8250_port *p);  void serial8250_rpm_get_tx(struct uart_8250_port *p);  void serial8250_rpm_put_tx(struct uart_8250_port *p); -int serial8250_em485_init(struct uart_8250_port *p); +int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485); +void serial8250_em485_start_tx(struct uart_8250_port *p); +void serial8250_em485_stop_tx(struct uart_8250_port *p);  void serial8250_em485_destroy(struct uart_8250_port *p);  /* MCR <-> TIOCM conversion */ diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index e70e3cc30050..12d03e678295 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -6,6 +6,10 @@   *   * Based on 8250_lpc18xx.c:   * Copyright (C) 2015 Joachim Eastwood <[email protected]> + * + * The bcm2835aux is capable of RTS auto flow-control, but this driver doesn't + * take advantage of it yet.  When adding support, be sure not to enable it + * simultaneously to rs485.   */  #include <linux/clk.h> @@ -16,16 +20,64 @@  #include "8250.h" +#define BCM2835_AUX_UART_CNTL		8 +#define BCM2835_AUX_UART_CNTL_RXEN	0x01 /* Receiver enable */ +#define BCM2835_AUX_UART_CNTL_TXEN	0x02 /* Transmitter enable */ +#define BCM2835_AUX_UART_CNTL_AUTORTS	0x04 /* RTS set by RX fill level */ +#define BCM2835_AUX_UART_CNTL_AUTOCTS	0x08 /* CTS stops transmitter */ +#define BCM2835_AUX_UART_CNTL_RTS3	0x00 /* RTS set until 3 chars left */ +#define BCM2835_AUX_UART_CNTL_RTS2	0x10 /* RTS set until 2 chars left */ +#define BCM2835_AUX_UART_CNTL_RTS1	0x20 /* RTS set until 1 chars left */ +#define BCM2835_AUX_UART_CNTL_RTS4	0x30 /* RTS set until 4 chars left */ +#define BCM2835_AUX_UART_CNTL_RTSINV	0x40 /* Invert auto RTS polarity */ +#define BCM2835_AUX_UART_CNTL_CTSINV	0x80 /* Invert auto CTS polarity */ +  /**   * struct bcm2835aux_data - driver private data of BCM2835 auxiliary UART   * @clk: clock producer of the port's uartclk   * @line: index of the port's serial8250_ports[] entry + * @cntl: cached copy of CNTL register   */  struct bcm2835aux_data {  	struct clk *clk;  	int line; +	u32 cntl;  }; +static void bcm2835aux_rs485_start_tx(struct uart_8250_port *up) +{ +	if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) { +		struct bcm2835aux_data *data = dev_get_drvdata(up->port.dev); + +		data->cntl &= ~BCM2835_AUX_UART_CNTL_RXEN; +		serial_out(up, BCM2835_AUX_UART_CNTL, data->cntl); +	} + +	/* +	 * On the bcm2835aux, the MCR register contains no other +	 * flags besides RTS.  So no need for a read-modify-write. +	 */ +	if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) +		serial8250_out_MCR(up, 0); +	else +		serial8250_out_MCR(up, UART_MCR_RTS); +} + +static void bcm2835aux_rs485_stop_tx(struct uart_8250_port *up) +{ +	if (up->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) +		serial8250_out_MCR(up, 0); +	else +		serial8250_out_MCR(up, UART_MCR_RTS); + +	if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX)) { +		struct bcm2835aux_data *data = dev_get_drvdata(up->port.dev); + +		data->cntl |= BCM2835_AUX_UART_CNTL_RXEN; +		serial_out(up, BCM2835_AUX_UART_CNTL, data->cntl); +	} +} +  static int bcm2835aux_serial_probe(struct platform_device *pdev)  {  	struct uart_8250_port up = { }; @@ -47,6 +99,14 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)  	up.port.fifosize = 8;  	up.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE |  			UPF_SKIP_TEST | UPF_IOREMAP; +	up.port.rs485_config = serial8250_em485_config; +	up.rs485_start_tx = bcm2835aux_rs485_start_tx; +	up.rs485_stop_tx = bcm2835aux_rs485_stop_tx; + +	/* initialize cached copy with power-on reset value */ +	data->cntl = BCM2835_AUX_UART_CNTL_RXEN | BCM2835_AUX_UART_CNTL_TXEN; + +	platform_set_drvdata(pdev, data);  	/* get the clock - this also enables the HW */  	data->clk = devm_clk_get(&pdev->dev, NULL); @@ -102,8 +162,6 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev)  	}  	data->line = ret; -	platform_set_drvdata(pdev, data); -  	return 0;  dis_clk: @@ -137,6 +195,24 @@ static struct platform_driver bcm2835aux_serial_driver = {  };  module_platform_driver(bcm2835aux_serial_driver); +#ifdef CONFIG_SERIAL_8250_CONSOLE + +static int __init early_bcm2835aux_setup(struct earlycon_device *device, +					const char *options) +{ +	if (!device->port.membase) +		return -ENODEV; + +	device->port.iotype = UPIO_MEM32; +	device->port.regshift = 2; + +	return early_serial8250_setup(device, NULL); +} + +OF_EARLYCON_DECLARE(bcm2835aux, "brcm,bcm2835-aux-uart", +		    early_bcm2835aux_setup); +#endif +  MODULE_DESCRIPTION("BCM2835 auxiliar UART driver");  MODULE_AUTHOR("Martin Sperl <[email protected]>");  MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index f2a33c9082a6..45d9117cab68 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -608,6 +608,14 @@ static int univ8250_console_setup(struct console *co, char *options)  	return retval;  } +static int univ8250_console_exit(struct console *co) +{ +	struct uart_port *port; + +	port = &serial8250_ports[co->index].port; +	return serial8250_console_exit(port); +} +  /**   *	univ8250_console_match - non-standard console matching   *	@co:	  registering console @@ -666,6 +674,7 @@ static struct console univ8250_console = {  	.write		= univ8250_console_write,  	.device		= uart_console_device,  	.setup		= univ8250_console_setup, +	.exit		= univ8250_console_exit,  	.match		= univ8250_console_match,  	.flags		= CON_PRINTBUFFER | CON_ANYTIME,  	.index		= -1, @@ -1007,14 +1016,18 @@ int serial8250_register_8250_port(struct uart_8250_port *up)  		uart->port.unthrottle	= up->port.unthrottle;  		uart->port.rs485_config	= up->port.rs485_config;  		uart->port.rs485	= up->port.rs485; +		uart->rs485_start_tx	= up->rs485_start_tx; +		uart->rs485_stop_tx	= up->rs485_stop_tx;  		uart->dma		= up->dma;  		/* Take tx_loadsz from fifosize if it wasn't set separately */  		if (uart->port.fifosize && !uart->tx_loadsz)  			uart->tx_loadsz = uart->port.fifosize; -		if (up->port.dev) +		if (up->port.dev) {  			uart->port.dev = up->port.dev; +			uart_get_rs485_mode(uart->port.dev, &uart->port.rs485); +		}  		if (up->port.flags & UPF_FIXED_TYPE)  			uart->port.type = up->port.type; diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h index 87a4db2a8aba..9a12953832d3 100644 --- a/drivers/tty/serial/8250/8250_dwlib.h +++ b/drivers/tty/serial/8250/8250_dwlib.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */  /* Synopsys DesignWare 8250 library header file. */  #include <linux/types.h> diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index d330da76d6b6..59449b6500cd 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -135,7 +135,7 @@ struct exar8250 {  	unsigned int		nr;  	struct exar8250_board	*board;  	void __iomem		*virt; -	int			line[0]; +	int			line[];  };  static void exar_pm(struct uart_port *port, unsigned int state, unsigned int old) diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index 60eff3240c8a..4dee8a9e0c95 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -156,6 +156,11 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)  	return 0;  } +static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port) +{ +	return 0; +} +  #ifdef CONFIG_SERIAL_8250_DMA  static const struct dw_dma_platform_data qrk_serial_dma_pdata = {  	.nr_channels = 2, @@ -356,6 +361,7 @@ static const struct lpss8250_board byt_board = {  static const struct lpss8250_board ehl_board = {  	.freq = 200000000,  	.base_baud = 12500000, +	.setup = ehl_serial_setup,  };  static const struct lpss8250_board qrk_board = { diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c index 4d067f515f74..f839380c2f4c 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -32,6 +32,7 @@  #define MTK_UART_RXTRI_AD	0x14	/* RX Trigger address */  #define MTK_UART_FRACDIV_L	0x15	/* Fractional divider LSB address */  #define MTK_UART_FRACDIV_M	0x16	/* Fractional divider MSB address */ +#define MTK_UART_DEBUG0	0x18  #define MTK_UART_IER_XOFFI	0x20	/* Enable XOFF character interrupt */  #define MTK_UART_IER_RTSI	0x40	/* Enable RTS Modem status interrupt */  #define MTK_UART_IER_CTSI	0x80	/* Enable CTS Modem status interrupt */ @@ -388,9 +389,18 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,  static int __maybe_unused mtk8250_runtime_suspend(struct device *dev)  {  	struct mtk8250_data *data = dev_get_drvdata(dev); +	struct uart_8250_port *up = serial8250_get_port(data->line); -	clk_disable_unprepare(data->uart_clk); -	clk_disable_unprepare(data->bus_clk); +	/* wait until UART in idle status */ +	while +		(serial_in(up, MTK_UART_DEBUG0)); + +	if (data->clk_count == 0U) { +		dev_dbg(dev, "%s clock count is 0\n", __func__); +	} else { +		clk_disable_unprepare(data->bus_clk); +		data->clk_count--; +	}  	return 0;  } @@ -400,16 +410,16 @@ static int __maybe_unused mtk8250_runtime_resume(struct device *dev)  	struct mtk8250_data *data = dev_get_drvdata(dev);  	int err; -	err = clk_prepare_enable(data->uart_clk); -	if (err) { -		dev_warn(dev, "Can't enable clock\n"); -		return err; -	} - -	err = clk_prepare_enable(data->bus_clk); -	if (err) { -		dev_warn(dev, "Can't enable bus clock\n"); -		return err; +	if (data->clk_count > 0U) { +		dev_dbg(dev, "%s clock count is %d\n", __func__, +			data->clk_count); +	} else { +		err = clk_prepare_enable(data->bus_clk); +		if (err) { +			dev_warn(dev, "Can't enable bus clock\n"); +			return err; +		} +		data->clk_count++;  	}  	return 0; @@ -419,12 +429,14 @@ static void  mtk8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)  {  	if (!state) -		pm_runtime_get_sync(port->dev); +		if (!mtk8250_runtime_resume(port->dev)) +			pm_runtime_get_sync(port->dev);  	serial8250_do_pm(port, state, old);  	if (state) -		pm_runtime_put_sync_suspend(port->dev); +		if (!pm_runtime_put_sync_suspend(port->dev)) +			mtk8250_runtime_suspend(port->dev);  }  #ifdef CONFIG_SERIAL_8250_DMA @@ -501,6 +513,8 @@ static int mtk8250_probe(struct platform_device *pdev)  	if (!data)  		return -ENOMEM; +	data->clk_count = 0; +  	if (pdev->dev.of_node) {  		err = mtk8250_probe_of(pdev, &uart.port, data);  		if (err) @@ -533,6 +547,7 @@ static int mtk8250_probe(struct platform_device *pdev)  	platform_set_drvdata(pdev, data); +	pm_runtime_enable(&pdev->dev);  	err = mtk8250_runtime_resume(&pdev->dev);  	if (err)  		return err; @@ -541,9 +556,6 @@ static int mtk8250_probe(struct platform_device *pdev)  	if (data->line < 0)  		return data->line; -	pm_runtime_set_active(&pdev->dev); -	pm_runtime_enable(&pdev->dev); -  	data->rx_wakeup_irq = platform_get_irq_optional(pdev, 1);  	return 0; @@ -556,11 +568,13 @@ static int mtk8250_remove(struct platform_device *pdev)  	pm_runtime_get_sync(&pdev->dev);  	serial8250_unregister_port(data->line); -	mtk8250_runtime_suspend(&pdev->dev);  	pm_runtime_disable(&pdev->dev);  	pm_runtime_put_noidle(&pdev->dev); +	if (!pm_runtime_status_suspended(&pdev->dev)) +		mtk8250_runtime_suspend(&pdev->dev); +  	return 0;  } diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index f6687756ec5e..65e9045dafe6 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -7,7 +7,6 @@  #include <linux/console.h>  #include <linux/module.h>  #include <linux/slab.h> -#include <linux/delay.h>  #include <linux/serial_core.h>  #include <linux/serial_reg.h>  #include <linux/of_address.h> @@ -26,67 +25,16 @@ struct of_serial_info {  	int line;  }; -#ifdef CONFIG_ARCH_TEGRA -static void tegra_serial_handle_break(struct uart_port *p) -{ -	unsigned int status, tmout = 10000; - -	do { -		status = p->serial_in(p, UART_LSR); -		if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) -			status = p->serial_in(p, UART_RX); -		else -			break; -		if (--tmout == 0) -			break; -		udelay(1); -	} while (1); -} -#else -static inline void tegra_serial_handle_break(struct uart_port *port) -{ -} -#endif - -static int of_8250_rs485_config(struct uart_port *port, -				  struct serial_rs485 *rs485) -{ -	struct uart_8250_port *up = up_to_u8250p(port); - -	/* Clamp the delays to [0, 100ms] */ -	rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); -	rs485->delay_rts_after_send  = min(rs485->delay_rts_after_send, 100U); - -	port->rs485 = *rs485; - -	/* -	 * Both serial8250_em485_init and serial8250_em485_destroy -	 * are idempotent -	 */ -	if (rs485->flags & SER_RS485_ENABLED) { -		int ret = serial8250_em485_init(up); - -		if (ret) { -			rs485->flags &= ~SER_RS485_ENABLED; -			port->rs485.flags &= ~SER_RS485_ENABLED; -		} -		return ret; -	} - -	serial8250_em485_destroy(up); - -	return 0; -} -  /*   * Fill a struct uart_port for a given device node   */  static int of_platform_serial_setup(struct platform_device *ofdev, -			int type, struct uart_port *port, +			int type, struct uart_8250_port *up,  			struct of_serial_info *info)  {  	struct resource resource;  	struct device_node *np = ofdev->dev.of_node; +	struct uart_port *port = &up->port;  	u32 clk, spd, prop;  	int ret, irq; @@ -207,13 +155,11 @@ static int of_platform_serial_setup(struct platform_device *ofdev,  		port->flags |= UPF_SKIP_TEST;  	port->dev = &ofdev->dev; -	port->rs485_config = of_8250_rs485_config; +	port->rs485_config = serial8250_em485_config; +	up->rs485_start_tx = serial8250_em485_start_tx; +	up->rs485_stop_tx = serial8250_em485_stop_tx;  	switch (type) { -	case PORT_TEGRA: -		port->handle_break = tegra_serial_handle_break; -		break; -  	case PORT_RT2880:  		port->iotype = UPIO_AU;  		break; @@ -258,7 +204,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)  		return -ENOMEM;  	memset(&port8250, 0, sizeof(port8250)); -	ret = of_platform_serial_setup(ofdev, port_type, &port8250.port, info); +	ret = of_platform_serial_setup(ofdev, port_type, &port8250, info);  	if (ret)  		goto err_free; @@ -358,7 +304,6 @@ static const struct of_device_id of_platform_serial_table[] = {  	{ .compatible = "ns16550",  .data = (void *)PORT_16550, },  	{ .compatible = "ns16750",  .data = (void *)PORT_16750, },  	{ .compatible = "ns16850",  .data = (void *)PORT_16850, }, -	{ .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, },  	{ .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, },  	{ .compatible = "ralink,rt2880-uart", .data = (void *)PORT_RT2880, },  	{ .compatible = "intel,xscale-uart", .data = (void *)PORT_XSCALE, }, diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 6f343ca08440..16cfb887c5a3 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -40,6 +40,7 @@   * The same errata is applicable to AM335x and DRA7x processors too.   */  #define UART_ERRATA_CLOCK_DISABLE	(1 << 3) +#define	UART_HAS_EFR2			BIT(4)  #define OMAP_UART_FCR_RX_TRIG		6  #define OMAP_UART_FCR_TX_TRIG		4 @@ -93,6 +94,10 @@  #define OMAP_UART_REV_52 0x0502  #define OMAP_UART_REV_63 0x0603 +/* Enhanced features register 2 */ +#define UART_OMAP_EFR2			0x23 +#define UART_OMAP_EFR2_TIMEOUT_BEHAVE	BIT(6) +  struct omap8250_priv {  	int line;  	u8 habit; @@ -105,6 +110,8 @@ struct omap8250_priv {  	u8 delayed_restore;  	u16 quot; +	u8 tx_trigger; +	u8 rx_trigger;  	bool is_suspending;  	int wakeirq;  	int wakeups_enabled; @@ -118,6 +125,17 @@ struct omap8250_priv {  	bool throttled;  }; +struct omap8250_dma_params { +	u32 rx_size; +	u8 rx_trigger; +	u8 tx_trigger; +}; + +struct omap8250_platdata { +	struct omap8250_dma_params *dma_params; +	u8 habit; +}; +  #ifdef CONFIG_SERIAL_8250_DMA  static void omap_8250_rx_dma_flush(struct uart_8250_port *p);  #else @@ -295,8 +313,8 @@ static void omap8250_restore_regs(struct uart_8250_port *up)  	serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_RESTORE(16) |  			OMAP_UART_TCR_HALT(52));  	serial_out(up, UART_TI752_TLR, -		   TRIGGER_TLR_MASK(TX_TRIGGER) << UART_TI752_TLR_TX | -		   TRIGGER_TLR_MASK(RX_TRIGGER) << UART_TI752_TLR_RX); +		   TRIGGER_TLR_MASK(priv->tx_trigger) << UART_TI752_TLR_TX | +		   TRIGGER_TLR_MASK(priv->rx_trigger) << UART_TI752_TLR_RX);  	serial_out(up, UART_LCR, 0); @@ -435,8 +453,8 @@ static void omap_8250_set_termios(struct uart_port *port,  	 * This is because threshold and trigger values are the same.  	 */  	up->fcr = UART_FCR_ENABLE_FIFO; -	up->fcr |= TRIGGER_FCR_MASK(TX_TRIGGER) << OMAP_UART_FCR_TX_TRIG; -	up->fcr |= TRIGGER_FCR_MASK(RX_TRIGGER) << OMAP_UART_FCR_RX_TRIG; +	up->fcr |= TRIGGER_FCR_MASK(priv->tx_trigger) << OMAP_UART_FCR_TX_TRIG; +	up->fcr |= TRIGGER_FCR_MASK(priv->rx_trigger) << OMAP_UART_FCR_RX_TRIG;  	priv->scr = OMAP_UART_SCR_RX_TRIG_GRANU1_MASK | OMAP_UART_SCR_TX_EMPTY |  		OMAP_UART_SCR_TX_TRIG_GRANU1_MASK; @@ -569,7 +587,7 @@ static void omap8250_uart_qos_work(struct work_struct *work)  	struct omap8250_priv *priv;  	priv = container_of(work, struct omap8250_priv, qos_work); -	pm_qos_update_request(&priv->pm_qos_request, priv->latency); +	cpu_latency_qos_update_request(&priv->pm_qos_request, priv->latency);  }  #ifdef CONFIG_SERIAL_8250_DMA @@ -651,7 +669,7 @@ static int omap_8250_startup(struct uart_port *port)  		priv->wer |= OMAP_UART_TX_WAKEUP_EN;  	serial_out(up, UART_OMAP_WER, priv->wer); -	if (up->dma) +	if (up->dma && !(priv->habit & UART_HAS_EFR2))  		up->dma->rx_dma(up);  	pm_runtime_mark_last_busy(port->dev); @@ -676,6 +694,8 @@ static void omap_8250_shutdown(struct uart_port *port)  	pm_runtime_get_sync(port->dev);  	serial_out(up, UART_OMAP_WER, 0); +	if (priv->habit & UART_HAS_EFR2) +		serial_out(up, UART_OMAP_EFR2, 0x0);  	up->ier = 0;  	serial_out(up, UART_IER, 0); @@ -699,14 +719,12 @@ static void omap_8250_shutdown(struct uart_port *port)  static void omap_8250_throttle(struct uart_port *port)  {  	struct omap8250_priv *priv = port->private_data; -	struct uart_8250_port *up = up_to_u8250p(port);  	unsigned long flags;  	pm_runtime_get_sync(port->dev);  	spin_lock_irqsave(&port->lock, flags); -	up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); -	serial_out(up, UART_IER, up->ier); +	port->ops->stop_rx(port);  	priv->throttled = true;  	spin_unlock_irqrestore(&port->lock, flags); @@ -714,36 +732,6 @@ static void omap_8250_throttle(struct uart_port *port)  	pm_runtime_put_autosuspend(port->dev);  } -static int omap_8250_rs485_config(struct uart_port *port, -				  struct serial_rs485 *rs485) -{ -	struct uart_8250_port *up = up_to_u8250p(port); - -	/* Clamp the delays to [0, 100ms] */ -	rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); -	rs485->delay_rts_after_send  = min(rs485->delay_rts_after_send, 100U); - -	port->rs485 = *rs485; - -	/* -	 * Both serial8250_em485_init and serial8250_em485_destroy -	 * are idempotent -	 */ -	if (rs485->flags & SER_RS485_ENABLED) { -		int ret = serial8250_em485_init(up); - -		if (ret) { -			rs485->flags &= ~SER_RS485_ENABLED; -			port->rs485.flags &= ~SER_RS485_ENABLED; -		} -		return ret; -	} - -	serial8250_em485_destroy(up); - -	return 0; -} -  static void omap_8250_unthrottle(struct uart_port *port)  {  	struct omap8250_priv *priv = port->private_data; @@ -757,6 +745,7 @@ static void omap_8250_unthrottle(struct uart_port *port)  	if (up->dma)  		up->dma->rx_dma(up);  	up->ier |= UART_IER_RLSI | UART_IER_RDI; +	port->read_status_mask |= UART_LSR_DR;  	serial_out(up, UART_IER, up->ier);  	spin_unlock_irqrestore(&port->lock, flags); @@ -767,32 +756,50 @@ static void omap_8250_unthrottle(struct uart_port *port)  #ifdef CONFIG_SERIAL_8250_DMA  static int omap_8250_rx_dma(struct uart_8250_port *p); +/* Must be called while priv->rx_dma_lock is held */  static void __dma_rx_do_complete(struct uart_8250_port *p)  { -	struct omap8250_priv	*priv = p->port.private_data;  	struct uart_8250_dma    *dma = p->dma;  	struct tty_port         *tty_port = &p->port.state->port; +	struct dma_chan		*rxchan = dma->rxchan; +	dma_cookie_t		cookie;  	struct dma_tx_state     state;  	int                     count; -	unsigned long		flags;  	int			ret; -	spin_lock_irqsave(&priv->rx_dma_lock, flags); -  	if (!dma->rx_running) -		goto unlock; +		goto out; +	cookie = dma->rx_cookie;  	dma->rx_running = 0; -	dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); +	dmaengine_tx_status(rxchan, cookie, &state); + +	count = dma->rx_size - state.residue + state.in_flight_bytes; +	if (count < dma->rx_size) { +		dmaengine_terminate_async(rxchan); + +		/* +		 * Poll for teardown to complete which guarantees in +		 * flight data is drained. +		 */ +		if (state.in_flight_bytes) { +			int poll_count = 25; -	count = dma->rx_size - state.residue; +			while (dmaengine_tx_status(rxchan, cookie, NULL) && +			       poll_count--) +				cpu_relax(); +			if (!poll_count) +				dev_err(p->port.dev, "teardown incomplete\n"); +		} +	} +	if (!count) +		goto out;  	ret = tty_insert_flip_string(tty_port, dma->rx_buf, count);  	p->port.icount.rx += ret;  	p->port.icount.buf_overrun += count - ret; -unlock: -	spin_unlock_irqrestore(&priv->rx_dma_lock, flags); +out:  	tty_flip_buffer_push(tty_port);  } @@ -818,8 +825,12 @@ static void __dma_rx_complete(void *param)  		return;  	}  	__dma_rx_do_complete(p); -	if (!priv->throttled) -		omap_8250_rx_dma(p); +	if (!priv->throttled) { +		p->ier |= UART_IER_RLSI | UART_IER_RDI; +		serial_out(p, UART_IER, p->ier); +		if (!(priv->habit & UART_HAS_EFR2)) +			omap_8250_rx_dma(p); +	}  	spin_unlock_irqrestore(&p->port.lock, flags);  } @@ -845,10 +856,8 @@ static void omap_8250_rx_dma_flush(struct uart_8250_port *p)  		if (WARN_ON_ONCE(ret))  			priv->rx_dma_broken = true;  	} -	spin_unlock_irqrestore(&priv->rx_dma_lock, flags); -  	__dma_rx_do_complete(p); -	dmaengine_terminate_all(dma->rxchan); +	spin_unlock_irqrestore(&priv->rx_dma_lock, flags);  }  static int omap_8250_rx_dma(struct uart_8250_port *p) @@ -864,8 +873,20 @@ static int omap_8250_rx_dma(struct uart_8250_port *p)  	spin_lock_irqsave(&priv->rx_dma_lock, flags); -	if (dma->rx_running) +	if (dma->rx_running) { +		enum dma_status state; + +		state = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, NULL); +		if (state == DMA_COMPLETE) { +			/* +			 * Disable RX interrupts to allow RX DMA completion +			 * callback to run. +			 */ +			p->ier &= ~(UART_IER_RLSI | UART_IER_RDI); +			serial_out(p, UART_IER, p->ier); +		}  		goto out; +	}  	desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,  					   dma->rx_size, DMA_DEV_TO_MEM, @@ -1036,6 +1057,46 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)  	return omap_8250_rx_dma(up);  } +static unsigned char omap_8250_handle_rx_dma(struct uart_8250_port *up, +					     u8 iir, unsigned char status) +{ +	if ((status & (UART_LSR_DR | UART_LSR_BI)) && +	    (iir & UART_IIR_RDI)) { +		if (handle_rx_dma(up, iir)) { +			status = serial8250_rx_chars(up, status); +			omap_8250_rx_dma(up); +		} +	} + +	return status; +} + +static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir, +				     unsigned char status) +{ +	/* +	 * Queue a new transfer if FIFO has data. +	 */ +	if ((status & (UART_LSR_DR | UART_LSR_BI)) && +	    (up->ier & UART_IER_RDI)) { +		omap_8250_rx_dma(up); +		serial_out(up, UART_OMAP_EFR2, UART_OMAP_EFR2_TIMEOUT_BEHAVE); +	} else if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) { +		/* +		 * Disable RX timeout, read IIR to clear +		 * current timeout condition, clear EFR2 to +		 * periodic timeouts, re-enable interrupts. +		 */ +		up->ier &= ~(UART_IER_RLSI | UART_IER_RDI); +		serial_out(up, UART_IER, up->ier); +		omap_8250_rx_dma_flush(up); +		serial_in(up, UART_IIR); +		serial_out(up, UART_OMAP_EFR2, 0x0); +		up->ier |= UART_IER_RLSI | UART_IER_RDI; +		serial_out(up, UART_IER, up->ier); +	} +} +  /*   * This is mostly serial8250_handle_irq(). We have a slightly different DMA   * hoook for RX/TX and need different logic for them in the ISR. Therefore we @@ -1044,6 +1105,7 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir)  static int omap_8250_dma_handle_irq(struct uart_port *port)  {  	struct uart_8250_port *up = up_to_u8250p(port); +	struct omap8250_priv *priv = up->port.private_data;  	unsigned char status;  	unsigned long flags;  	u8 iir; @@ -1053,19 +1115,18 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)  	iir = serial_port_in(port, UART_IIR);  	if (iir & UART_IIR_NO_INT) {  		serial8250_rpm_put(up); -		return 0; +		return IRQ_HANDLED;  	}  	spin_lock_irqsave(&port->lock, flags);  	status = serial_port_in(port, UART_LSR); -	if (status & (UART_LSR_DR | UART_LSR_BI)) { -		if (handle_rx_dma(up, iir)) { -			status = serial8250_rx_chars(up, status); -			omap_8250_rx_dma(up); -		} -	} +	if (priv->habit & UART_HAS_EFR2) +		am654_8250_handle_rx_dma(up, iir, status); +	else +		status = omap_8250_handle_rx_dma(up, iir, status); +  	serial8250_modem_status(up);  	if (status & UART_LSR_THRE && up->dma->tx_err) {  		if (uart_tx_stopped(&up->port) || @@ -1107,18 +1168,41 @@ static int omap8250_no_handle_irq(struct uart_port *port)  	return 0;  } -static const u8 omap4_habit = UART_ERRATA_CLOCK_DISABLE; -static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE; -static const u8 dra742_habit = UART_ERRATA_CLOCK_DISABLE; +static struct omap8250_dma_params am654_dma = { +	.rx_size = SZ_2K, +	.rx_trigger = 1, +	.tx_trigger = TX_TRIGGER, +}; + +static struct omap8250_dma_params am33xx_dma = { +	.rx_size = RX_TRIGGER, +	.rx_trigger = RX_TRIGGER, +	.tx_trigger = TX_TRIGGER, +}; + +static struct omap8250_platdata am654_platdata = { +	.dma_params	= &am654_dma, +	.habit		= UART_HAS_EFR2, +}; + +static struct omap8250_platdata am33xx_platdata = { +	.dma_params	= &am33xx_dma, +	.habit		= OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE, +}; + +static struct omap8250_platdata omap4_platdata = { +	.dma_params	= &am33xx_dma, +	.habit		= UART_ERRATA_CLOCK_DISABLE, +};  static const struct of_device_id omap8250_dt_ids[] = { -	{ .compatible = "ti,am654-uart" }, +	{ .compatible = "ti,am654-uart", .data = &am654_platdata, },  	{ .compatible = "ti,omap2-uart" },  	{ .compatible = "ti,omap3-uart" }, -	{ .compatible = "ti,omap4-uart", .data = &omap4_habit, }, -	{ .compatible = "ti,am3352-uart", .data = &am3352_habit, }, -	{ .compatible = "ti,am4372-uart", .data = &am3352_habit, }, -	{ .compatible = "ti,dra742-uart", .data = &dra742_habit, }, +	{ .compatible = "ti,omap4-uart", .data = &omap4_platdata, }, +	{ .compatible = "ti,am3352-uart", .data = &am33xx_platdata, }, +	{ .compatible = "ti,am4372-uart", .data = &am33xx_platdata, }, +	{ .compatible = "ti,dra742-uart", .data = &omap4_platdata, },  	{},  };  MODULE_DEVICE_TABLE(of, omap8250_dt_ids); @@ -1129,10 +1213,10 @@ static int omap8250_probe(struct platform_device *pdev)  	struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);  	struct device_node *np = pdev->dev.of_node;  	struct omap8250_priv *priv; +	const struct omap8250_platdata *pdata;  	struct uart_8250_port up;  	int ret;  	void __iomem *membase; -	const struct of_device_id *id;  	if (!regs || !irq) {  		dev_err(&pdev->dev, "missing registers or irq\n"); @@ -1187,7 +1271,9 @@ static int omap8250_probe(struct platform_device *pdev)  	up.port.shutdown = omap_8250_shutdown;  	up.port.throttle = omap_8250_throttle;  	up.port.unthrottle = omap_8250_unthrottle; -	up.port.rs485_config = omap_8250_rs485_config; +	up.port.rs485_config = serial8250_em485_config; +	up.rs485_start_tx = serial8250_em485_start_tx; +	up.rs485_stop_tx = serial8250_em485_stop_tx;  	up.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);  	ret = of_alias_get_id(np, "serial"); @@ -1211,9 +1297,9 @@ static int omap8250_probe(struct platform_device *pdev)  	priv->wakeirq = irq_of_parse_and_map(np, 1); -	id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev); -	if (id && id->data) -		priv->habit |= *(u8 *)id->data; +	pdata = of_device_get_match_data(&pdev->dev); +	if (pdata) +		priv->habit |= pdata->habit;  	if (!up.port.uartclk) {  		up.port.uartclk = DEFAULT_CLK_SPEED; @@ -1222,15 +1308,15 @@ static int omap8250_probe(struct platform_device *pdev)  			 DEFAULT_CLK_SPEED);  	} -	priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; -	priv->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; -	pm_qos_add_request(&priv->pm_qos_request, PM_QOS_CPU_DMA_LATENCY, -			   priv->latency); +	priv->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; +	priv->calc_latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; +	cpu_latency_qos_add_request(&priv->pm_qos_request, priv->latency);  	INIT_WORK(&priv->qos_work, omap8250_uart_qos_work);  	spin_lock_init(&priv->rx_dma_lock);  	device_init_wakeup(&pdev->dev, true); +	pm_runtime_enable(&pdev->dev);  	pm_runtime_use_autosuspend(&pdev->dev);  	/* @@ -1244,12 +1330,13 @@ static int omap8250_probe(struct platform_device *pdev)  		pm_runtime_set_autosuspend_delay(&pdev->dev, -1);  	pm_runtime_irq_safe(&pdev->dev); -	pm_runtime_enable(&pdev->dev);  	pm_runtime_get_sync(&pdev->dev);  	omap_serial_fill_features_erratas(&up, priv);  	up.port.handle_irq = omap8250_no_handle_irq; +	priv->rx_trigger = RX_TRIGGER; +	priv->tx_trigger = TX_TRIGGER;  #ifdef CONFIG_SERIAL_8250_DMA  	/*  	 * Oh DMA support. If there are no DMA properties in the DT then @@ -1261,13 +1348,26 @@ static int omap8250_probe(struct platform_device *pdev)  	 */  	ret = of_property_count_strings(np, "dma-names");  	if (ret == 2) { +		struct omap8250_dma_params *dma_params = NULL; +  		up.dma = &priv->omap8250_dma; -		priv->omap8250_dma.fn = the_no_dma_filter_fn; -		priv->omap8250_dma.tx_dma = omap_8250_tx_dma; -		priv->omap8250_dma.rx_dma = omap_8250_rx_dma; -		priv->omap8250_dma.rx_size = RX_TRIGGER; -		priv->omap8250_dma.rxconf.src_maxburst = RX_TRIGGER; -		priv->omap8250_dma.txconf.dst_maxburst = TX_TRIGGER; +		up.dma->fn = the_no_dma_filter_fn; +		up.dma->tx_dma = omap_8250_tx_dma; +		up.dma->rx_dma = omap_8250_rx_dma; +		if (pdata) +			dma_params = pdata->dma_params; + +		if (dma_params) { +			up.dma->rx_size = dma_params->rx_size; +			up.dma->rxconf.src_maxburst = dma_params->rx_trigger; +			up.dma->txconf.dst_maxburst = dma_params->tx_trigger; +			priv->rx_trigger = dma_params->rx_trigger; +			priv->tx_trigger = dma_params->tx_trigger; +		} else { +			up.dma->rx_size = RX_TRIGGER; +			up.dma->rxconf.src_maxburst = RX_TRIGGER; +			up.dma->txconf.dst_maxburst = TX_TRIGGER; +		}  	}  #endif  	ret = serial8250_register_8250_port(&up); @@ -1295,7 +1395,7 @@ static int omap8250_remove(struct platform_device *pdev)  	pm_runtime_put_sync(&pdev->dev);  	pm_runtime_disable(&pdev->dev);  	serial8250_unregister_port(priv->line); -	pm_qos_remove_request(&priv->pm_qos_request); +	cpu_latency_qos_remove_request(&priv->pm_qos_request);  	device_init_wakeup(&pdev->dev, false);  	return 0;  } @@ -1445,7 +1545,7 @@ static int omap8250_runtime_suspend(struct device *dev)  	if (up->dma && up->dma->rxchan)  		omap_8250_rx_dma_flush(up); -	priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; +	priv->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE;  	schedule_work(&priv->qos_work);  	return 0; @@ -1465,7 +1565,7 @@ static int omap8250_runtime_resume(struct device *dev)  	if (omap8250_lost_context(up))  		omap8250_restore_regs(up); -	if (up->dma && up->dma->rxchan) +	if (up->dma && up->dma->rxchan && !(priv->habit & UART_HAS_EFR2))  		omap_8250_rx_dma(up);  	priv->latency = priv->calc_latency; diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 939685fed396..0804469ff052 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -53,7 +53,7 @@ struct serial_private {  	unsigned int		nr;  	struct pci_serial_quirk	*quirk;  	const struct pciserial_board *board; -	int			line[0]; +	int			line[];  };  static const struct pci_device_id pci_use_msi[] = { diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 0325f2e53b74..f77bf820b7a3 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -557,17 +557,6 @@ static void serial8250_clear_fifos(struct uart_8250_port *p)  	}  } -static inline void serial8250_em485_rts_after_send(struct uart_8250_port *p) -{ -	unsigned char mcr = serial8250_in_MCR(p); - -	if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) -		mcr |= UART_MCR_RTS; -	else -		mcr &= ~UART_MCR_RTS; -	serial8250_out_MCR(p, mcr); -} -  static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t);  static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t); @@ -615,7 +604,7 @@ EXPORT_SYMBOL_GPL(serial8250_rpm_put);   *   *	Return 0 - success, -errno - otherwise   */ -int serial8250_em485_init(struct uart_8250_port *p) +static int serial8250_em485_init(struct uart_8250_port *p)  {  	if (p->em485)  		return 0; @@ -632,11 +621,12 @@ int serial8250_em485_init(struct uart_8250_port *p)  	p->em485->start_tx_timer.function = &serial8250_em485_handle_start_tx;  	p->em485->port = p;  	p->em485->active_timer = NULL; -	serial8250_em485_rts_after_send(p); +	p->em485->tx_stopped = true; + +	p->rs485_stop_tx(p);  	return 0;  } -EXPORT_SYMBOL_GPL(serial8250_em485_init);  /**   *	serial8250_em485_destroy() - put uart_8250_port into normal state @@ -664,6 +654,52 @@ void serial8250_em485_destroy(struct uart_8250_port *p)  }  EXPORT_SYMBOL_GPL(serial8250_em485_destroy); +/** + * serial8250_em485_config() - generic ->rs485_config() callback + * @port: uart port + * @rs485: rs485 settings + * + * Generic callback usable by 8250 uart drivers to activate rs485 settings + * if the uart is incapable of driving RTS as a Transmit Enable signal in + * hardware, relying on software emulation instead. + */ +int serial8250_em485_config(struct uart_port *port, struct serial_rs485 *rs485) +{ +	struct uart_8250_port *up = up_to_u8250p(port); + +	/* pick sane settings if the user hasn't */ +	if (!!(rs485->flags & SER_RS485_RTS_ON_SEND) == +	    !!(rs485->flags & SER_RS485_RTS_AFTER_SEND)) { +		rs485->flags |= SER_RS485_RTS_ON_SEND; +		rs485->flags &= ~SER_RS485_RTS_AFTER_SEND; +	} + +	/* clamp the delays to [0, 100ms] */ +	rs485->delay_rts_before_send = min(rs485->delay_rts_before_send, 100U); +	rs485->delay_rts_after_send  = min(rs485->delay_rts_after_send, 100U); + +	memset(rs485->padding, 0, sizeof(rs485->padding)); +	port->rs485 = *rs485; + +	/* +	 * Both serial8250_em485_init() and serial8250_em485_destroy() +	 * are idempotent. +	 */ +	if (rs485->flags & SER_RS485_ENABLED) { +		int ret = serial8250_em485_init(up); + +		if (ret) { +			rs485->flags &= ~SER_RS485_ENABLED; +			port->rs485.flags &= ~SER_RS485_ENABLED; +		} +		return ret; +	} + +	serial8250_em485_destroy(up); +	return 0; +} +EXPORT_SYMBOL_GPL(serial8250_em485_config); +  /*   * These two wrappers ensure that enable_runtime_pm_tx() can be called more than   * once and disable_runtime_pm_tx() will still disable RPM because the fifo is @@ -1318,8 +1354,8 @@ out_lock:  		fintek_8250_probe(up);  	if (up->capabilities != old_capabilities) { -		pr_warn("%s: detected caps %08x should be %08x\n", -			port->name, old_capabilities, up->capabilities); +		dev_warn(port->dev, "detected caps %08x should be %08x\n", +			 old_capabilities, up->capabilities);  	}  out:  	DEBUG_AUTOCONF("iir=%d ", scratch); @@ -1394,9 +1430,21 @@ static void serial8250_stop_rx(struct uart_port *port)  	serial8250_rpm_put(up);  } -static void __do_stop_tx_rs485(struct uart_8250_port *p) +/** + * serial8250_em485_stop_tx() - generic ->rs485_stop_tx() callback + * @up: uart 8250 port + * + * Generic callback usable by 8250 uart drivers to stop rs485 transmission. + */ +void serial8250_em485_stop_tx(struct uart_8250_port *p)  { -	serial8250_em485_rts_after_send(p); +	unsigned char mcr = serial8250_in_MCR(p); + +	if (p->port.rs485.flags & SER_RS485_RTS_AFTER_SEND) +		mcr |= UART_MCR_RTS; +	else +		mcr &= ~UART_MCR_RTS; +	serial8250_out_MCR(p, mcr);  	/*  	 * Empty the RX FIFO, we are not interested in anything @@ -1410,6 +1458,8 @@ static void __do_stop_tx_rs485(struct uart_8250_port *p)  		serial_port_out(&p->port, UART_IER, p->ier);  	}  } +EXPORT_SYMBOL_GPL(serial8250_em485_stop_tx); +  static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t)  {  	struct uart_8250_em485 *em485; @@ -1422,8 +1472,9 @@ static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t)  	serial8250_rpm_get(p);  	spin_lock_irqsave(&p->port.lock, flags);  	if (em485->active_timer == &em485->stop_tx_timer) { -		__do_stop_tx_rs485(p); +		p->rs485_stop_tx(p);  		em485->active_timer = NULL; +		em485->tx_stopped = true;  	}  	spin_unlock_irqrestore(&p->port.lock, flags);  	serial8250_rpm_put(p); @@ -1444,7 +1495,7 @@ static void __stop_tx_rs485(struct uart_8250_port *p)  	struct uart_8250_em485 *em485 = p->em485;  	/* -	 * __do_stop_tx_rs485 is going to set RTS according to config +	 * rs485_stop_tx() is going to set RTS according to config  	 * AND flush RX FIFO if required.  	 */  	if (p->port.rs485.delay_rts_after_send > 0) { @@ -1452,7 +1503,9 @@ static void __stop_tx_rs485(struct uart_8250_port *p)  		start_hrtimer_ms(&em485->stop_tx_timer,  				   p->port.rs485.delay_rts_after_send);  	} else { -		__do_stop_tx_rs485(p); +		p->rs485_stop_tx(p); +		em485->active_timer = NULL; +		em485->tx_stopped = true;  	}  } @@ -1477,8 +1530,6 @@ static inline void __stop_tx(struct uart_8250_port *p)  		if ((lsr & BOTH_EMPTY) != BOTH_EMPTY)  			return; -		em485->active_timer = NULL; -  		__stop_tx_rs485(p);  	}  	__do_stop_tx(p); @@ -1528,25 +1579,42 @@ static inline void __start_tx(struct uart_port *port)  	}  } -static inline void start_tx_rs485(struct uart_port *port) +/** + * serial8250_em485_start_tx() - generic ->rs485_start_tx() callback + * @up: uart 8250 port + * + * Generic callback usable by 8250 uart drivers to start rs485 transmission. + * Assumes that setting the RTS bit in the MCR register means RTS is high. + * (Some chips use inverse semantics.)  Further assumes that reception is + * stoppable by disabling the UART_IER_RDI interrupt.  (Some chips set the + * UART_LSR_DR bit even when UART_IER_RDI is disabled, foiling this approach.) + */ +void serial8250_em485_start_tx(struct uart_8250_port *up)  { -	struct uart_8250_port *up = up_to_u8250p(port); -	struct uart_8250_em485 *em485 = up->em485; -	unsigned char mcr; +	unsigned char mcr = serial8250_in_MCR(up);  	if (!(up->port.rs485.flags & SER_RS485_RX_DURING_TX))  		serial8250_stop_rx(&up->port); +	if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) +		mcr |= UART_MCR_RTS; +	else +		mcr &= ~UART_MCR_RTS; +	serial8250_out_MCR(up, mcr); +} +EXPORT_SYMBOL_GPL(serial8250_em485_start_tx); + +static inline void start_tx_rs485(struct uart_port *port) +{ +	struct uart_8250_port *up = up_to_u8250p(port); +	struct uart_8250_em485 *em485 = up->em485; +  	em485->active_timer = NULL; -	mcr = serial8250_in_MCR(up); -	if (!!(up->port.rs485.flags & SER_RS485_RTS_ON_SEND) != -	    !!(mcr & UART_MCR_RTS)) { -		if (up->port.rs485.flags & SER_RS485_RTS_ON_SEND) -			mcr |= UART_MCR_RTS; -		else -			mcr &= ~UART_MCR_RTS; -		serial8250_out_MCR(up, mcr); +	if (em485->tx_stopped) { +		em485->tx_stopped = false; + +		up->rs485_start_tx(up);  		if (up->port.rs485.delay_rts_before_send > 0) {  			em485->active_timer = &em485->start_tx_timer; @@ -1683,7 +1751,7 @@ void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr)  		lsr &= port->read_status_mask;  		if (lsr & UART_LSR_BI) { -			pr_debug("%s: handling break\n", __func__); +			dev_dbg(port->dev, "handling break\n");  			flag = TTY_BREAK;  		} else if (lsr & UART_LSR_PE)  			flag = TTY_PARITY; @@ -1815,6 +1883,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)  	unsigned char status;  	unsigned long flags;  	struct uart_8250_port *up = up_to_u8250p(port); +	bool skip_rx = false;  	if (iir & UART_IIR_NO_INT)  		return 0; @@ -1823,7 +1892,20 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)  	status = serial_port_in(port, UART_LSR); -	if (status & (UART_LSR_DR | UART_LSR_BI)) { +	/* +	 * If port is stopped and there are no error conditions in the +	 * FIFO, then don't drain the FIFO, as this may lead to TTY buffer +	 * overflow. Not servicing, RX FIFO would trigger auto HW flow +	 * control when FIFO occupancy reaches preset threshold, thus +	 * halting RX. This only works when auto HW flow control is +	 * available. +	 */ +	if (!(status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) && +	    (port->status & (UPSTAT_AUTOCTS | UPSTAT_AUTORTS)) && +	    !(port->read_status_mask & UART_LSR_DR)) +		skip_rx = true; + +	if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) {  		if (!up->dma || handle_rx_dma(up, iir))  			status = serial8250_rx_chars(up, status);  	} @@ -1924,6 +2006,13 @@ void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)  	struct uart_8250_port *up = up_to_u8250p(port);  	unsigned char mcr; +	if (port->rs485.flags & SER_RS485_ENABLED) { +		if (serial8250_in_MCR(up) & UART_MCR_RTS) +			mctrl |= TIOCM_RTS; +		else +			mctrl &= ~TIOCM_RTS; +	} +  	mcr = serial8250_TIOCM_to_MCR(mctrl);  	mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr; @@ -2134,7 +2223,7 @@ int serial8250_do_startup(struct uart_port *port)  	 */  	if (!(port->flags & UPF_BUGGY_UART) &&  	    (serial_port_in(port, UART_LSR) == 0xff)) { -		pr_info_ratelimited("%s: LSR safety check engaged!\n", port->name); +		dev_info_ratelimited(port->dev, "LSR safety check engaged!\n");  		retval = -ENODEV;  		goto out;  	} @@ -2166,8 +2255,7 @@ int serial8250_do_startup(struct uart_port *port)  	     (port->type == PORT_ALTR_16550_F128)) && (port->fifosize > 1)) {  		/* Bounds checking of TX threshold (valid 0 to fifosize-2) */  		if ((up->tx_loadsz < 2) || (up->tx_loadsz > port->fifosize)) { -			pr_err("%s TX FIFO Threshold errors, skipping\n", -			       port->name); +			dev_err(port->dev, "TX FIFO Threshold errors, skipping\n");  		} else {  			serial_port_out(port, UART_ALTR_AFR,  					UART_ALTR_EN_TXFIFO_LW); @@ -2268,8 +2356,7 @@ int serial8250_do_startup(struct uart_port *port)  	if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {  		if (!(up->bugs & UART_BUG_TXEN)) {  			up->bugs |= UART_BUG_TXEN; -			pr_debug("%s - enabling bad tx status workarounds\n", -				 port->name); +			dev_dbg(port->dev, "enabling bad tx status workarounds\n");  		}  	} else {  		up->bugs &= ~UART_BUG_TXEN; @@ -2294,10 +2381,14 @@ dont_test_tx_en:  	 * Request DMA channels for both RX and TX.  	 */  	if (up->dma) { -		retval = serial8250_request_dma(up); -		if (retval) { -			pr_warn_ratelimited("%s - failed to request DMA\n", -					    port->name); +		const char *msg = NULL; + +		if (uart_console(port)) +			msg = "forbid DMA for kernel console"; +		else if (serial8250_request_dma(up)) +			msg = "failed to request DMA"; +		if (msg) { +			dev_warn_ratelimited(port->dev, "%s\n", msg);  			up->dma = NULL;  		}  	} @@ -2880,7 +2971,7 @@ static int do_serial8250_get_rxtrig(struct tty_port *port)  	return rxtrig_bytes;  } -static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev, +static ssize_t rx_trig_bytes_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct tty_port *port = dev_get_drvdata(dev); @@ -2926,7 +3017,7 @@ static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes)  	return ret;  } -static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev, +static ssize_t rx_trig_bytes_store(struct device *dev,  	struct device_attribute *attr, const char *buf, size_t count)  {  	struct tty_port *port = dev_get_drvdata(dev); @@ -2947,18 +3038,16 @@ static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev,  	return count;  } -static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP, -		   serial8250_get_attr_rx_trig_bytes, -		   serial8250_set_attr_rx_trig_bytes); +static DEVICE_ATTR_RW(rx_trig_bytes);  static struct attribute *serial8250_dev_attrs[] = {  	&dev_attr_rx_trig_bytes.attr, -	NULL, -	}; +	NULL +};  static struct attribute_group serial8250_dev_attr_group = {  	.attrs = serial8250_dev_attrs, -	}; +};  static void register_dev_spec_attr_grp(struct uart_8250_port *up)  { @@ -2987,6 +3076,9 @@ static void serial8250_config_port(struct uart_port *port, int flags)  	if (flags & UART_CONFIG_TYPE)  		autoconfig(up); +	if (port->rs485.flags & SER_RS485_ENABLED) +		port->rs485_config(port, &port->rs485); +  	/* if access method is AU, it is a 16550 with a quirk */  	if (port->type == PORT_16550A && port->iotype == UPIO_AU)  		up->bugs |= UART_BUG_NOMSR; @@ -3127,10 +3219,14 @@ static void serial8250_console_restore(struct uart_8250_port *up)   *	any possible real use of the port...   *   *	The console_lock must be held when we get here. + * + *	Doing runtime PM is really a bad idea for the kernel console. + *	Thus, we assume the function is called when device is powered up.   */  void serial8250_console_write(struct uart_8250_port *up, const char *s,  			      unsigned int count)  { +	struct uart_8250_em485 *em485 = up->em485;  	struct uart_port *port = &up->port;  	unsigned long flags;  	unsigned int ier; @@ -3138,8 +3234,6 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,  	touch_nmi_watchdog(); -	serial8250_rpm_get(up); -  	if (oops_in_progress)  		locked = spin_trylock_irqsave(&port->lock, flags);  	else @@ -3161,6 +3255,12 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,  		up->canary = 0;  	} +	if (em485) { +		if (em485->tx_stopped) +			up->rs485_start_tx(up); +		mdelay(port->rs485.delay_rts_before_send); +	} +  	uart_console_write(port, s, count, serial8250_console_putchar);  	/* @@ -3168,6 +3268,13 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,  	 *	and restore the IER  	 */  	wait_for_xmitr(up, BOTH_EMPTY); + +	if (em485) { +		mdelay(port->rs485.delay_rts_after_send); +		if (em485->tx_stopped) +			up->rs485_stop_tx(up); +	} +  	serial_port_out(port, UART_IER, ier);  	/* @@ -3182,7 +3289,6 @@ void serial8250_console_write(struct uart_8250_port *up, const char *s,  	if (locked)  		spin_unlock_irqrestore(&port->lock, flags); -	serial8250_rpm_put(up);  }  static unsigned int probe_baud(struct uart_port *port) @@ -3206,6 +3312,7 @@ int serial8250_console_setup(struct uart_port *port, char *options, bool probe)  	int bits = 8;  	int parity = 'n';  	int flow = 'n'; +	int ret;  	if (!port->iobase && !port->membase)  		return -ENODEV; @@ -3215,7 +3322,22 @@ int serial8250_console_setup(struct uart_port *port, char *options, bool probe)  	else if (probe)  		baud = probe_baud(port); -	return uart_set_options(port, port->cons, baud, parity, bits, flow); +	ret = uart_set_options(port, port->cons, baud, parity, bits, flow); +	if (ret) +		return ret; + +	if (port->dev) +		pm_runtime_get_sync(port->dev); + +	return 0; +} + +int serial8250_console_exit(struct uart_port *port) +{ +	if (port->dev) +		pm_runtime_put_sync(port->dev); + +	return 0;  }  #endif /* CONFIG_SERIAL_8250_CONSOLE */ diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c index c47188860e32..11612d174716 100644 --- a/drivers/tty/serial/8250/8250_pxa.c +++ b/drivers/tty/serial/8250/8250_pxa.c @@ -123,7 +123,7 @@ static int serial_pxa_probe(struct platform_device *pdev)  	uart.port.regshift = 2;  	uart.port.irq = irqres->start;  	uart.port.fifosize = 64; -	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST; +	uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE;  	uart.port.dev = &pdev->dev;  	uart.port.uartclk = clk_get_rate(data->clk);  	uart.port.pm = serial_pxa_pm; diff --git a/drivers/tty/serial/8250/8250_tegra.c b/drivers/tty/serial/8250/8250_tegra.c new file mode 100644 index 000000000000..c0ffad1572c6 --- /dev/null +++ b/drivers/tty/serial/8250/8250_tegra.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + *  Serial Port driver for Tegra devices + * + *  Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved. + */ + +#include <linux/acpi.h> +#include <linux/clk.h> +#include <linux/console.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/reset.h> +#include <linux/slab.h> + +#include "8250.h" + +struct tegra_uart { +	struct clk *clk; +	struct reset_control *rst; +	int line; +}; + +static void tegra_uart_handle_break(struct uart_port *p) +{ +	unsigned int status, tmout = 10000; + +	do { +		status = p->serial_in(p, UART_LSR); +		if (status & (UART_LSR_FIFOE | UART_LSR_BRK_ERROR_BITS)) +			status = p->serial_in(p, UART_RX); +		else +			break; +		if (--tmout == 0) +			break; +		udelay(1); +	} while (1); +} + +static int tegra_uart_probe(struct platform_device *pdev) +{ +	struct uart_8250_port port8250; +	struct tegra_uart *uart; +	struct uart_port *port; +	struct resource *res; +	int ret; + +	uart = devm_kzalloc(&pdev->dev, sizeof(*uart), GFP_KERNEL); +	if (!uart) +		return -ENOMEM; + +	memset(&port8250, 0, sizeof(port8250)); + +	port = &port8250.port; +	spin_lock_init(&port->lock); + +	port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | +		      UPF_FIXED_TYPE; +	port->iotype = UPIO_MEM32; +	port->regshift = 2; +	port->type = PORT_TEGRA; +	port->irqflags |= IRQF_SHARED; +	port->dev = &pdev->dev; +	port->handle_break = tegra_uart_handle_break; + +	ret = of_alias_get_id(pdev->dev.of_node, "serial"); +	if (ret >= 0) +		port->line = ret; + +	ret = platform_get_irq(pdev, 0); +	if (ret < 0) +		return ret; + +	port->irq = ret; + +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	if (!res) +		return -ENODEV; + +	port->membase = devm_ioremap(&pdev->dev, res->start, +				     resource_size(res)); +	if (!port->membase) +		return -ENOMEM; + +	port->mapbase = res->start; +	port->mapsize = resource_size(res); + +	uart->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL); +	if (IS_ERR(uart->rst)) +		return PTR_ERR(uart->rst); + +	if (device_property_read_u32(&pdev->dev, "clock-frequency", +				     &port->uartclk)) { +		uart->clk = devm_clk_get(&pdev->dev, NULL); +		if (IS_ERR(uart->clk)) { +			dev_err(&pdev->dev, "failed to get clock!\n"); +			return -ENODEV; +		} + +		ret = clk_prepare_enable(uart->clk); +		if (ret < 0) +			return ret; + +		port->uartclk = clk_get_rate(uart->clk); +	} + +	ret = reset_control_deassert(uart->rst); +	if (ret) +		goto err_clkdisable; + +	ret = serial8250_register_8250_port(&port8250); +	if (ret < 0) +		goto err_clkdisable; + +	platform_set_drvdata(pdev, uart); +	uart->line = ret; + +	return 0; + +err_clkdisable: +	clk_disable_unprepare(uart->clk); + +	return ret; +} + +static int tegra_uart_remove(struct platform_device *pdev) +{ +	struct tegra_uart *uart = platform_get_drvdata(pdev); + +	serial8250_unregister_port(uart->line); +	reset_control_assert(uart->rst); +	clk_disable_unprepare(uart->clk); + +	return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int tegra_uart_suspend(struct device *dev) +{ +	struct tegra_uart *uart = dev_get_drvdata(dev); +	struct uart_8250_port *port8250 = serial8250_get_port(uart->line); +	struct uart_port *port = &port8250->port; + +	serial8250_suspend_port(uart->line); + +	if (!uart_console(port) || console_suspend_enabled) +		clk_disable_unprepare(uart->clk); + +	return 0; +} + +static int tegra_uart_resume(struct device *dev) +{ +	struct tegra_uart *uart = dev_get_drvdata(dev); +	struct uart_8250_port *port8250 = serial8250_get_port(uart->line); +	struct uart_port *port = &port8250->port; + +	if (!uart_console(port) || console_suspend_enabled) +		clk_prepare_enable(uart->clk); + +	serial8250_resume_port(uart->line); + +	return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(tegra_uart_pm_ops, tegra_uart_suspend, +			 tegra_uart_resume); + +static const struct of_device_id tegra_uart_of_match[] = { +	{ .compatible = "nvidia,tegra20-uart", }, +	{ }, +}; +MODULE_DEVICE_TABLE(of, tegra_uart_of_match); + +static const struct acpi_device_id tegra_uart_acpi_match[] = { +	{ "NVDA0100", 0 }, +	{ }, +}; +MODULE_DEVICE_TABLE(acpi, tegra_uart_acpi_match); + +static struct platform_driver tegra_uart_driver = { +	.driver = { +		.name = "tegra-uart", +		.pm = &tegra_uart_pm_ops, +		.of_match_table = tegra_uart_of_match, +		.acpi_match_table = ACPI_PTR(tegra_uart_acpi_match), +	}, +	.probe = tegra_uart_probe, +	.remove = tegra_uart_remove, +}; + +module_platform_driver(tegra_uart_driver); + +MODULE_AUTHOR("Jeff Brasen <[email protected]>"); +MODULE_DESCRIPTION("NVIDIA Tegra 8250 Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index f16824bbb573..af0688156dd0 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -500,6 +500,15 @@ config SERIAL_8250_PXA  	  applicable to both devicetree and legacy boards, and early console is  	  part of its support. +config SERIAL_8250_TEGRA +	tristate "8250 support for Tegra serial ports" +	default SERIAL_8250 +	depends on SERIAL_8250 +	depends on ARCH_TEGRA || COMPILE_TEST +	help +	  Select this option if you have machine with an NVIDIA Tegra SoC and +	  wish to enable 8250 serial driver for the Tegra serial interfaces. +  config SERIAL_OF_PLATFORM  	tristate "Devicetree based probing for 8250 ports"  	depends on SERIAL_8250 && OF diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 51a6079d3f1f..a8bfb654d490 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_SERIAL_8250_INGENIC)	+= 8250_ingenic.o  obj-$(CONFIG_SERIAL_8250_LPSS)		+= 8250_lpss.o  obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o  obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o +obj-$(CONFIG_SERIAL_8250_TEGRA)		+= 8250_tegra.o  obj-$(CONFIG_SERIAL_OF_PLATFORM)	+= 8250_of.o  CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 52eaac21ff9f..adf9e80e7dc9 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -3,8 +3,6 @@  # Serial device configuration  # -if TTY -  menu "Serial drivers"  	depends on HAS_IOMEM @@ -88,7 +86,7 @@ config SERIAL_EARLYCON_ARM_SEMIHOST  config SERIAL_EARLYCON_RISCV_SBI  	bool "Early console using RISC-V SBI" -	depends on RISCV_SBI +	depends on RISCV_SBI_V01  	select SERIAL_CORE  	select SERIAL_CORE_CONSOLE  	select SERIAL_EARLYCON @@ -260,15 +258,6 @@ config SERIAL_SAMSUNG_UARTS  	help  	  Select the number of available UART ports for the Samsung S3C  	  serial driver -	 -config SERIAL_SAMSUNG_DEBUG -	bool "Samsung SoC serial debug" -	depends on SERIAL_SAMSUNG && DEBUG_LL -	help -	  Add support for debugging the serial driver. Since this is -	  generally being used as a console, we use our own output -	  routines that go via the low-level debug printascii() -	  function.  config SERIAL_SAMSUNG_CONSOLE  	bool "Support for console on Samsung SoC serial port" @@ -1111,7 +1100,7 @@ config SERIAL_SC16IS7XX_SPI  	help  	  Enable SC16IS7xx driver on SPI bus,  	  If required say y, and say n to spi if not required, -	  This is additional support to exsisting driver. +	  This is additional support to existing driver.  	  You must select at least one bus for the driver to be built.  config SERIAL_TIMBERDALE @@ -1279,6 +1268,7 @@ config SERIAL_AR933X  	tristate "AR933X serial port support"  	depends on HAVE_CLK && ATH79  	select SERIAL_CORE +	select SERIAL_MCTRL_GPIO if GPIOLIB  	help  	  If you have an Atheros AR933X SOC based board and want to use the  	  built-in UART of the SoC, say Y to this option. @@ -1452,8 +1442,8 @@ config SERIAL_MEN_Z135  config SERIAL_SPRD  	tristate "Support for Spreadtrum serial" -	depends on ARCH_SPRD  	select SERIAL_CORE +	depends on COMMON_CLK  	help  	  This enables the driver for the Spreadtrum's serial. @@ -1576,5 +1566,3 @@ endmenu  config SERIAL_MCTRL_GPIO  	tristate - -endif # TTY diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c index ea12f10610b6..7e7f1398019f 100644 --- a/drivers/tty/serial/ar933x_uart.c +++ b/drivers/tty/serial/ar933x_uart.c @@ -13,6 +13,7 @@  #include <linux/console.h>  #include <linux/sysrq.h>  #include <linux/delay.h> +#include <linux/gpio/consumer.h>  #include <linux/platform_device.h>  #include <linux/of.h>  #include <linux/of_platform.h> @@ -29,6 +30,8 @@  #include <asm/mach-ath79/ar933x_uart.h> +#include "serial_mctrl_gpio.h" +  #define DRIVER_NAME "ar933x-uart"  #define AR933X_UART_MAX_SCALE	0xff @@ -47,6 +50,8 @@ struct ar933x_uart_port {  	unsigned int		min_baud;  	unsigned int		max_baud;  	struct clk		*clk; +	struct mctrl_gpios	*gpios; +	struct gpio_desc	*rts_gpiod;  };  static inline unsigned int ar933x_uart_read(struct ar933x_uart_port *up, @@ -100,6 +105,18 @@ static inline void ar933x_uart_stop_tx_interrupt(struct ar933x_uart_port *up)  	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier);  } +static inline void ar933x_uart_start_rx_interrupt(struct ar933x_uart_port *up) +{ +	up->ier |= AR933X_UART_INT_RX_VALID; +	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier); +} + +static inline void ar933x_uart_stop_rx_interrupt(struct ar933x_uart_port *up) +{ +	up->ier &= ~AR933X_UART_INT_RX_VALID; +	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier); +} +  static inline void ar933x_uart_putc(struct ar933x_uart_port *up, int ch)  {  	unsigned int rdata; @@ -125,11 +142,21 @@ static unsigned int ar933x_uart_tx_empty(struct uart_port *port)  static unsigned int ar933x_uart_get_mctrl(struct uart_port *port)  { -	return TIOCM_CAR; +	struct ar933x_uart_port *up = +		container_of(port, struct ar933x_uart_port, port); +	int ret = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + +	mctrl_gpio_get(up->gpios, &ret); + +	return ret;  }  static void ar933x_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)  { +	struct ar933x_uart_port *up = +		container_of(port, struct ar933x_uart_port, port); + +	mctrl_gpio_set(up->gpios, mctrl);  }  static void ar933x_uart_start_tx(struct uart_port *port) @@ -140,6 +167,37 @@ static void ar933x_uart_start_tx(struct uart_port *port)  	ar933x_uart_start_tx_interrupt(up);  } +static void ar933x_uart_wait_tx_complete(struct ar933x_uart_port *up) +{ +	unsigned int status; +	unsigned int timeout = 60000; + +	/* Wait up to 60ms for the character(s) to be sent. */ +	do { +		status = ar933x_uart_read(up, AR933X_UART_CS_REG); +		if (--timeout == 0) +			break; +		udelay(1); +	} while (status & AR933X_UART_CS_TX_BUSY); + +	if (timeout == 0) +		dev_err(up->port.dev, "waiting for TX timed out\n"); +} + +static void ar933x_uart_rx_flush(struct ar933x_uart_port *up) +{ +	unsigned int status; + +	/* clear RX_VALID interrupt */ +	ar933x_uart_write(up, AR933X_UART_INT_REG, AR933X_UART_INT_RX_VALID); + +	/* remove characters from the RX FIFO */ +	do { +		ar933x_uart_write(up, AR933X_UART_DATA_REG, AR933X_UART_DATA_RX_CSR); +		status = ar933x_uart_read(up, AR933X_UART_DATA_REG); +	} while (status & AR933X_UART_DATA_RX_CSR); +} +  static void ar933x_uart_stop_tx(struct uart_port *port)  {  	struct ar933x_uart_port *up = @@ -153,8 +211,7 @@ static void ar933x_uart_stop_rx(struct uart_port *port)  	struct ar933x_uart_port *up =  		container_of(port, struct ar933x_uart_port, port); -	up->ier &= ~AR933X_UART_INT_RX_VALID; -	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier); +	ar933x_uart_stop_rx_interrupt(up);  }  static void ar933x_uart_break_ctl(struct uart_port *port, int break_state) @@ -336,11 +393,20 @@ static void ar933x_uart_rx_chars(struct ar933x_uart_port *up)  static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)  {  	struct circ_buf *xmit = &up->port.state->xmit; +	struct serial_rs485 *rs485conf = &up->port.rs485;  	int count; +	bool half_duplex_send = false;  	if (uart_tx_stopped(&up->port))  		return; +	if ((rs485conf->flags & SER_RS485_ENABLED) && +	    (up->port.x_char || !uart_circ_empty(xmit))) { +		ar933x_uart_stop_rx_interrupt(up); +		gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_ON_SEND)); +		half_duplex_send = true; +	} +  	count = up->port.fifosize;  	do {  		unsigned int rdata; @@ -368,8 +434,14 @@ static void ar933x_uart_tx_chars(struct ar933x_uart_port *up)  	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)  		uart_write_wakeup(&up->port); -	if (!uart_circ_empty(xmit)) +	if (!uart_circ_empty(xmit)) {  		ar933x_uart_start_tx_interrupt(up); +	} else if (half_duplex_send) { +		ar933x_uart_wait_tx_complete(up); +		ar933x_uart_rx_flush(up); +		ar933x_uart_start_rx_interrupt(up); +		gpiod_set_value(up->rts_gpiod, !!(rs485conf->flags & SER_RS485_RTS_AFTER_SEND)); +	}  }  static irqreturn_t ar933x_uart_interrupt(int irq, void *dev_id) @@ -427,8 +499,7 @@ static int ar933x_uart_startup(struct uart_port *port)  		AR933X_UART_CS_TX_READY_ORIDE | AR933X_UART_CS_RX_READY_ORIDE);  	/* Enable RX interrupts */ -	up->ier = AR933X_UART_INT_RX_VALID; -	ar933x_uart_write(up, AR933X_UART_INT_EN_REG, up->ier); +	ar933x_uart_start_rx_interrupt(up);  	spin_unlock_irqrestore(&up->port.lock, flags); @@ -511,6 +582,21 @@ static const struct uart_ops ar933x_uart_ops = {  	.verify_port	= ar933x_uart_verify_port,  }; +static int ar933x_config_rs485(struct uart_port *port, +				struct serial_rs485 *rs485conf) +{ +	struct ar933x_uart_port *up = +		container_of(port, struct ar933x_uart_port, port); + +	if ((rs485conf->flags & SER_RS485_ENABLED) && +	    !up->rts_gpiod) { +		dev_err(port->dev, "RS485 needs rts-gpio\n"); +		return 1; +	} +	port->rs485 = *rs485conf; +	return 0; +} +  #ifdef CONFIG_SERIAL_AR933X_CONSOLE  static struct ar933x_uart_port *  ar933x_console_ports[CONFIG_SERIAL_AR933X_NR_UARTS]; @@ -680,6 +766,8 @@ static int ar933x_uart_probe(struct platform_device *pdev)  		goto err_disable_clk;  	} +	uart_get_rs485_mode(&pdev->dev, &port->rs485); +  	port->mapbase = mem_res->start;  	port->line = id;  	port->irq = irq_res->start; @@ -690,6 +778,7 @@ static int ar933x_uart_probe(struct platform_device *pdev)  	port->regshift = 2;  	port->fifosize = AR933X_UART_FIFO_SIZE;  	port->ops = &ar933x_uart_ops; +	port->rs485_config = ar933x_config_rs485;  	baud = ar933x_uart_get_baud(port->uartclk, AR933X_UART_MAX_SCALE, 1);  	up->min_baud = max_t(unsigned int, baud, AR933X_UART_MIN_BAUD); @@ -697,6 +786,18 @@ static int ar933x_uart_probe(struct platform_device *pdev)  	baud = ar933x_uart_get_baud(port->uartclk, 0, AR933X_UART_MAX_STEP);  	up->max_baud = min_t(unsigned int, baud, AR933X_UART_MAX_BAUD); +	up->gpios = mctrl_gpio_init(port, 0); +	if (IS_ERR(up->gpios) && PTR_ERR(up->gpios) != -ENOSYS) +		return PTR_ERR(up->gpios); + +	up->rts_gpiod = mctrl_gpio_to_gpiod(up->gpios, UART_GPIO_RTS); + +	if ((port->rs485.flags & SER_RS485_ENABLED) && +	    !up->rts_gpiod) { +		dev_err(&pdev->dev, "lacking rts-gpio, disabling RS485\n"); +		port->rs485.flags &= ~SER_RS485_ENABLED; +	} +  #ifdef CONFIG_SERIAL_AR933X_CONSOLE  	ar933x_console_ports[up->port.line] = up;  #endif diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index a39c87a7c2e1..8d7080efad9b 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -20,15 +20,12 @@  #include <linux/platform_device.h>  #include <linux/of.h>  #include <linux/of_device.h> -#include <linux/of_gpio.h>  #include <linux/dma-mapping.h>  #include <linux/dmaengine.h>  #include <linux/atmel_pdc.h>  #include <linux/uaccess.h>  #include <linux/platform_data/atmel.h>  #include <linux/timer.h> -#include <linux/gpio.h> -#include <linux/gpio/consumer.h>  #include <linux/err.h>  #include <linux/irq.h>  #include <linux/suspend.h> @@ -2679,18 +2676,8 @@ static struct console atmel_console = {  #define ATMEL_CONSOLE_DEVICE	(&atmel_console) -static inline bool atmel_is_console_port(struct uart_port *port) -{ -	return port->cons && port->cons->index == port->line; -} -  #else  #define ATMEL_CONSOLE_DEVICE	NULL - -static inline bool atmel_is_console_port(struct uart_port *port) -{ -	return false; -}  #endif  static struct uart_driver atmel_uart = { @@ -2719,14 +2706,14 @@ static int atmel_serial_suspend(struct platform_device *pdev,  	struct uart_port *port = platform_get_drvdata(pdev);  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); -	if (atmel_is_console_port(port) && console_suspend_enabled) { +	if (uart_console(port) && console_suspend_enabled) {  		/* Drain the TX shifter */  		while (!(atmel_uart_readl(port, ATMEL_US_CSR) &  			 ATMEL_US_TXEMPTY))  			cpu_relax();  	} -	if (atmel_is_console_port(port) && !console_suspend_enabled) { +	if (uart_console(port) && !console_suspend_enabled) {  		/* Cache register values as we won't get a full shutdown/startup  		 * cycle  		 */ @@ -2762,7 +2749,7 @@ static int atmel_serial_resume(struct platform_device *pdev)  	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);  	unsigned long flags; -	if (atmel_is_console_port(port) && !console_suspend_enabled) { +	if (uart_console(port) && !console_suspend_enabled) {  		atmel_uart_writel(port, ATMEL_US_MR, atmel_port->cache.mr);  		atmel_uart_writel(port, ATMEL_US_IER, atmel_port->cache.imr);  		atmel_uart_writel(port, ATMEL_US_BRGR, atmel_port->cache.brgr); @@ -2916,7 +2903,7 @@ static int atmel_serial_probe(struct platform_device *pdev)  		goto err_add_port;  #ifdef CONFIG_SERIAL_ATMEL_CONSOLE -	if (atmel_is_console_port(&atmel_port->uart) +	if (uart_console(&atmel_port->uart)  			&& ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) {  		/*  		 * The serial core enabled the clock for us, so undo @@ -2959,7 +2946,7 @@ err_add_port:  	kfree(atmel_port->rx_ring.buf);  	atmel_port->rx_ring.buf = NULL;  err_alloc_ring: -	if (!atmel_is_console_port(&atmel_port->uart)) { +	if (!uart_console(&atmel_port->uart)) {  		clk_put(atmel_port->clk);  		atmel_port->clk = NULL;  	} diff --git a/drivers/tty/serial/atmel_serial.h b/drivers/tty/serial/atmel_serial.h index d811d4f2d0c0..0d8a0f9cc5c3 100644 --- a/drivers/tty/serial/atmel_serial.h +++ b/drivers/tty/serial/atmel_serial.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */  /*   * include/linux/atmel_serial.h   * diff --git a/drivers/tty/serial/cpm_uart/cpm_uart.h b/drivers/tty/serial/cpm_uart/cpm_uart.h index 9f175a92fb5d..6113b953ce25 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart.h +++ b/drivers/tty/serial/cpm_uart/cpm_uart.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */  /*   *  Driver for CPM (SCC/SMC) serial ports   * @@ -13,6 +13,8 @@  #include <linux/platform_device.h>  #include <linux/fs_uart_pd.h> +struct gpio_desc; +  #if defined(CONFIG_CPM2)  #include "cpm_uart_cpm2.h"  #elif defined(CONFIG_CPM1) @@ -80,7 +82,7 @@ struct uart_cpm_port {  	int			wait_closing;  	/* value to combine with opcode to form cpm command */  	u32			command; -	int			gpios[NUM_GPIOS]; +	struct gpio_desc	*gpios[NUM_GPIOS];  };  extern int cpm_uart_nr; diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c index d4b81b06e0cb..a04f74d2e854 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c @@ -30,8 +30,7 @@  #include <linux/of_address.h>  #include <linux/of_irq.h>  #include <linux/of_platform.h> -#include <linux/gpio.h> -#include <linux/of_gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/clk.h>  #include <asm/io.h> @@ -88,11 +87,11 @@ static void cpm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)  	struct uart_cpm_port *pinfo =  		container_of(port, struct uart_cpm_port, port); -	if (pinfo->gpios[GPIO_RTS] >= 0) -		gpio_set_value(pinfo->gpios[GPIO_RTS], !(mctrl & TIOCM_RTS)); +	if (pinfo->gpios[GPIO_RTS]) +		gpiod_set_value(pinfo->gpios[GPIO_RTS], !(mctrl & TIOCM_RTS)); -	if (pinfo->gpios[GPIO_DTR] >= 0) -		gpio_set_value(pinfo->gpios[GPIO_DTR], !(mctrl & TIOCM_DTR)); +	if (pinfo->gpios[GPIO_DTR]) +		gpiod_set_value(pinfo->gpios[GPIO_DTR], !(mctrl & TIOCM_DTR));  }  static unsigned int cpm_uart_get_mctrl(struct uart_port *port) @@ -101,23 +100,23 @@ static unsigned int cpm_uart_get_mctrl(struct uart_port *port)  		container_of(port, struct uart_cpm_port, port);  	unsigned int mctrl = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; -	if (pinfo->gpios[GPIO_CTS] >= 0) { -		if (gpio_get_value(pinfo->gpios[GPIO_CTS])) +	if (pinfo->gpios[GPIO_CTS]) { +		if (gpiod_get_value(pinfo->gpios[GPIO_CTS]))  			mctrl &= ~TIOCM_CTS;  	} -	if (pinfo->gpios[GPIO_DSR] >= 0) { -		if (gpio_get_value(pinfo->gpios[GPIO_DSR])) +	if (pinfo->gpios[GPIO_DSR]) { +		if (gpiod_get_value(pinfo->gpios[GPIO_DSR]))  			mctrl &= ~TIOCM_DSR;  	} -	if (pinfo->gpios[GPIO_DCD] >= 0) { -		if (gpio_get_value(pinfo->gpios[GPIO_DCD])) +	if (pinfo->gpios[GPIO_DCD]) { +		if (gpiod_get_value(pinfo->gpios[GPIO_DCD]))  			mctrl &= ~TIOCM_CAR;  	} -	if (pinfo->gpios[GPIO_RI] >= 0) { -		if (!gpio_get_value(pinfo->gpios[GPIO_RI])) +	if (pinfo->gpios[GPIO_RI]) { +		if (!gpiod_get_value(pinfo->gpios[GPIO_RI]))  			mctrl |= TIOCM_RNG;  	} @@ -1139,6 +1138,7 @@ static int cpm_uart_init_port(struct device_node *np,  {  	const u32 *data;  	void __iomem *mem, *pram; +	struct device *dev = pinfo->port.dev;  	int len;  	int ret;  	int i; @@ -1211,29 +1211,23 @@ static int cpm_uart_init_port(struct device_node *np,  	}  	for (i = 0; i < NUM_GPIOS; i++) { -		int gpio; +		struct gpio_desc *gpiod; -		pinfo->gpios[i] = -1; +		pinfo->gpios[i] = NULL; -		gpio = of_get_gpio(np, i); +		gpiod = devm_gpiod_get_index(dev, NULL, i, GPIOD_ASIS); -		if (gpio_is_valid(gpio)) { -			ret = gpio_request(gpio, "cpm_uart"); -			if (ret) { -				pr_err("can't request gpio #%d: %d\n", i, ret); -				continue; -			} +		if (gpiod) {  			if (i == GPIO_RTS || i == GPIO_DTR) -				ret = gpio_direction_output(gpio, 0); +				ret = gpiod_direction_output(gpiod, 0);  			else -				ret = gpio_direction_input(gpio); +				ret = gpiod_direction_input(gpiod);  			if (ret) {  				pr_err("can't set direction for gpio #%d: %d\n",  					i, ret); -				gpio_free(gpio);  				continue;  			} -			pinfo->gpios[i] = gpio; +			pinfo->gpios[i] = gpiod;  		}  	} diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index c14873b67803..2ae9190b64bb 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -170,6 +170,7 @@ static int __init register_earlycon(char *buf, const struct earlycon_id *match)  int __init setup_earlycon(char *buf)  {  	const struct earlycon_id **p_match; +	bool empty_compatible = true;  	if (!buf || !buf[0])  		return -EINVAL; @@ -177,6 +178,7 @@ int __init setup_earlycon(char *buf)  	if (early_con.flags & CON_ENABLED)  		return -EALREADY; +again:  	for (p_match = __earlycon_table; p_match < __earlycon_table_end;  	     p_match++) {  		const struct earlycon_id *match = *p_match; @@ -185,6 +187,10 @@ int __init setup_earlycon(char *buf)  		if (strncmp(buf, match->name, len))  			continue; +		/* prefer entries with empty compatible */ +		if (empty_compatible && *match->compatible) +			continue; +  		if (buf[len]) {  			if (buf[len] != ',')  				continue; @@ -195,6 +201,11 @@ int __init setup_earlycon(char *buf)  		return register_earlycon(buf, match);  	} +	if (empty_compatible) { +		empty_compatible = false; +		goto again; +	} +  	return -ENOENT;  } diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index 2ac87128d7fd..f12f29cf4f31 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c @@ -200,7 +200,7 @@ static void efm32_uart_rx_chars(struct efm32_uart_port *efm_port)  		/*  		 * This is a reserved bit and I only saw it read as 0. But to be  		 * sure not to be confused too much by new devices adhere to the -		 * warning in the reference manual that reserverd bits might +		 * warning in the reference manual that reserved bits might  		 * read as 1 in the future.  		 */  		rxdata &= ~SW_UARTn_RXDATAX_BERR; diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index c31b8f3db6bf..5d41075964f2 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -234,6 +234,7 @@ static DEFINE_IDA(fsl_lpuart_ida);  enum lpuart_type {  	VF610_LPUART,  	LS1021A_LPUART, +	LS1028A_LPUART,  	IMX7ULP_LPUART,  	IMX8QXP_LPUART,  }; @@ -278,11 +279,16 @@ static const struct lpuart_soc_data vf_data = {  	.iotype = UPIO_MEM,  }; -static const struct lpuart_soc_data ls_data = { +static const struct lpuart_soc_data ls1021a_data = {  	.devtype = LS1021A_LPUART,  	.iotype = UPIO_MEM32BE,  }; +static const struct lpuart_soc_data ls1028a_data = { +	.devtype = LS1028A_LPUART, +	.iotype = UPIO_MEM32, +}; +  static struct lpuart_soc_data imx7ulp_data = {  	.devtype = IMX7ULP_LPUART,  	.iotype = UPIO_MEM32, @@ -297,7 +303,8 @@ static struct lpuart_soc_data imx8qxp_data = {  static const struct of_device_id lpuart_dt_ids[] = {  	{ .compatible = "fsl,vf610-lpuart",	.data = &vf_data, }, -	{ .compatible = "fsl,ls1021a-lpuart",	.data = &ls_data, }, +	{ .compatible = "fsl,ls1021a-lpuart",	.data = &ls1021a_data, }, +	{ .compatible = "fsl,ls1028a-lpuart",	.data = &ls1028a_data, },  	{ .compatible = "fsl,imx7ulp-lpuart",	.data = &imx7ulp_data, },  	{ .compatible = "fsl,imx8qxp-lpuart",	.data = &imx8qxp_data, },  	{ /* sentinel */ } @@ -307,6 +314,11 @@ MODULE_DEVICE_TABLE(of, lpuart_dt_ids);  /* Forward declare this for the dma callbacks*/  static void lpuart_dma_tx_complete(void *arg); +static inline bool is_ls1028a_lpuart(struct lpuart_port *sport) +{ +	return sport->devtype == LS1028A_LPUART; +} +  static inline bool is_imx8qxp_lpuart(struct lpuart_port *sport)  {  	return sport->devtype == IMX8QXP_LPUART; @@ -409,6 +421,7 @@ static void lpuart_dma_tx(struct lpuart_port *sport)  	struct circ_buf *xmit = &sport->port.state->xmit;  	struct scatterlist *sgl = sport->tx_sgl;  	struct device *dev = sport->port.dev; +	struct dma_chan *chan = sport->dma_tx_chan;  	int ret;  	if (sport->dma_tx_in_progress) @@ -427,17 +440,19 @@ static void lpuart_dma_tx(struct lpuart_port *sport)  		sg_set_buf(sgl + 1, xmit->buf, xmit->head);  	} -	ret = dma_map_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); +	ret = dma_map_sg(chan->device->dev, sgl, sport->dma_tx_nents, +			 DMA_TO_DEVICE);  	if (!ret) {  		dev_err(dev, "DMA mapping error for TX.\n");  		return;  	} -	sport->dma_tx_desc = dmaengine_prep_slave_sg(sport->dma_tx_chan, sgl, +	sport->dma_tx_desc = dmaengine_prep_slave_sg(chan, sgl,  					ret, DMA_MEM_TO_DEV,  					DMA_PREP_INTERRUPT);  	if (!sport->dma_tx_desc) { -		dma_unmap_sg(dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); +		dma_unmap_sg(chan->device->dev, sgl, sport->dma_tx_nents, +			      DMA_TO_DEVICE);  		dev_err(dev, "Cannot prepare TX slave DMA!\n");  		return;  	} @@ -446,7 +461,7 @@ static void lpuart_dma_tx(struct lpuart_port *sport)  	sport->dma_tx_desc->callback_param = sport;  	sport->dma_tx_in_progress = true;  	sport->dma_tx_cookie = dmaengine_submit(sport->dma_tx_desc); -	dma_async_issue_pending(sport->dma_tx_chan); +	dma_async_issue_pending(chan);  }  static bool lpuart_stopped_or_empty(struct uart_port *port) @@ -459,11 +474,13 @@ static void lpuart_dma_tx_complete(void *arg)  	struct lpuart_port *sport = arg;  	struct scatterlist *sgl = &sport->tx_sgl[0];  	struct circ_buf *xmit = &sport->port.state->xmit; +	struct dma_chan *chan = sport->dma_tx_chan;  	unsigned long flags;  	spin_lock_irqsave(&sport->port.lock, flags); -	dma_unmap_sg(sport->port.dev, sgl, sport->dma_tx_nents, DMA_TO_DEVICE); +	dma_unmap_sg(chan->device->dev, sgl, sport->dma_tx_nents, +		     DMA_TO_DEVICE);  	xmit->tail = (xmit->tail + sport->dma_tx_bytes) & (UART_XMIT_SIZE - 1); @@ -529,15 +546,16 @@ static bool lpuart_is_32(struct lpuart_port *sport)  static void lpuart_flush_buffer(struct uart_port *port)  {  	struct lpuart_port *sport = container_of(port, struct lpuart_port, port); +	struct dma_chan *chan = sport->dma_tx_chan;  	u32 val;  	if (sport->lpuart_dma_tx_use) {  		if (sport->dma_tx_in_progress) { -			dma_unmap_sg(sport->port.dev, &sport->tx_sgl[0], +			dma_unmap_sg(chan->device->dev, &sport->tx_sgl[0],  				sport->dma_tx_nents, DMA_TO_DEVICE);  			sport->dma_tx_in_progress = false;  		} -		dmaengine_terminate_all(sport->dma_tx_chan); +		dmaengine_terminate_all(chan);  	}  	if (lpuart_is_32(sport)) { @@ -993,6 +1011,7 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)  	struct tty_port *port = &sport->port.state->port;  	struct dma_tx_state state;  	enum dma_status dmastat; +	struct dma_chan *chan = sport->dma_rx_chan;  	struct circ_buf *ring = &sport->rx_ring;  	unsigned long flags;  	int count = 0; @@ -1053,10 +1072,7 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)  	spin_lock_irqsave(&sport->port.lock, flags); -	dmastat = dmaengine_tx_status(sport->dma_rx_chan, -				sport->dma_rx_cookie, -				&state); - +	dmastat = dmaengine_tx_status(chan, sport->dma_rx_cookie, &state);  	if (dmastat == DMA_ERROR) {  		dev_err(sport->port.dev, "Rx DMA transfer failed!\n");  		spin_unlock_irqrestore(&sport->port.lock, flags); @@ -1064,7 +1080,8 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)  	}  	/* CPU claims ownership of RX DMA buffer */ -	dma_sync_sg_for_cpu(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); +	dma_sync_sg_for_cpu(chan->device->dev, &sport->rx_sgl, 1, +			    DMA_FROM_DEVICE);  	/*  	 * ring->head points to the end of data already written by the DMA. @@ -1106,7 +1123,7 @@ static void lpuart_copy_rx_to_tty(struct lpuart_port *sport)  		sport->port.icount.rx += count;  	} -	dma_sync_sg_for_device(sport->port.dev, &sport->rx_sgl, 1, +	dma_sync_sg_for_device(chan->device->dev, &sport->rx_sgl, 1,  			       DMA_FROM_DEVICE);  	spin_unlock_irqrestore(&sport->port.lock, flags); @@ -1138,6 +1155,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)  	struct tty_port *port = &sport->port.state->port;  	struct tty_struct *tty = port->tty;  	struct ktermios *termios = &tty->termios; +	struct dma_chan *chan = sport->dma_rx_chan;  	baud = tty_get_baud_rate(tty); @@ -1159,7 +1177,8 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)  		return -ENOMEM;  	sg_init_one(&sport->rx_sgl, ring->buf, sport->rx_dma_rng_buf_len); -	nent = dma_map_sg(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); +	nent = dma_map_sg(chan->device->dev, &sport->rx_sgl, 1, +			  DMA_FROM_DEVICE);  	if (!nent) {  		dev_err(sport->port.dev, "DMA Rx mapping error\n"); @@ -1170,7 +1189,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)  	dma_rx_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;  	dma_rx_sconfig.src_maxburst = 1;  	dma_rx_sconfig.direction = DMA_DEV_TO_MEM; -	ret = dmaengine_slave_config(sport->dma_rx_chan, &dma_rx_sconfig); +	ret = dmaengine_slave_config(chan, &dma_rx_sconfig);  	if (ret < 0) {  		dev_err(sport->port.dev, @@ -1178,7 +1197,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)  		return ret;  	} -	sport->dma_rx_desc = dmaengine_prep_dma_cyclic(sport->dma_rx_chan, +	sport->dma_rx_desc = dmaengine_prep_dma_cyclic(chan,  				 sg_dma_address(&sport->rx_sgl),  				 sport->rx_sgl.length,  				 sport->rx_sgl.length / 2, @@ -1192,7 +1211,7 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)  	sport->dma_rx_desc->callback = lpuart_dma_rx_complete;  	sport->dma_rx_desc->callback_param = sport;  	sport->dma_rx_cookie = dmaengine_submit(sport->dma_rx_desc); -	dma_async_issue_pending(sport->dma_rx_chan); +	dma_async_issue_pending(chan);  	if (lpuart_is_32(sport)) {  		unsigned long temp = lpuart32_read(&sport->port, UARTBAUD); @@ -1210,11 +1229,12 @@ static void lpuart_dma_rx_free(struct uart_port *port)  {  	struct lpuart_port *sport = container_of(port,  					struct lpuart_port, port); +	struct dma_chan *chan = sport->dma_rx_chan; -	if (sport->dma_rx_chan) -		dmaengine_terminate_all(sport->dma_rx_chan); +	if (chan) +		dmaengine_terminate_all(chan); -	dma_unmap_sg(sport->port.dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE); +	dma_unmap_sg(chan->device->dev, &sport->rx_sgl, 1, DMA_FROM_DEVICE);  	kfree(sport->rx_ring.buf);  	sport->rx_ring.tail = 0;  	sport->rx_ring.head = 0; @@ -1490,39 +1510,77 @@ static void rx_dma_timer_init(struct lpuart_port *sport)  	add_timer(&sport->lpuart_timer);  } +static void lpuart_request_dma(struct lpuart_port *sport) +{ +	sport->dma_tx_chan = dma_request_chan(sport->port.dev, "tx"); +	if (IS_ERR(sport->dma_tx_chan)) { +		dev_info_once(sport->port.dev, +			      "DMA tx channel request failed, operating without tx DMA (%ld)\n", +			      PTR_ERR(sport->dma_tx_chan)); +		sport->dma_tx_chan = NULL; +	} + +	sport->dma_rx_chan = dma_request_chan(sport->port.dev, "rx"); +	if (IS_ERR(sport->dma_rx_chan)) { +		dev_info_once(sport->port.dev, +			      "DMA rx channel request failed, operating without rx DMA (%ld)\n", +			      PTR_ERR(sport->dma_rx_chan)); +		sport->dma_rx_chan = NULL; +	} +} +  static void lpuart_tx_dma_startup(struct lpuart_port *sport)  {  	u32 uartbaud; +	int ret; -	if (sport->dma_tx_chan && !lpuart_dma_tx_request(&sport->port)) { -		init_waitqueue_head(&sport->dma_wait); -		sport->lpuart_dma_tx_use = true; -		if (lpuart_is_32(sport)) { -			uartbaud = lpuart32_read(&sport->port, UARTBAUD); -			lpuart32_write(&sport->port, -				       uartbaud | UARTBAUD_TDMAE, UARTBAUD); -		} else { -			writeb(readb(sport->port.membase + UARTCR5) | -				UARTCR5_TDMAS, sport->port.membase + UARTCR5); -		} +	if (!sport->dma_tx_chan) +		goto err; + +	ret = lpuart_dma_tx_request(&sport->port); +	if (ret) +		goto err; + +	init_waitqueue_head(&sport->dma_wait); +	sport->lpuart_dma_tx_use = true; +	if (lpuart_is_32(sport)) { +		uartbaud = lpuart32_read(&sport->port, UARTBAUD); +		lpuart32_write(&sport->port, +			       uartbaud | UARTBAUD_TDMAE, UARTBAUD);  	} else { -		sport->lpuart_dma_tx_use = false; +		writeb(readb(sport->port.membase + UARTCR5) | +		       UARTCR5_TDMAS, sport->port.membase + UARTCR5);  	} + +	return; + +err: +	sport->lpuart_dma_tx_use = false;  }  static void lpuart_rx_dma_startup(struct lpuart_port *sport)  { -	if (sport->dma_rx_chan && !lpuart_start_rx_dma(sport)) { -		/* set Rx DMA timeout */ -		sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT); -		if (!sport->dma_rx_timeout) -			sport->dma_rx_timeout = 1; +	int ret; -		sport->lpuart_dma_rx_use = true; -		rx_dma_timer_init(sport); -	} else { -		sport->lpuart_dma_rx_use = false; -	} +	if (!sport->dma_rx_chan) +		goto err; + +	ret = lpuart_start_rx_dma(sport); +	if (ret) +		goto err; + +	/* set Rx DMA timeout */ +	sport->dma_rx_timeout = msecs_to_jiffies(DMA_RX_TIMEOUT); +	if (!sport->dma_rx_timeout) +		sport->dma_rx_timeout = 1; + +	sport->lpuart_dma_rx_use = true; +	rx_dma_timer_init(sport); + +	return; + +err: +	sport->lpuart_dma_rx_use = false;  }  static int lpuart_startup(struct uart_port *port) @@ -1541,6 +1599,8 @@ static int lpuart_startup(struct uart_port *port)  	sport->rxfifo_size = UARTFIFO_DEPTH((temp >> UARTPFIFO_RXSIZE_OFF) &  					    UARTPFIFO_FIFOSIZE_MASK); +	lpuart_request_dma(sport); +  	spin_lock_irqsave(&sport->port.lock, flags);  	lpuart_setup_watermark_enable(sport); @@ -1587,11 +1647,23 @@ static int lpuart32_startup(struct uart_port *port)  	sport->rxfifo_size = UARTFIFO_DEPTH((temp >> UARTFIFO_RXSIZE_OFF) &  					    UARTFIFO_FIFOSIZE_MASK); +	/* +	 * The LS1028A has a fixed length of 16 words. Although it supports the +	 * RX/TXSIZE fields their encoding is different. Eg the reference manual +	 * states 0b101 is 16 words. +	 */ +	if (is_ls1028a_lpuart(sport)) { +		sport->rxfifo_size = 16; +		sport->txfifo_size = 16; +		sport->port.fifosize = sport->txfifo_size; +	} + +	lpuart_request_dma(sport); +  	spin_lock_irqsave(&sport->port.lock, flags);  	lpuart32_setup_watermark_enable(sport); -  	lpuart_rx_dma_startup(sport);  	lpuart_tx_dma_startup(sport); @@ -1615,6 +1687,11 @@ static void lpuart_dma_shutdown(struct lpuart_port *sport)  			dmaengine_terminate_all(sport->dma_tx_chan);  		}  	} + +	if (sport->dma_tx_chan) +		dma_release_channel(sport->dma_tx_chan); +	if (sport->dma_rx_chan) +		dma_release_channel(sport->dma_rx_chan);  }  static void lpuart_shutdown(struct uart_port *port) @@ -1811,11 +1888,12 @@ lpuart_set_termios(struct uart_port *port, struct ktermios *termios,  	spin_unlock_irqrestore(&sport->port.lock, flags);  } -static void -lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate) +static void __lpuart32_serial_setbrg(struct uart_port *port, +				     unsigned int baudrate, bool use_rx_dma, +				     bool use_tx_dma)  {  	u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff, tmp; -	u32 clk = sport->port.uartclk; +	u32 clk = port->uartclk;  	/*  	 * The idea is to use the best OSR (over-sampling rate) possible. @@ -1861,10 +1939,10 @@ lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)  	/* handle buadrate outside acceptable rate */  	if (baud_diff > ((baudrate / 100) * 3)) -		dev_warn(sport->port.dev, +		dev_warn(port->dev,  			 "unacceptable baud rate difference of more than 3%%\n"); -	tmp = lpuart32_read(&sport->port, UARTBAUD); +	tmp = lpuart32_read(port, UARTBAUD);  	if ((osr > 3) && (osr < 8))  		tmp |= UARTBAUD_BOTHEDGE; @@ -1875,14 +1953,23 @@ lpuart32_serial_setbrg(struct lpuart_port *sport, unsigned int baudrate)  	tmp &= ~UARTBAUD_SBR_MASK;  	tmp |= sbr & UARTBAUD_SBR_MASK; -	if (!sport->lpuart_dma_rx_use) +	if (!use_rx_dma)  		tmp &= ~UARTBAUD_RDMAE; -	if (!sport->lpuart_dma_tx_use) +	if (!use_tx_dma)  		tmp &= ~UARTBAUD_TDMAE; -	lpuart32_write(&sport->port, tmp, UARTBAUD); +	lpuart32_write(port, tmp, UARTBAUD); +} + +static void lpuart32_serial_setbrg(struct lpuart_port *sport, +				   unsigned int baudrate) +{ +	__lpuart32_serial_setbrg(&sport->port, baudrate, +				 sport->lpuart_dma_rx_use, +				 sport->lpuart_dma_tx_use);  } +  static void  lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,  		   struct ktermios *old) @@ -2376,6 +2463,30 @@ static int __init lpuart32_early_console_setup(struct earlycon_device *device,  	return 0;  } +static int __init ls1028a_early_console_setup(struct earlycon_device *device, +					      const char *opt) +{ +	u32 cr; + +	if (!device->port.membase) +		return -ENODEV; + +	device->port.iotype = UPIO_MEM32; +	device->con->write = lpuart32_early_write; + +	/* set the baudrate */ +	if (device->port.uartclk && device->baud) +		__lpuart32_serial_setbrg(&device->port, device->baud, +					 false, false); + +	/* enable transmitter */ +	cr = lpuart32_read(&device->port, UARTCTRL); +	cr |= UARTCTRL_TE; +	lpuart32_write(&device->port, cr, UARTCTRL); + +	return 0; +} +  static int __init lpuart32_imx_early_console_setup(struct earlycon_device *device,  						   const char *opt)  { @@ -2390,6 +2501,7 @@ static int __init lpuart32_imx_early_console_setup(struct earlycon_device *devic  }  OF_EARLYCON_DECLARE(lpuart, "fsl,vf610-lpuart", lpuart_early_console_setup);  OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1021a-lpuart", lpuart32_early_console_setup); +OF_EARLYCON_DECLARE(lpuart32, "fsl,ls1028a-lpuart", ls1028a_early_console_setup);  OF_EARLYCON_DECLARE(lpuart32, "fsl,imx7ulp-lpuart", lpuart32_imx_early_console_setup);  EARLYCON_DECLARE(lpuart, lpuart_early_console_setup);  EARLYCON_DECLARE(lpuart32, lpuart32_early_console_setup); @@ -2520,16 +2632,6 @@ static int lpuart_probe(struct platform_device *pdev)  	sport->port.rs485_config(&sport->port, &sport->port.rs485); -	sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx"); -	if (!sport->dma_tx_chan) -		dev_info(sport->port.dev, "DMA tx channel request failed, " -				"operating without tx DMA\n"); - -	sport->dma_rx_chan = dma_request_slave_channel(sport->port.dev, "rx"); -	if (!sport->dma_rx_chan) -		dev_info(sport->port.dev, "DMA rx channel request failed, " -				"operating without rx DMA\n"); -  	return 0;  failed_attach_port: diff --git a/drivers/tty/serial/icom.h b/drivers/tty/serial/icom.h index 8a77e739b333..26e3aa7b01e2 100644 --- a/drivers/tty/serial/icom.h +++ b/drivers/tty/serial/icom.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */  /*   * icom.h   * diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 31033d517e82..7d16fe41932f 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -39,7 +39,7 @@  #include <linux/fs.h>  #include <linux/ip.h>  #include <linux/dmapool.h> -#include <linux/gpio.h> +#include <linux/gpio/consumer.h>  #include <linux/sched.h>  #include <linux/time.h>  #include <linux/wait.h> @@ -61,7 +61,6 @@  #define IFX_SPI_HEADER_F		(-2)  #define PO_POST_DELAY		200 -#define IFX_MDM_RST_PMU	4  /* forward reference */  static void ifx_spi_handle_srdy(struct ifx_spi_device *ifx_dev); @@ -81,7 +80,7 @@ static struct notifier_block ifx_modem_reboot_notifier_block = {  static int ifx_modem_power_off(struct ifx_spi_device *ifx_dev)  { -	gpio_set_value(IFX_MDM_RST_PMU, 1); +	gpiod_set_value(ifx_dev->gpio.pmu_reset, 1);  	msleep(PO_POST_DELAY);  	return 0; @@ -107,7 +106,7 @@ static int ifx_modem_reboot_callback(struct notifier_block *nfb,   */  static inline void mrdy_set_high(struct ifx_spi_device *ifx)  { -	gpio_set_value(ifx->gpio.mrdy, 1); +	gpiod_set_value(ifx->gpio.mrdy, 1);  }  /** @@ -117,7 +116,7 @@ static inline void mrdy_set_high(struct ifx_spi_device *ifx)   */  static inline void mrdy_set_low(struct ifx_spi_device *ifx)  { -	gpio_set_value(ifx->gpio.mrdy, 0); +	gpiod_set_value(ifx->gpio.mrdy, 0);  }  /** @@ -244,7 +243,7 @@ static inline void swap_buf_32(unsigned char *buf, int len, void *end)   */  static void mrdy_assert(struct ifx_spi_device *ifx_dev)  { -	int val = gpio_get_value(ifx_dev->gpio.srdy); +	int val = gpiod_get_value(ifx_dev->gpio.srdy);  	if (!val) {  		if (!test_and_set_bit(IFX_SPI_STATE_TIMER_PENDING,  				      &ifx_dev->flags)) { @@ -691,7 +690,7 @@ complete_exit:  	clear_bit(IFX_SPI_STATE_IO_IN_PROGRESS, &(ifx_dev->flags));  	queue_length = kfifo_len(&ifx_dev->tx_fifo); -	srdy = gpio_get_value(ifx_dev->gpio.srdy); +	srdy = gpiod_get_value(ifx_dev->gpio.srdy);  	if (!srdy)  		ifx_spi_power_state_clear(ifx_dev, IFX_SPI_POWER_SRDY); @@ -898,7 +897,7 @@ static irqreturn_t ifx_spi_srdy_interrupt(int irq, void *dev)  static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev)  {  	struct ifx_spi_device *ifx_dev = dev; -	int val = gpio_get_value(ifx_dev->gpio.reset_out); +	int val = gpiod_get_value(ifx_dev->gpio.reset_out);  	int solreset = test_bit(MR_START, &ifx_dev->mdm_reset_state);  	if (val == 0) { @@ -954,14 +953,14 @@ static int ifx_spi_reset(struct ifx_spi_device *ifx_dev)  	 * to reset properly  	 */  	set_bit(MR_START, &ifx_dev->mdm_reset_state); -	gpio_set_value(ifx_dev->gpio.po, 0); -	gpio_set_value(ifx_dev->gpio.reset, 0); +	gpiod_set_value(ifx_dev->gpio.po, 0); +	gpiod_set_value(ifx_dev->gpio.reset, 0);  	msleep(25); -	gpio_set_value(ifx_dev->gpio.reset, 1); +	gpiod_set_value(ifx_dev->gpio.reset, 1);  	msleep(1); -	gpio_set_value(ifx_dev->gpio.po, 1); +	gpiod_set_value(ifx_dev->gpio.po, 1);  	msleep(1); -	gpio_set_value(ifx_dev->gpio.po, 0); +	gpiod_set_value(ifx_dev->gpio.po, 0);  	ret = wait_event_timeout(ifx_dev->mdm_reset_wait,  				 test_bit(MR_COMPLETE,  					  &ifx_dev->mdm_reset_state), @@ -992,22 +991,23 @@ static int ifx_spi_spi_probe(struct spi_device *spi)  	int srdy;  	struct ifx_modem_platform_data *pl_data;  	struct ifx_spi_device *ifx_dev; +	struct device *dev = &spi->dev;  	if (saved_ifx_dev) { -		dev_dbg(&spi->dev, "ignoring subsequent detection"); +		dev_dbg(dev, "ignoring subsequent detection");  		return -ENODEV;  	} -	pl_data = dev_get_platdata(&spi->dev); +	pl_data = dev_get_platdata(dev);  	if (!pl_data) { -		dev_err(&spi->dev, "missing platform data!"); +		dev_err(dev, "missing platform data!");  		return -ENODEV;  	}  	/* initialize structure to hold our device variables */  	ifx_dev = kzalloc(sizeof(struct ifx_spi_device), GFP_KERNEL);  	if (!ifx_dev) { -		dev_err(&spi->dev, "spi device allocation failed"); +		dev_err(dev, "spi device allocation failed");  		return -ENOMEM;  	}  	saved_ifx_dev = ifx_dev; @@ -1026,7 +1026,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)  	spi->bits_per_word = spi_bpw;  	ret = spi_setup(spi);  	if (ret) { -		dev_err(&spi->dev, "SPI setup wasn't successful %d", ret); +		dev_err(dev, "SPI setup wasn't successful %d", ret);  		kfree(ifx_dev);  		return -ENODEV;  	} @@ -1049,7 +1049,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)  				&ifx_dev->tx_bus,  				GFP_KERNEL);  	if (!ifx_dev->tx_buffer) { -		dev_err(&spi->dev, "DMA-TX buffer allocation failed"); +		dev_err(dev, "DMA-TX buffer allocation failed");  		ret = -ENOMEM;  		goto error_ret;  	} @@ -1058,7 +1058,7 @@ static int ifx_spi_spi_probe(struct spi_device *spi)  				&ifx_dev->rx_bus,  				GFP_KERNEL);  	if (!ifx_dev->rx_buffer) { -		dev_err(&spi->dev, "DMA-RX buffer allocation failed"); +		dev_err(dev, "DMA-RX buffer allocation failed");  		ret = -ENOMEM;  		goto error_ret;  	} @@ -1075,122 +1075,83 @@ static int ifx_spi_spi_probe(struct spi_device *spi)  	/* create our tty port */  	ret = ifx_spi_create_port(ifx_dev);  	if (ret != 0) { -		dev_err(&spi->dev, "create default tty port failed"); +		dev_err(dev, "create default tty port failed");  		goto error_ret;  	} -	ifx_dev->gpio.reset = pl_data->rst_pmu; -	ifx_dev->gpio.po = pl_data->pwr_on; -	ifx_dev->gpio.mrdy = pl_data->mrdy; -	ifx_dev->gpio.srdy = pl_data->srdy; -	ifx_dev->gpio.reset_out = pl_data->rst_out; - -	dev_info(&spi->dev, "gpios %d, %d, %d, %d, %d", -		 ifx_dev->gpio.reset, ifx_dev->gpio.po, ifx_dev->gpio.mrdy, -		 ifx_dev->gpio.srdy, ifx_dev->gpio.reset_out); - -	/* Configure gpios */ -	ret = gpio_request(ifx_dev->gpio.reset, "ifxModem"); -	if (ret < 0) { -		dev_err(&spi->dev, "Unable to allocate GPIO%d (RESET)", -			ifx_dev->gpio.reset); +	ifx_dev->gpio.reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); +	if (IS_ERR(ifx_dev->gpio.reset)) { +		dev_err(dev, "could not obtain reset GPIO\n"); +		ret = PTR_ERR(ifx_dev->gpio.reset);  		goto error_ret;  	} -	ret += gpio_direction_output(ifx_dev->gpio.reset, 0); -	ret += gpio_export(ifx_dev->gpio.reset, 1); -	if (ret) { -		dev_err(&spi->dev, "Unable to configure GPIO%d (RESET)", -			ifx_dev->gpio.reset); -		ret = -EBUSY; -		goto error_ret2; -	} - -	ret = gpio_request(ifx_dev->gpio.po, "ifxModem"); -	ret += gpio_direction_output(ifx_dev->gpio.po, 0); -	ret += gpio_export(ifx_dev->gpio.po, 1); -	if (ret) { -		dev_err(&spi->dev, "Unable to configure GPIO%d (ON)", -			ifx_dev->gpio.po); -		ret = -EBUSY; -		goto error_ret3; -	} - -	ret = gpio_request(ifx_dev->gpio.mrdy, "ifxModem"); -	if (ret < 0) { -		dev_err(&spi->dev, "Unable to allocate GPIO%d (MRDY)", -			ifx_dev->gpio.mrdy); -		goto error_ret3; -	} -	ret += gpio_export(ifx_dev->gpio.mrdy, 1); -	ret += gpio_direction_output(ifx_dev->gpio.mrdy, 0); -	if (ret) { -		dev_err(&spi->dev, "Unable to configure GPIO%d (MRDY)", -			ifx_dev->gpio.mrdy); -		ret = -EBUSY; -		goto error_ret4; +	gpiod_set_consumer_name(ifx_dev->gpio.reset, "ifxModem reset"); +	ifx_dev->gpio.po = devm_gpiod_get(dev, "power", GPIOD_OUT_LOW); +	if (IS_ERR(ifx_dev->gpio.po)) { +		dev_err(dev, "could not obtain power GPIO\n"); +		ret = PTR_ERR(ifx_dev->gpio.po); +		goto error_ret;  	} - -	ret = gpio_request(ifx_dev->gpio.srdy, "ifxModem"); -	if (ret < 0) { -		dev_err(&spi->dev, "Unable to allocate GPIO%d (SRDY)", -			ifx_dev->gpio.srdy); -		ret = -EBUSY; -		goto error_ret4; +	gpiod_set_consumer_name(ifx_dev->gpio.po, "ifxModem power"); +	ifx_dev->gpio.mrdy = devm_gpiod_get(dev, "mrdy", GPIOD_OUT_LOW); +	if (IS_ERR(ifx_dev->gpio.mrdy)) { +		dev_err(dev, "could not obtain mrdy GPIO\n"); +		ret = PTR_ERR(ifx_dev->gpio.mrdy); +		goto error_ret;  	} -	ret += gpio_export(ifx_dev->gpio.srdy, 1); -	ret += gpio_direction_input(ifx_dev->gpio.srdy); -	if (ret) { -		dev_err(&spi->dev, "Unable to configure GPIO%d (SRDY)", -			ifx_dev->gpio.srdy); -		ret = -EBUSY; -		goto error_ret5; +	gpiod_set_consumer_name(ifx_dev->gpio.mrdy, "ifxModem mrdy"); +	ifx_dev->gpio.srdy = devm_gpiod_get(dev, "srdy", GPIOD_IN); +	if (IS_ERR(ifx_dev->gpio.srdy)) { +		dev_err(dev, "could not obtain srdy GPIO\n"); +		ret = PTR_ERR(ifx_dev->gpio.srdy); +		goto error_ret;  	} - -	ret = gpio_request(ifx_dev->gpio.reset_out, "ifxModem"); -	if (ret < 0) { -		dev_err(&spi->dev, "Unable to allocate GPIO%d (RESET_OUT)", -			ifx_dev->gpio.reset_out); -		goto error_ret5; +	gpiod_set_consumer_name(ifx_dev->gpio.srdy, "ifxModem srdy"); +	ifx_dev->gpio.reset_out = devm_gpiod_get(dev, "rst_out", GPIOD_IN); +	if (IS_ERR(ifx_dev->gpio.reset_out)) { +		dev_err(dev, "could not obtain rst_out GPIO\n"); +		ret = PTR_ERR(ifx_dev->gpio.reset_out); +		goto error_ret;  	} -	ret += gpio_export(ifx_dev->gpio.reset_out, 1); -	ret += gpio_direction_input(ifx_dev->gpio.reset_out); -	if (ret) { -		dev_err(&spi->dev, "Unable to configure GPIO%d (RESET_OUT)", -			ifx_dev->gpio.reset_out); -		ret = -EBUSY; -		goto error_ret6; +	gpiod_set_consumer_name(ifx_dev->gpio.reset_out, "ifxModem reset out"); +	ifx_dev->gpio.pmu_reset = devm_gpiod_get(dev, "pmu_reset", GPIOD_ASIS); +	if (IS_ERR(ifx_dev->gpio.pmu_reset)) { +		dev_err(dev, "could not obtain pmu_reset GPIO\n"); +		ret = PTR_ERR(ifx_dev->gpio.pmu_reset); +		goto error_ret;  	} +	gpiod_set_consumer_name(ifx_dev->gpio.pmu_reset, "ifxModem PMU reset"); -	ret = request_irq(gpio_to_irq(ifx_dev->gpio.reset_out), +	ret = request_irq(gpiod_to_irq(ifx_dev->gpio.reset_out),  			  ifx_spi_reset_interrupt,  			  IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, DRVNAME,  			  ifx_dev);  	if (ret) { -		dev_err(&spi->dev, "Unable to get irq %x\n", -			gpio_to_irq(ifx_dev->gpio.reset_out)); -		goto error_ret6; +		dev_err(dev, "Unable to get irq %x\n", +			gpiod_to_irq(ifx_dev->gpio.reset_out)); +		goto error_ret;  	}  	ret = ifx_spi_reset(ifx_dev); -	ret = request_irq(gpio_to_irq(ifx_dev->gpio.srdy), +	ret = request_irq(gpiod_to_irq(ifx_dev->gpio.srdy),  			  ifx_spi_srdy_interrupt, IRQF_TRIGGER_RISING, DRVNAME,  			  ifx_dev);  	if (ret) { -		dev_err(&spi->dev, "Unable to get irq %x", -			gpio_to_irq(ifx_dev->gpio.srdy)); -		goto error_ret7; +		dev_err(dev, "Unable to get irq %x", +			gpiod_to_irq(ifx_dev->gpio.srdy)); +		goto error_ret2;  	}  	/* set pm runtime power state and register with power system */ -	pm_runtime_set_active(&spi->dev); -	pm_runtime_enable(&spi->dev); +	pm_runtime_set_active(dev); +	pm_runtime_enable(dev);  	/* handle case that modem is already signaling SRDY */  	/* no outgoing tty open at this point, this just satisfies the  	 * modem's read and should reset communication properly  	 */ -	srdy = gpio_get_value(ifx_dev->gpio.srdy); +	srdy = gpiod_get_value(ifx_dev->gpio.srdy);  	if (srdy) {  		mrdy_assert(ifx_dev); @@ -1199,18 +1160,8 @@ static int ifx_spi_spi_probe(struct spi_device *spi)  		mrdy_set_low(ifx_dev);  	return 0; -error_ret7: -	free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), ifx_dev); -error_ret6: -	gpio_free(ifx_dev->gpio.srdy); -error_ret5: -	gpio_free(ifx_dev->gpio.mrdy); -error_ret4: -	gpio_free(ifx_dev->gpio.reset); -error_ret3: -	gpio_free(ifx_dev->gpio.po);  error_ret2: -	gpio_free(ifx_dev->gpio.reset_out); +	free_irq(gpiod_to_irq(ifx_dev->gpio.reset_out), ifx_dev);  error_ret:  	ifx_spi_free_device(ifx_dev);  	saved_ifx_dev = NULL; @@ -1234,14 +1185,8 @@ static int ifx_spi_spi_remove(struct spi_device *spi)  	pm_runtime_disable(&spi->dev);  	/* free irq */ -	free_irq(gpio_to_irq(ifx_dev->gpio.reset_out), ifx_dev); -	free_irq(gpio_to_irq(ifx_dev->gpio.srdy), ifx_dev); - -	gpio_free(ifx_dev->gpio.srdy); -	gpio_free(ifx_dev->gpio.mrdy); -	gpio_free(ifx_dev->gpio.reset); -	gpio_free(ifx_dev->gpio.po); -	gpio_free(ifx_dev->gpio.reset_out); +	free_irq(gpiod_to_irq(ifx_dev->gpio.reset_out), ifx_dev); +	free_irq(gpiod_to_irq(ifx_dev->gpio.srdy), ifx_dev);  	/* free allocations */  	ifx_spi_free_device(ifx_dev); diff --git a/drivers/tty/serial/ifx6x60.h b/drivers/tty/serial/ifx6x60.h index c5a2514212ff..ecb841d928a7 100644 --- a/drivers/tty/serial/ifx6x60.h +++ b/drivers/tty/serial/ifx6x60.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */  /****************************************************************************   *   * Driver for the IFX spi modem. @@ -10,6 +10,8 @@  #ifndef _IFX6X60_H  #define _IFX6X60_H +struct gpio_desc; +  #define DRVNAME				"ifx6x60"  #define TTYNAME				"ttyIFX" @@ -94,11 +96,12 @@ struct ifx_spi_device {  	struct {  		/* gpio lines */ -		unsigned short srdy;		/* slave-ready gpio */ -		unsigned short mrdy;		/* master-ready gpio */ -		unsigned short reset;		/* modem-reset gpio */ -		unsigned short po;		/* modem-on gpio */ -		unsigned short reset_out;	/* modem-in-reset gpio */ +		struct gpio_desc *srdy;		/* slave-ready gpio */ +		struct gpio_desc *mrdy;		/* master-ready gpio */ +		struct gpio_desc *reset;	/* modem-reset gpio */ +		struct gpio_desc *po;		/* modem-on gpio */ +		struct gpio_desc *reset_out;	/* modem-in-reset gpio */ +		struct gpio_desc *pmu_reset;	/* PMU reset gpio */  		/* state/stats */  		int unack_srdy_int_nb;  	} gpio; diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index d337782b3648..f4d68109bc8b 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -195,6 +195,8 @@ struct imx_port {  	unsigned int		have_rtscts:1;  	unsigned int		have_rtsgpio:1;  	unsigned int		dte_mode:1; +	unsigned int		inverted_tx:1; +	unsigned int		inverted_rx:1;  	struct clk		*clk_ipg;  	struct clk		*clk_per;  	const struct imx_uart_data *devdata; @@ -1335,7 +1337,7 @@ static int imx_uart_startup(struct uart_port *port)  	int retval, i;  	unsigned long flags;  	int dma_is_inited = 0; -	u32 ucr1, ucr2, ucr4; +	u32 ucr1, ucr2, ucr3, ucr4;  	retval = clk_prepare_enable(sport->clk_per);  	if (retval) @@ -1387,11 +1389,29 @@ static int imx_uart_startup(struct uart_port *port)  	imx_uart_writel(sport, ucr1, UCR1); -	ucr4 = imx_uart_readl(sport, UCR4) & ~UCR4_OREN; +	ucr4 = imx_uart_readl(sport, UCR4) & ~(UCR4_OREN | UCR4_INVR);  	if (!sport->dma_is_enabled)  		ucr4 |= UCR4_OREN; +	if (sport->inverted_rx) +		ucr4 |= UCR4_INVR;  	imx_uart_writel(sport, ucr4, UCR4); +	ucr3 = imx_uart_readl(sport, UCR3) & ~UCR3_INVT; +	/* +	 * configure tx polarity before enabling tx +	 */ +	if (sport->inverted_tx) +		ucr3 |= UCR3_INVT; + +	if (!imx_uart_is_imx1(sport)) { +		ucr3 |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD; + +		if (sport->dte_mode) +			/* disable broken interrupts */ +			ucr3 &= ~(UCR3_RI | UCR3_DCD); +	} +	imx_uart_writel(sport, ucr3, UCR3); +  	ucr2 = imx_uart_readl(sport, UCR2) & ~UCR2_ATEN;  	ucr2 |= (UCR2_RXEN | UCR2_TXEN);  	if (!sport->have_rtscts) @@ -1404,20 +1424,6 @@ static int imx_uart_startup(struct uart_port *port)  		ucr2 &= ~UCR2_RTSEN;  	imx_uart_writel(sport, ucr2, UCR2); -	if (!imx_uart_is_imx1(sport)) { -		u32 ucr3; - -		ucr3 = imx_uart_readl(sport, UCR3); - -		ucr3 |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD; - -		if (sport->dte_mode) -			/* disable broken interrupts */ -			ucr3 &= ~(UCR3_RI | UCR3_DCD); - -		imx_uart_writel(sport, ucr3, UCR3); -	} -  	/*  	 * Enable modem status interrupts  	 */ @@ -2184,6 +2190,12 @@ static int imx_uart_probe_dt(struct imx_port *sport,  	if (of_get_property(np, "rts-gpios", NULL))  		sport->have_rtsgpio = 1; +	if (of_get_property(np, "fsl,inverted-tx", NULL)) +		sport->inverted_tx = 1; + +	if (of_get_property(np, "fsl,inverted-rx", NULL)) +		sport->inverted_rx = 1; +  	return 0;  }  #else diff --git a/drivers/tty/serial/jsm/jsm.h b/drivers/tty/serial/jsm/jsm.h index 7a128aaa3a66..8489c07f4cd5 100644 --- a/drivers/tty/serial/jsm/jsm.h +++ b/drivers/tty/serial/jsm/jsm.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */  /************************************************************************   * Copyright 2003 Digi International (www.digi.com)   * diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index c7d51b51898f..c9f94fa82be4 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c @@ -169,15 +169,13 @@ static int configure_kgdboc(void)  	if (!p)  		goto noconfig; -	cons = console_drivers; -	while (cons) { +	for_each_console(cons) {  		int idx;  		if (cons->device && cons->device(cons, &idx) == p &&  		    idx == tty_line) {  			kgdboc_io_ops.is_console = 1;  			break;  		} -		cons = cons->next;  	}  	kgdb_tty_driver = p; diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c index f67226df30d4..c5e46ff972e4 100644 --- a/drivers/tty/serial/lantiq.c +++ b/drivers/tty/serial/lantiq.c @@ -11,7 +11,6 @@  #include <linux/clk.h>  #include <linux/console.h>  #include <linux/device.h> -#include <linux/gpio.h>  #include <linux/init.h>  #include <linux/io.h>  #include <linux/ioport.h> diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 48017cec7f2f..f7d6b3c9ea45 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -37,8 +37,6 @@  #include <linux/of_gpio.h>  #include <linux/platform_data/serial-omap.h> -#include <dt-bindings/gpio/gpio.h> -  #define OMAP_MAX_HSUART_PORTS	10  #define UART_BUILD_REVISION(x, y)	(((x) << 8) | (y)) @@ -831,7 +829,7 @@ static void serial_omap_uart_qos_work(struct work_struct *work)  	struct uart_omap_port *up = container_of(work, struct uart_omap_port,  						qos_work); -	pm_qos_update_request(&up->pm_qos_request, up->latency); +	cpu_latency_qos_update_request(&up->pm_qos_request, up->latency);  }  static void @@ -1722,10 +1720,9 @@ static int serial_omap_probe(struct platform_device *pdev)  			 DEFAULT_CLK_SPEED);  	} -	up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; -	up->calc_latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; -	pm_qos_add_request(&up->pm_qos_request, -		PM_QOS_CPU_DMA_LATENCY, up->latency); +	up->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; +	up->calc_latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE; +	cpu_latency_qos_add_request(&up->pm_qos_request, up->latency);  	INIT_WORK(&up->qos_work, serial_omap_uart_qos_work);  	platform_set_drvdata(pdev, up); @@ -1759,7 +1756,7 @@ err_add_port:  	pm_runtime_dont_use_autosuspend(&pdev->dev);  	pm_runtime_put_sync(&pdev->dev);  	pm_runtime_disable(&pdev->dev); -	pm_qos_remove_request(&up->pm_qos_request); +	cpu_latency_qos_remove_request(&up->pm_qos_request);  	device_init_wakeup(up->dev, false);  err_rs485:  err_port_line: @@ -1777,7 +1774,7 @@ static int serial_omap_remove(struct platform_device *dev)  	pm_runtime_dont_use_autosuspend(up->dev);  	pm_runtime_put_sync(up->dev);  	pm_runtime_disable(up->dev); -	pm_qos_remove_request(&up->pm_qos_request); +	cpu_latency_qos_remove_request(&up->pm_qos_request);  	device_init_wakeup(&dev->dev, false);  	return 0; @@ -1869,7 +1866,7 @@ static int serial_omap_runtime_suspend(struct device *dev)  	serial_omap_enable_wakeup(up, true); -	up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; +	up->latency = PM_QOS_CPU_LATENCY_DEFAULT_VALUE;  	schedule_work(&up->qos_work);  	return 0; diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c index 42c8cc93b603..c149f8c30007 100644 --- a/drivers/tty/serial/owl-uart.c +++ b/drivers/tty/serial/owl-uart.c @@ -680,6 +680,12 @@ static int owl_uart_probe(struct platform_device *pdev)  		return PTR_ERR(owl_port->clk);  	} +	ret = clk_prepare_enable(owl_port->clk); +	if (ret) { +		dev_err(&pdev->dev, "could not enable clk\n"); +		return ret; +	} +  	owl_port->port.dev = &pdev->dev;  	owl_port->port.line = pdev->id;  	owl_port->port.type = PORT_OWL; @@ -712,6 +718,7 @@ static int owl_uart_remove(struct platform_device *pdev)  	uart_remove_one_port(&owl_uart_driver, &owl_port->port);  	owl_uart_ports[pdev->id] = NULL; +	clk_disable_unprepare(owl_port->clk);  	return 0;  } diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 0a96217dba67..40fa7a27722d 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -310,32 +310,32 @@ static ssize_t port_show_regs(struct file *file, char __user *user_buf,  	if (!buf)  		return 0; -	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, +	len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,  			"PCH EG20T port[%d] regs:\n", priv->port.line); -	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, +	len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,  			"=================================\n"); -	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, +	len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,  			"IER: \t0x%02x\n", ioread8(priv->membase + UART_IER)); -	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, +	len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,  			"IIR: \t0x%02x\n", ioread8(priv->membase + UART_IIR)); -	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, +	len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,  			"LCR: \t0x%02x\n", ioread8(priv->membase + UART_LCR)); -	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, +	len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,  			"MCR: \t0x%02x\n", ioread8(priv->membase + UART_MCR)); -	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, +	len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,  			"LSR: \t0x%02x\n", ioread8(priv->membase + UART_LSR)); -	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, +	len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,  			"MSR: \t0x%02x\n", ioread8(priv->membase + UART_MSR)); -	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, +	len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,  			"BRCSR: \t0x%02x\n",  			ioread8(priv->membase + PCH_UART_BRCSR));  	lcr = ioread8(priv->membase + UART_LCR);  	iowrite8(PCH_UART_LCR_DLAB, priv->membase + UART_LCR); -	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, +	len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,  			"DLL: \t0x%02x\n", ioread8(priv->membase + UART_DLL)); -	len += snprintf(buf + len, PCH_REGS_BUFSIZE - len, +	len += scnprintf(buf + len, PCH_REGS_BUFSIZE - len,  			"DLM: \t0x%02x\n", ioread8(priv->membase + UART_DLM));  	iowrite8(lcr, priv->membase + UART_LCR); diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c index 484b7e8d5381..0a12fb11e698 100644 --- a/drivers/tty/serial/pic32_uart.c +++ b/drivers/tty/serial/pic32_uart.c @@ -768,11 +768,6 @@ static int __init pic32_console_init(void)  }  console_initcall(pic32_console_init); -static inline bool is_pic32_console_port(struct uart_port *port) -{ -	return port->cons && port->cons->index == port->line; -} -  /*   * Late console initialization.   */ @@ -873,8 +868,7 @@ static int pic32_uart_probe(struct platform_device *pdev)  	}  #ifdef CONFIG_SERIAL_PIC32_CONSOLE -	if (is_pic32_console_port(port) && -	    (pic32_console.flags & CON_ENABLED)) { +	if (uart_console(port) && (pic32_console.flags & CON_ENABLED)) {  		/* The peripheral clock has been enabled by console_setup,  		 * so disable it till the port is used.  		 */ diff --git a/drivers/tty/serial/pic32_uart.h b/drivers/tty/serial/pic32_uart.h index 2f2b56927dc6..b15639cc336b 100644 --- a/drivers/tty/serial/pic32_uart.h +++ b/drivers/tty/serial/pic32_uart.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */  /*   * PIC32 Integrated Serial Driver.   * diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 0bd1684cabb3..6119090ce045 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -21,6 +21,7 @@  /* UART specific GENI registers */  #define SE_UART_LOOPBACK_CFG		0x22c +#define SE_UART_IO_MACRO_CTRL		0x240  #define SE_UART_TX_TRANS_CFG		0x25c  #define SE_UART_TX_WORD_LEN		0x268  #define SE_UART_TX_STOP_BIT_LEN		0x26c @@ -95,6 +96,12 @@  #define CTS_RTS_SORTED	BIT(1)  #define RX_TX_CTS_RTS_SORTED	(RX_TX_SORTED | CTS_RTS_SORTED) +/* UART pin swap value */ +#define DEFAULT_IO_MACRO_IO0_IO1_MASK		GENMASK(3, 0) +#define IO_MACRO_IO0_SEL		0x3 +#define DEFAULT_IO_MACRO_IO2_IO3_MASK		GENMASK(15, 4) +#define IO_MACRO_IO2_IO3_SWAP		0x4640 +  #ifdef CONFIG_CONSOLE_POLL  #define CONSOLE_RX_BYTES_PW 1  #else @@ -113,12 +120,14 @@ struct qcom_geni_serial_port {  	unsigned int baud;  	unsigned int tx_bytes_pw;  	unsigned int rx_bytes_pw; -	u32 *rx_fifo; +	void *rx_fifo;  	u32 loopback;  	bool brk;  	unsigned int tx_remaining;  	int wakeup_irq; +	bool rx_tx_swap; +	bool cts_rts_swap;  };  static const struct uart_ops qcom_geni_console_pops; @@ -505,7 +514,6 @@ static int handle_rx_console(struct uart_port *uport, u32 bytes, bool drop)  static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop)  { -	unsigned char *buf;  	struct tty_port *tport;  	struct qcom_geni_serial_port *port = to_dev_port(uport, uport);  	u32 num_bytes_pw = port->tx_fifo_width / BITS_PER_BYTE; @@ -517,8 +525,7 @@ static int handle_rx_uart(struct uart_port *uport, u32 bytes, bool drop)  	if (drop)  		return 0; -	buf = (unsigned char *)port->rx_fifo; -	ret = tty_insert_flip_string(tport, buf, bytes); +	ret = tty_insert_flip_string(tport, port->rx_fifo, bytes);  	if (ret != bytes) {  		dev_err(uport->dev, "%s:Unable to push data ret %d_bytes %d\n",  				__func__, ret, bytes); @@ -818,17 +825,7 @@ static void get_tx_fifo_size(struct qcom_geni_serial_port *port)  static void qcom_geni_serial_shutdown(struct uart_port *uport)  { -	unsigned long flags; - -	/* Stop the console before stopping the current tx */ -	if (uart_console(uport)) -		console_stop(uport->cons); -  	disable_irq(uport->irq); -	spin_lock_irqsave(&uport->lock, flags); -	qcom_geni_serial_stop_tx(uport); -	qcom_geni_serial_stop_rx(uport); -	spin_unlock_irqrestore(&uport->lock, flags);  }  static int qcom_geni_serial_port_setup(struct uart_port *uport) @@ -836,6 +833,7 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport)  	struct qcom_geni_serial_port *port = to_dev_port(uport, uport);  	u32 rxstale = DEFAULT_BITS_PER_CHAR * STALE_TIMEOUT;  	u32 proto; +	u32 pin_swap;  	if (uart_console(uport)) {  		port->tx_bytes_pw = 1; @@ -856,6 +854,20 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport)  	get_tx_fifo_size(port);  	writel(rxstale, uport->membase + SE_UART_RX_STALE_CNT); + +	pin_swap = readl(uport->membase + SE_UART_IO_MACRO_CTRL); +	if (port->rx_tx_swap) { +		pin_swap &= ~DEFAULT_IO_MACRO_IO2_IO3_MASK; +		pin_swap |= IO_MACRO_IO2_IO3_SWAP; +	} +	if (port->cts_rts_swap) { +		pin_swap &= ~DEFAULT_IO_MACRO_IO0_IO1_MASK; +		pin_swap |= IO_MACRO_IO0_SEL; +	} +	/* Configure this register if RX-TX, CTS-RTS pins are swapped */ +	if (port->rx_tx_swap || port->cts_rts_swap) +		writel(pin_swap, uport->membase + SE_UART_IO_MACRO_CTRL); +  	/*  	 * Make an unconditional cancel on the main sequencer to reset  	 * it else we could end up in data loss scenarios. @@ -868,12 +880,6 @@ static int qcom_geni_serial_port_setup(struct uart_port *uport)  						false, false, true);  	geni_se_init(&port->se, UART_RX_WM, port->rx_fifo_depth - 2);  	geni_se_select_mode(&port->se, GENI_SE_FIFO); -	if (!uart_console(uport)) { -		port->rx_fifo = devm_kcalloc(uport->dev, -			port->rx_fifo_depth, sizeof(u32), GFP_KERNEL); -		if (!port->rx_fifo) -			return -ENOMEM; -	}  	port->setup = true;  	return 0; @@ -1284,6 +1290,13 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)  	port->rx_fifo_depth = DEF_FIFO_DEPTH_WORDS;  	port->tx_fifo_width = DEF_FIFO_WIDTH_BITS; +	if (!console) { +		port->rx_fifo = devm_kcalloc(uport->dev, +			port->rx_fifo_depth, sizeof(u32), GFP_KERNEL); +		if (!port->rx_fifo) +			return -ENOMEM; +	} +  	port->name = devm_kasprintf(uport->dev, GFP_KERNEL,  			"qcom_geni_serial_%s%d",  			uart_console(uport) ? "console" : "uart", uport->line); @@ -1299,6 +1312,12 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)  	if (!console)  		port->wakeup_irq = platform_get_irq_optional(pdev, 1); +	if (of_property_read_bool(pdev->dev.of_node, "rx-tx-swap")) +		port->rx_tx_swap = true; + +	if (of_property_read_bool(pdev->dev.of_node, "cts-rts-swap")) +		port->cts_rts_swap = true; +  	uport->private_data = drv;  	platform_set_drvdata(pdev, port);  	port->handle_rx = console ? handle_rx_console : handle_rx_uart; diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index 7d3ae31cc720..06e8071d5601 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -329,7 +329,7 @@ struct sc16is7xx_port {  	struct task_struct		*kworker_task;  	struct kthread_work		irq_work;  	struct mutex			efr_lock; -	struct sc16is7xx_one		p[0]; +	struct sc16is7xx_one		p[];  };  static unsigned long sc16is7xx_lines; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 76e506ee335c..66a5e2faf57e 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -20,6 +20,7 @@  #include <linux/device.h>  #include <linux/serial.h> /* for serial_state and serial_icounter_struct */  #include <linux/serial_core.h> +#include <linux/sysrq.h>  #include <linux/delay.h>  #include <linux/mutex.h>  #include <linux/security.h> @@ -40,6 +41,8 @@ static struct lock_class_key port_lock_key;  #define HIGH_BITS_OFFSET	((sizeof(long)-sizeof(int))*8) +#define SYSRQ_TIMEOUT	(HZ * 5) +  static void uart_change_speed(struct tty_struct *tty, struct uart_state *state,  					struct ktermios *old_termios);  static void uart_wait_until_sent(struct tty_struct *tty, int timeout); @@ -1908,6 +1911,24 @@ static int uart_proc_show(struct seq_file *m, void *v)  }  #endif +static inline bool uart_console_enabled(struct uart_port *port) +{ +	return uart_console(port) && (port->cons->flags & CON_ENABLED); +} + +/* + * Ensure that the serial console lock is initialised early. + * If this port is a console, then the spinlock is already initialised. + */ +static inline void uart_port_spin_lock_init(struct uart_port *port) +{ +	if (uart_console(port)) +		return; + +	spin_lock_init(&port->lock); +	lockdep_set_class(&port->lock, &port_lock_key); +} +  #if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(CONFIG_CONSOLE_POLL)  /**   *	uart_console_write - write a console message to a serial port @@ -2060,16 +2081,7 @@ uart_set_options(struct uart_port *port, struct console *co,  	struct ktermios termios;  	static struct ktermios dummy; -	/* -	 * Ensure that the serial console lock is initialised -	 * early. -	 * If this port is a console, then the spinlock is already -	 * initialised. -	 */ -	if (!(uart_console(port) && (port->cons->flags & CON_ENABLED))) { -		spin_lock_init(&port->lock); -		lockdep_set_class(&port->lock, &port_lock_key); -	} +	uart_port_spin_lock_init(port);  	memset(&termios, 0, sizeof(struct ktermios)); @@ -2605,7 +2617,7 @@ struct tty_driver *uart_console_device(struct console *co, int *index)  }  EXPORT_SYMBOL_GPL(uart_console_device); -static ssize_t uart_get_attr_uartclk(struct device *dev, +static ssize_t uartclk_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct serial_struct tmp; @@ -2615,7 +2627,7 @@ static ssize_t uart_get_attr_uartclk(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.baud_base * 16);  } -static ssize_t uart_get_attr_type(struct device *dev, +static ssize_t type_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct serial_struct tmp; @@ -2624,7 +2636,8 @@ static ssize_t uart_get_attr_type(struct device *dev,  	uart_get_info(port, &tmp);  	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.type);  } -static ssize_t uart_get_attr_line(struct device *dev, + +static ssize_t line_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct serial_struct tmp; @@ -2634,7 +2647,7 @@ static ssize_t uart_get_attr_line(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.line);  } -static ssize_t uart_get_attr_port(struct device *dev, +static ssize_t port_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct serial_struct tmp; @@ -2648,7 +2661,7 @@ static ssize_t uart_get_attr_port(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "0x%lX\n", ioaddr);  } -static ssize_t uart_get_attr_irq(struct device *dev, +static ssize_t irq_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct serial_struct tmp; @@ -2658,7 +2671,7 @@ static ssize_t uart_get_attr_irq(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.irq);  } -static ssize_t uart_get_attr_flags(struct device *dev, +static ssize_t flags_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct serial_struct tmp; @@ -2668,7 +2681,7 @@ static ssize_t uart_get_attr_flags(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "0x%X\n", tmp.flags);  } -static ssize_t uart_get_attr_xmit_fifo_size(struct device *dev, +static ssize_t xmit_fifo_size_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct serial_struct tmp; @@ -2678,8 +2691,7 @@ static ssize_t uart_get_attr_xmit_fifo_size(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.xmit_fifo_size);  } - -static ssize_t uart_get_attr_close_delay(struct device *dev, +static ssize_t close_delay_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct serial_struct tmp; @@ -2689,8 +2701,7 @@ static ssize_t uart_get_attr_close_delay(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.close_delay);  } - -static ssize_t uart_get_attr_closing_wait(struct device *dev, +static ssize_t closing_wait_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct serial_struct tmp; @@ -2700,7 +2711,7 @@ static ssize_t uart_get_attr_closing_wait(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.closing_wait);  } -static ssize_t uart_get_attr_custom_divisor(struct device *dev, +static ssize_t custom_divisor_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct serial_struct tmp; @@ -2710,7 +2721,7 @@ static ssize_t uart_get_attr_custom_divisor(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.custom_divisor);  } -static ssize_t uart_get_attr_io_type(struct device *dev, +static ssize_t io_type_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct serial_struct tmp; @@ -2720,7 +2731,7 @@ static ssize_t uart_get_attr_io_type(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.io_type);  } -static ssize_t uart_get_attr_iomem_base(struct device *dev, +static ssize_t iomem_base_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct serial_struct tmp; @@ -2730,7 +2741,7 @@ static ssize_t uart_get_attr_iomem_base(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "0x%lX\n", (unsigned long)tmp.iomem_base);  } -static ssize_t uart_get_attr_iomem_reg_shift(struct device *dev, +static ssize_t iomem_reg_shift_show(struct device *dev,  	struct device_attribute *attr, char *buf)  {  	struct serial_struct tmp; @@ -2740,40 +2751,92 @@ static ssize_t uart_get_attr_iomem_reg_shift(struct device *dev,  	return snprintf(buf, PAGE_SIZE, "%d\n", tmp.iomem_reg_shift);  } -static DEVICE_ATTR(type, S_IRUSR | S_IRGRP, uart_get_attr_type, NULL); -static DEVICE_ATTR(line, S_IRUSR | S_IRGRP, uart_get_attr_line, NULL); -static DEVICE_ATTR(port, S_IRUSR | S_IRGRP, uart_get_attr_port, NULL); -static DEVICE_ATTR(irq, S_IRUSR | S_IRGRP, uart_get_attr_irq, NULL); -static DEVICE_ATTR(flags, S_IRUSR | S_IRGRP, uart_get_attr_flags, NULL); -static DEVICE_ATTR(xmit_fifo_size, S_IRUSR | S_IRGRP, uart_get_attr_xmit_fifo_size, NULL); -static DEVICE_ATTR(uartclk, S_IRUSR | S_IRGRP, uart_get_attr_uartclk, NULL); -static DEVICE_ATTR(close_delay, S_IRUSR | S_IRGRP, uart_get_attr_close_delay, NULL); -static DEVICE_ATTR(closing_wait, S_IRUSR | S_IRGRP, uart_get_attr_closing_wait, NULL); -static DEVICE_ATTR(custom_divisor, S_IRUSR | S_IRGRP, uart_get_attr_custom_divisor, NULL); -static DEVICE_ATTR(io_type, S_IRUSR | S_IRGRP, uart_get_attr_io_type, NULL); -static DEVICE_ATTR(iomem_base, S_IRUSR | S_IRGRP, uart_get_attr_iomem_base, NULL); -static DEVICE_ATTR(iomem_reg_shift, S_IRUSR | S_IRGRP, uart_get_attr_iomem_reg_shift, NULL); +static ssize_t console_show(struct device *dev, +	struct device_attribute *attr, char *buf) +{ +	struct tty_port *port = dev_get_drvdata(dev); +	struct uart_state *state = container_of(port, struct uart_state, port); +	struct uart_port *uport; +	bool console = false; + +	mutex_lock(&port->mutex); +	uport = uart_port_check(state); +	if (uport) +		console = uart_console_enabled(uport); +	mutex_unlock(&port->mutex); + +	return sprintf(buf, "%c\n", console ? 'Y' : 'N'); +} + +static ssize_t console_store(struct device *dev, +	struct device_attribute *attr, const char *buf, size_t count) +{ +	struct tty_port *port = dev_get_drvdata(dev); +	struct uart_state *state = container_of(port, struct uart_state, port); +	struct uart_port *uport; +	bool oldconsole, newconsole; +	int ret; + +	ret = kstrtobool(buf, &newconsole); +	if (ret) +		return ret; + +	mutex_lock(&port->mutex); +	uport = uart_port_check(state); +	if (uport) { +		oldconsole = uart_console_enabled(uport); +		if (oldconsole && !newconsole) { +			ret = unregister_console(uport->cons); +		} else if (!oldconsole && newconsole) { +			if (uart_console(uport)) +				register_console(uport->cons); +			else +				ret = -ENOENT; +		} +	} else { +		ret = -ENXIO; +	} +	mutex_unlock(&port->mutex); + +	return ret < 0 ? ret : count; +} + +static DEVICE_ATTR_RO(uartclk); +static DEVICE_ATTR_RO(type); +static DEVICE_ATTR_RO(line); +static DEVICE_ATTR_RO(port); +static DEVICE_ATTR_RO(irq); +static DEVICE_ATTR_RO(flags); +static DEVICE_ATTR_RO(xmit_fifo_size); +static DEVICE_ATTR_RO(close_delay); +static DEVICE_ATTR_RO(closing_wait); +static DEVICE_ATTR_RO(custom_divisor); +static DEVICE_ATTR_RO(io_type); +static DEVICE_ATTR_RO(iomem_base); +static DEVICE_ATTR_RO(iomem_reg_shift); +static DEVICE_ATTR_RW(console);  static struct attribute *tty_dev_attrs[] = { +	&dev_attr_uartclk.attr,  	&dev_attr_type.attr,  	&dev_attr_line.attr,  	&dev_attr_port.attr,  	&dev_attr_irq.attr,  	&dev_attr_flags.attr,  	&dev_attr_xmit_fifo_size.attr, -	&dev_attr_uartclk.attr,  	&dev_attr_close_delay.attr,  	&dev_attr_closing_wait.attr,  	&dev_attr_custom_divisor.attr,  	&dev_attr_io_type.attr,  	&dev_attr_iomem_base.attr,  	&dev_attr_iomem_reg_shift.attr, -	NULL, -	}; +	&dev_attr_console.attr, +	NULL +};  static const struct attribute_group tty_dev_attr_group = {  	.attrs = tty_dev_attrs, -	}; +};  /**   *	uart_add_one_port - attach a driver-defined port structure @@ -2824,14 +2887,8 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)  		goto out;  	} -	/* -	 * If this port is a console, then the spinlock is already -	 * initialised. -	 */ -	if (!(uart_console(uport) && (uport->cons->flags & CON_ENABLED))) { -		spin_lock_init(&uport->lock); -		lockdep_set_class(&uport->lock, &port_lock_key); -	} +	uart_port_spin_lock_init(uport); +  	if (uport->cons && uport->dev)  		of_console_check(uport->dev->of_node, uport->cons->name, uport->line); @@ -3082,6 +3139,60 @@ void uart_insert_char(struct uart_port *port, unsigned int status,  }  EXPORT_SYMBOL_GPL(uart_insert_char); +#ifdef CONFIG_MAGIC_SYSRQ_SERIAL +static const char sysrq_toggle_seq[] = CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE; + +static void uart_sysrq_on(struct work_struct *w) +{ +	int sysrq_toggle_seq_len = strlen(sysrq_toggle_seq); + +	sysrq_toggle_support(1); +	pr_info("SysRq is enabled by magic sequence '%*pE' on serial\n", +		sysrq_toggle_seq_len, sysrq_toggle_seq); +} +static DECLARE_WORK(sysrq_enable_work, uart_sysrq_on); + +/** + *	uart_try_toggle_sysrq - Enables SysRq from serial line + *	@port: uart_port structure where char(s) after BREAK met + *	@ch: new character in the sequence after received BREAK + * + *	Enables magic SysRq when the required sequence is met on port + *	(see CONFIG_MAGIC_SYSRQ_SERIAL_SEQUENCE). + * + *	Returns false if @ch is out of enabling sequence and should be + *	handled some other way, true if @ch was consumed. + */ +static bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch) +{ +	int sysrq_toggle_seq_len = strlen(sysrq_toggle_seq); + +	if (!sysrq_toggle_seq_len) +		return false; + +	BUILD_BUG_ON(ARRAY_SIZE(sysrq_toggle_seq) >= U8_MAX); +	if (sysrq_toggle_seq[port->sysrq_seq] != ch) { +		port->sysrq_seq = 0; +		return false; +	} + +	if (++port->sysrq_seq < sysrq_toggle_seq_len) { +		port->sysrq = jiffies + SYSRQ_TIMEOUT; +		return true; +	} + +	schedule_work(&sysrq_enable_work); + +	port->sysrq = 0; +	return true; +} +#else +static inline bool uart_try_toggle_sysrq(struct uart_port *port, unsigned int ch) +{ +	return false; +} +#endif +  int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)  {  	if (!IS_ENABLED(CONFIG_MAGIC_SYSRQ_SERIAL)) @@ -3091,9 +3202,13 @@ int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)  		return 0;  	if (ch && time_before(jiffies, port->sysrq)) { -		handle_sysrq(ch); -		port->sysrq = 0; -		return 1; +		if (sysrq_mask()) { +			handle_sysrq(ch); +			port->sysrq = 0; +			return 1; +		} +		if (uart_try_toggle_sysrq(port, ch)) +			return 1;  	}  	port->sysrq = 0; @@ -3110,9 +3225,13 @@ int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch)  		return 0;  	if (ch && time_before(jiffies, port->sysrq)) { -		port->sysrq_ch = ch; -		port->sysrq = 0; -		return 1; +		if (sysrq_mask()) { +			port->sysrq_ch = ch; +			port->sysrq = 0; +			return 1; +		} +		if (uart_try_toggle_sysrq(port, ch)) +			return 1;  	}  	port->sysrq = 0; @@ -3120,22 +3239,19 @@ int uart_prepare_sysrq_char(struct uart_port *port, unsigned int ch)  }  EXPORT_SYMBOL_GPL(uart_prepare_sysrq_char); -void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long irqflags) +void uart_unlock_and_check_sysrq(struct uart_port *port, unsigned long flags) +__releases(&port->lock)  { -	int sysrq_ch; +	if (port->has_sysrq) { +		int sysrq_ch = port->sysrq_ch; -	if (!port->has_sysrq) { -		spin_unlock_irqrestore(&port->lock, irqflags); -		return; +		port->sysrq_ch = 0; +		spin_unlock_irqrestore(&port->lock, flags); +		if (sysrq_ch) +			handle_sysrq(sysrq_ch); +	} else { +		spin_unlock_irqrestore(&port->lock, flags);  	} - -	sysrq_ch = port->sysrq_ch; -	port->sysrq_ch = 0; - -	spin_unlock_irqrestore(&port->lock, irqflags); - -	if (sysrq_ch) -		handle_sysrq(sysrq_ch);  }  EXPORT_SYMBOL_GPL(uart_unlock_and_check_sysrq); @@ -3149,14 +3265,12 @@ int uart_handle_break(struct uart_port *port)  	if (port->handle_break)  		port->handle_break(port); -	if (port->has_sysrq) { -		if (port->cons && port->cons->index == port->line) { -			if (!port->sysrq) { -				port->sysrq = jiffies + HZ*5; -				return 1; -			} -			port->sysrq = 0; +	if (port->has_sysrq && uart_console(port)) { +		if (!port->sysrq) { +			port->sysrq = jiffies + SYSRQ_TIMEOUT; +			return 1;  		} +		port->sysrq = 0;  	}  	if (port->flags & UPF_SAK) diff --git a/drivers/tty/serial/serial_mctrl_gpio.h b/drivers/tty/serial/serial_mctrl_gpio.h index 1b2ff503b2c2..b134a0ffc894 100644 --- a/drivers/tty/serial/serial_mctrl_gpio.h +++ b/drivers/tty/serial/serial_mctrl_gpio.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */  /*   * Helpers for controlling modem lines via GPIO   * diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index c073aa7001c4..e1179e74a2b8 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -870,9 +870,16 @@ static void sci_receive_chars(struct uart_port *port)  				tty_insert_flip_char(tport, c, TTY_NORMAL);  		} else {  			for (i = 0; i < count; i++) { -				char c = serial_port_in(port, SCxRDR); - -				status = serial_port_in(port, SCxSR); +				char c; + +				if (port->type == PORT_SCIF || +				    port->type == PORT_HSCIF) { +					status = serial_port_in(port, SCxSR); +					c = serial_port_in(port, SCxRDR); +				} else { +					c = serial_port_in(port, SCxRDR); +					status = serial_port_in(port, SCxSR); +				}  				if (uart_handle_sysrq_char(port, c)) {  					count--; i--;  					continue; diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c index d5f81b98e4d7..13eadcb8aec4 100644 --- a/drivers/tty/serial/sifive.c +++ b/drivers/tty/serial/sifive.c @@ -618,10 +618,10 @@ static void sifive_serial_shutdown(struct uart_port *port)   *   * On the V0 SoC, the UART IP block is derived from the CPU clock source   * after a synchronous divide-by-two divider, so any CPU clock rate change - * requires the UART baud rate to be updated.  This presumably could corrupt any - * serial word currently being transmitted or received.  It would probably - * be better to stop receives and transmits, then complete the baud rate - * change, then re-enable them. + * requires the UART baud rate to be updated.  This presumably corrupts any + * serial word currently being transmitted or received.  In order to avoid + * corrupting the output data stream, we drain the transmit queue before + * allowing the clock's rate to be changed.   */  static int sifive_serial_clk_notifier(struct notifier_block *nb,  				      unsigned long event, void *data) @@ -629,6 +629,26 @@ static int sifive_serial_clk_notifier(struct notifier_block *nb,  	struct clk_notifier_data *cnd = data;  	struct sifive_serial_port *ssp = notifier_to_sifive_serial_port(nb); +	if (event == PRE_RATE_CHANGE) { +		/* +		 * The TX watermark is always set to 1 by this driver, which +		 * means that the TX busy bit will lower when there are 0 bytes +		 * left in the TX queue -- in other words, when the TX FIFO is +		 * empty. +		 */ +		__ssp_wait_for_xmitr(ssp); +		/* +		 * On the cycle the TX FIFO goes empty there is still a full +		 * UART frame left to be transmitted in the shift register. +		 * The UART provides no way for software to directly determine +		 * when that last frame has been transmitted, so we just sleep +		 * here instead.  As we're not tracking the number of stop bits +		 * they're just worst cased here.  The rest of the serial +		 * framing parameters aren't configurable by software. +		 */ +		udelay(DIV_ROUND_UP(12 * 1000 * 1000, ssp->baud_rate)); +	} +  	if (event == POST_RATE_CHANGE && ssp->clkin_rate != cnd->new_rate) {  		ssp->clkin_rate = cnd->new_rate;  		__ssp_update_div(ssp); @@ -709,6 +729,29 @@ static const char *sifive_serial_type(struct uart_port *port)  	return port->type == PORT_SIFIVE_V0 ? "SiFive UART v0" : NULL;  } +#ifdef CONFIG_CONSOLE_POLL +static int sifive_serial_poll_get_char(struct uart_port *port) +{ +	struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); +	char is_empty, ch; + +	ch = __ssp_receive_char(ssp, &is_empty); +	if (is_empty) +		return NO_POLL_CHAR; + +	return ch; +} + +static void sifive_serial_poll_put_char(struct uart_port *port, +					unsigned char c) +{ +	struct sifive_serial_port *ssp = port_to_sifive_serial_port(port); + +	__ssp_wait_for_xmitr(ssp); +	__ssp_transmit_char(ssp, c); +} +#endif /* CONFIG_CONSOLE_POLL */ +  /*   * Early console support   */ @@ -877,6 +920,10 @@ static const struct uart_ops sifive_serial_uops = {  	.request_port	= sifive_serial_request_port,  	.config_port	= sifive_serial_config_port,  	.verify_port	= sifive_serial_verify_port, +#ifdef CONFIG_CONSOLE_POLL +	.poll_get_char	= sifive_serial_poll_get_char, +	.poll_put_char	= sifive_serial_poll_put_char, +#endif  };  static struct uart_driver sifive_serial_uart_driver = { diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h index 637b09d3fe79..fb88ac565227 100644 --- a/drivers/tty/serial/sirfsoc_uart.h +++ b/drivers/tty/serial/sirfsoc_uart.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */  /*   * Drivers for CSR SiRFprimaII onboard UARTs.   * diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c index 3d3c70634589..9a7ae6384edf 100644 --- a/drivers/tty/serial/sprd_serial.c +++ b/drivers/tty/serial/sprd_serial.c @@ -1013,7 +1013,7 @@ static void sprd_console_write(struct console *co, const char *s,  		spin_unlock_irqrestore(&port->lock, flags);  } -static int __init sprd_console_setup(struct console *co, char *options) +static int sprd_console_setup(struct console *co, char *options)  {  	struct sprd_uart_port *sprd_uart_port;  	int baud = 115200; @@ -1102,29 +1102,6 @@ static struct uart_driver sprd_uart_driver = {  	.cons = SPRD_CONSOLE,  }; -static int sprd_probe_dt_alias(int index, struct device *dev) -{ -	struct device_node *np; -	int ret = index; - -	if (!IS_ENABLED(CONFIG_OF)) -		return ret; - -	np = dev->of_node; -	if (!np) -		return ret; - -	ret = of_alias_get_id(np, "serial"); -	if (ret < 0) -		ret = index; -	else if (ret >= ARRAY_SIZE(sprd_port) || sprd_port[ret] != NULL) { -		dev_warn(dev, "requested serial port %d not available.\n", ret); -		ret = index; -	} - -	return ret; -} -  static int sprd_remove(struct platform_device *dev)  {  	struct sprd_uart_port *sup = platform_get_drvdata(dev); @@ -1132,14 +1109,13 @@ static int sprd_remove(struct platform_device *dev)  	if (sup) {  		uart_remove_one_port(&sprd_uart_driver, &sup->port);  		sprd_port[sup->port.line] = NULL; +		sprd_rx_free_buf(sup);  		sprd_ports_num--;  	}  	if (!sprd_ports_num)  		uart_unregister_driver(&sprd_uart_driver); -	sprd_rx_free_buf(sup); -  	return 0;  } @@ -1147,7 +1123,8 @@ static bool sprd_uart_is_console(struct uart_port *uport)  {  	struct console *cons = sprd_uart_driver.cons; -	if (cons && cons->index >= 0 && cons->index == uport->line) +	if ((cons && cons->index >= 0 && cons->index == uport->line) || +	    of_console_check(uport->dev->of_node, SPRD_TTY_NAME, uport->line))  		return true;  	return false; @@ -1203,14 +1180,11 @@ static int sprd_probe(struct platform_device *pdev)  	int index;  	int ret; -	for (index = 0; index < ARRAY_SIZE(sprd_port); index++) -		if (sprd_port[index] == NULL) -			break; - -	if (index == ARRAY_SIZE(sprd_port)) -		return -EBUSY; - -	index = sprd_probe_dt_alias(index, &pdev->dev); +	index = of_alias_get_id(pdev->dev.of_node, "serial"); +	if (index < 0 || index >= ARRAY_SIZE(sprd_port)) { +		dev_err(&pdev->dev, "got a wrong serial alias id %d\n", index); +		return -EINVAL; +	}  	sprd_port[index] = devm_kzalloc(&pdev->dev, sizeof(*sprd_port[index]),  					GFP_KERNEL); @@ -1262,10 +1236,8 @@ static int sprd_probe(struct platform_device *pdev)  	sprd_ports_num++;  	ret = uart_add_one_port(&sprd_uart_driver, up); -	if (ret) { -		sprd_port[index] = NULL; +	if (ret)  		sprd_remove(pdev); -	}  	platform_set_drvdata(pdev, up); diff --git a/drivers/tty/serial/stm32-usart.h b/drivers/tty/serial/stm32-usart.h index a175c1094dc8..db8bf0d4982d 100644 --- a/drivers/tty/serial/stm32-usart.h +++ b/drivers/tty/serial/stm32-usart.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */  /*   * Copyright (C) Maxime Coquelin 2015   * Copyright (C) STMicroelectronics SA 2017 diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c index eafada8fb6fa..e35073e93a5b 100644 --- a/drivers/tty/serial/sunhv.c +++ b/drivers/tty/serial/sunhv.c @@ -567,6 +567,9 @@ static int hv_probe(struct platform_device *op)  	sunserial_console_match(&sunhv_console, op->dev.of_node,  				&sunhv_reg, port->line, false); +	/* We need to initialize lock even for non-registered console */ +	spin_lock_init(&port->lock); +  	err = uart_add_one_port(&sunhv_reg, port);  	if (err)  		goto out_unregister_driver; diff --git a/drivers/tty/serial/timbuart.h b/drivers/tty/serial/timbuart.h index fb00b172117d..007e59af636d 100644 --- a/drivers/tty/serial/timbuart.h +++ b/drivers/tty/serial/timbuart.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */  /*   * timbuart.c timberdale FPGA GPIO driver   * Copyright (c) 2009 Intel Corporation diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 98db9dc168ff..35e9e8faf8de 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -26,13 +26,15 @@  #define CDNS_UART_TTY_NAME	"ttyPS"  #define CDNS_UART_NAME		"xuartps" +#define CDNS_UART_MAJOR		0	/* use dynamic node allocation */ +#define CDNS_UART_MINOR		0	/* works best with devtmpfs */ +#define CDNS_UART_NR_PORTS	16  #define CDNS_UART_FIFO_SIZE	64	/* FIFO size */  #define CDNS_UART_REGISTER_SPACE	0x1000  #define TX_TIMEOUT		500000  /* Rx Trigger level */  static int rx_trigger_level = 56; -static int uartps_major;  module_param(rx_trigger_level, uint, 0444);  MODULE_PARM_DESC(rx_trigger_level, "Rx trigger level, 1-63 bytes"); @@ -188,7 +190,6 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255");   * @pclk:		APB clock   * @cdns_uart_driver:	Pointer to UART driver   * @baud:		Current baud rate - * @id:			Port ID   * @clk_rate_change_nb:	Notifier block for clock changes   * @quirks:		Flags for RXBS support.   */ @@ -198,7 +199,6 @@ struct cdns_uart {  	struct clk		*pclk;  	struct uart_driver	*cdns_uart_driver;  	unsigned int		baud; -	int			id;  	struct notifier_block	clk_rate_change_nb;  	u32			quirks;  	bool cts_override; @@ -650,8 +650,8 @@ static unsigned int cdns_uart_tx_empty(struct uart_port *port)  	unsigned int status;  	status = readl(port->membase + CDNS_UART_SR) & -				CDNS_UART_SR_TXEMPTY; -	return status ? TIOCSER_TEMT : 0; +		       (CDNS_UART_SR_TXEMPTY | CDNS_UART_SR_TACTIVE); +	return (status == CDNS_UART_SR_TXEMPTY) ? TIOCSER_TEMT : 0;  }  /** @@ -693,20 +693,8 @@ static void cdns_uart_set_termios(struct uart_port *port,  	u32 cval = 0;  	unsigned int baud, minbaud, maxbaud;  	unsigned long flags; -	unsigned int ctrl_reg, mode_reg, val; -	int err; - -	/* Wait for the transmit FIFO to empty before making changes */ -	if (!(readl(port->membase + CDNS_UART_CR) & -				CDNS_UART_CR_TX_DIS)) { -		err = readl_poll_timeout(port->membase + CDNS_UART_SR, -					 val, (val & CDNS_UART_SR_TXEMPTY), -					 1000, TX_TIMEOUT); -		if (err) { -			dev_err(port->dev, "timed out waiting for tx empty"); -			return; -		} -	} +	unsigned int ctrl_reg, mode_reg; +  	spin_lock_irqsave(&port->lock, flags);  	/* Disable the TX and RX to set baud rate */ @@ -1145,6 +1133,8 @@ static const struct uart_ops cdns_uart_ops = {  #endif  }; +static struct uart_driver cdns_uart_uart_driver; +  #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE  /**   * cdns_uart_console_putchar - write the character to the FIFO buffer @@ -1284,6 +1274,16 @@ static int cdns_uart_console_setup(struct console *co, char *options)  	return uart_set_options(port, co, baud, parity, bits, flow);  } + +static struct console cdns_uart_console = { +	.name	= CDNS_UART_TTY_NAME, +	.write	= cdns_uart_console_write, +	.device	= uart_console_device, +	.setup	= cdns_uart_console_setup, +	.flags	= CON_PRINTBUFFER, +	.index	= -1, /* Specified on the cmdline (e.g. console=ttyPS ) */ +	.data	= &cdns_uart_uart_driver, +};  #endif /* CONFIG_SERIAL_XILINX_PS_UART_CONSOLE */  #ifdef CONFIG_PM_SLEEP @@ -1415,89 +1415,8 @@ static const struct of_device_id cdns_uart_of_match[] = {  };  MODULE_DEVICE_TABLE(of, cdns_uart_of_match); -/* - * Maximum number of instances without alias IDs but if there is alias - * which target "< MAX_UART_INSTANCES" range this ID can't be used. - */ -#define MAX_UART_INSTANCES	32 - -/* Stores static aliases list */ -static DECLARE_BITMAP(alias_bitmap, MAX_UART_INSTANCES); -static int alias_bitmap_initialized; - -/* Stores actual bitmap of allocated IDs with alias IDs together */ -static DECLARE_BITMAP(bitmap, MAX_UART_INSTANCES); -/* Protect bitmap operations to have unique IDs */ -static DEFINE_MUTEX(bitmap_lock); - -static int cdns_get_id(struct platform_device *pdev) -{ -	int id, ret; - -	mutex_lock(&bitmap_lock); - -	/* Alias list is stable that's why get alias bitmap only once */ -	if (!alias_bitmap_initialized) { -		ret = of_alias_get_alias_list(cdns_uart_of_match, "serial", -					      alias_bitmap, MAX_UART_INSTANCES); -		if (ret && ret != -EOVERFLOW) { -			mutex_unlock(&bitmap_lock); -			return ret; -		} - -		alias_bitmap_initialized++; -	} - -	/* Make sure that alias ID is not taken by instance without alias */ -	bitmap_or(bitmap, bitmap, alias_bitmap, MAX_UART_INSTANCES); - -	dev_dbg(&pdev->dev, "Alias bitmap: %*pb\n", -		MAX_UART_INSTANCES, bitmap); - -	/* Look for a serialN alias */ -	id = of_alias_get_id(pdev->dev.of_node, "serial"); -	if (id < 0) { -		dev_warn(&pdev->dev, -			 "No serial alias passed. Using the first free id\n"); - -		/* -		 * Start with id 0 and check if there is no serial0 alias -		 * which points to device which is compatible with this driver. -		 * If alias exists then try next free position. -		 */ -		id = 0; - -		for (;;) { -			dev_info(&pdev->dev, "Checking id %d\n", id); -			id = find_next_zero_bit(bitmap, MAX_UART_INSTANCES, id); - -			/* No free empty instance */ -			if (id == MAX_UART_INSTANCES) { -				dev_err(&pdev->dev, "No free ID\n"); -				mutex_unlock(&bitmap_lock); -				return -EINVAL; -			} - -			dev_dbg(&pdev->dev, "The empty id is %d\n", id); -			/* Check if ID is empty */ -			if (!test_and_set_bit(id, bitmap)) { -				/* Break the loop if bit is taken */ -				dev_dbg(&pdev->dev, -					"Selected ID %d allocation passed\n", -					id); -				break; -			} -			dev_dbg(&pdev->dev, -				"Selected ID %d allocation failed\n", id); -			/* if taking bit fails then try next one */ -			id++; -		} -	} - -	mutex_unlock(&bitmap_lock); - -	return id; -} +/* Temporary variable for storing number of instances */ +static int instances;  /**   * cdns_uart_probe - Platform driver probe @@ -1507,16 +1426,11 @@ static int cdns_get_id(struct platform_device *pdev)   */  static int cdns_uart_probe(struct platform_device *pdev)  { -	int rc, irq; +	int rc, id, irq;  	struct uart_port *port;  	struct resource *res;  	struct cdns_uart *cdns_uart_data;  	const struct of_device_id *match; -	struct uart_driver *cdns_uart_uart_driver; -	char *driver_name; -#ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE -	struct console *cdns_uart_console; -#endif  	cdns_uart_data = devm_kzalloc(&pdev->dev, sizeof(*cdns_uart_data),  			GFP_KERNEL); @@ -1526,64 +1440,36 @@ static int cdns_uart_probe(struct platform_device *pdev)  	if (!port)  		return -ENOMEM; -	cdns_uart_uart_driver = devm_kzalloc(&pdev->dev, -					     sizeof(*cdns_uart_uart_driver), -					     GFP_KERNEL); -	if (!cdns_uart_uart_driver) -		return -ENOMEM; - -	cdns_uart_data->id = cdns_get_id(pdev); -	if (cdns_uart_data->id < 0) -		return cdns_uart_data->id; +	/* Look for a serialN alias */ +	id = of_alias_get_id(pdev->dev.of_node, "serial"); +	if (id < 0) +		id = 0; -	/* There is a need to use unique driver name */ -	driver_name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%s%d", -				     CDNS_UART_NAME, cdns_uart_data->id); -	if (!driver_name) { -		rc = -ENOMEM; -		goto err_out_id; +	if (id >= CDNS_UART_NR_PORTS) { +		dev_err(&pdev->dev, "Cannot get uart_port structure\n"); +		return -ENODEV;  	} -	cdns_uart_uart_driver->owner = THIS_MODULE; -	cdns_uart_uart_driver->driver_name = driver_name; -	cdns_uart_uart_driver->dev_name	= CDNS_UART_TTY_NAME; -	cdns_uart_uart_driver->major = uartps_major; -	cdns_uart_uart_driver->minor = cdns_uart_data->id; -	cdns_uart_uart_driver->nr = 1; - +	if (!cdns_uart_uart_driver.state) { +		cdns_uart_uart_driver.owner = THIS_MODULE; +		cdns_uart_uart_driver.driver_name = CDNS_UART_NAME; +		cdns_uart_uart_driver.dev_name = CDNS_UART_TTY_NAME; +		cdns_uart_uart_driver.major = CDNS_UART_MAJOR; +		cdns_uart_uart_driver.minor = CDNS_UART_MINOR; +		cdns_uart_uart_driver.nr = CDNS_UART_NR_PORTS;  #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE -	cdns_uart_console = devm_kzalloc(&pdev->dev, sizeof(*cdns_uart_console), -					 GFP_KERNEL); -	if (!cdns_uart_console) { -		rc = -ENOMEM; -		goto err_out_id; -	} - -	strncpy(cdns_uart_console->name, CDNS_UART_TTY_NAME, -		sizeof(cdns_uart_console->name)); -	cdns_uart_console->index = cdns_uart_data->id; -	cdns_uart_console->write = cdns_uart_console_write; -	cdns_uart_console->device = uart_console_device; -	cdns_uart_console->setup = cdns_uart_console_setup; -	cdns_uart_console->flags = CON_PRINTBUFFER; -	cdns_uart_console->data = cdns_uart_uart_driver; -	cdns_uart_uart_driver->cons = cdns_uart_console; +		cdns_uart_uart_driver.cons = &cdns_uart_console; +		cdns_uart_console.index = id;  #endif -	rc = uart_register_driver(cdns_uart_uart_driver); -	if (rc < 0) { -		dev_err(&pdev->dev, "Failed to register driver\n"); -		goto err_out_id; +		rc = uart_register_driver(&cdns_uart_uart_driver); +		if (rc < 0) { +			dev_err(&pdev->dev, "Failed to register driver\n"); +			return rc; +		}  	} -	cdns_uart_data->cdns_uart_driver = cdns_uart_uart_driver; - -	/* -	 * Setting up proper name_base needs to be done after uart -	 * registration because tty_driver structure is not filled. -	 * name_base is 0 by default. -	 */ -	cdns_uart_uart_driver->tty_driver->name_base = cdns_uart_data->id; +	cdns_uart_data->cdns_uart_driver = &cdns_uart_uart_driver;  	match = of_match_node(cdns_uart_of_match, pdev->dev.of_node);  	if (match && match->data) { @@ -1661,6 +1547,7 @@ static int cdns_uart_probe(struct platform_device *pdev)  	port->ops	= &cdns_uart_ops;  	port->fifosize	= CDNS_UART_FIFO_SIZE;  	port->has_sysrq = IS_ENABLED(CONFIG_SERIAL_XILINX_PS_UART_CONSOLE); +	port->line	= id;  	/*  	 * Register the port. @@ -1692,7 +1579,7 @@ static int cdns_uart_probe(struct platform_device *pdev)  		console_port = port;  #endif -	rc = uart_add_one_port(cdns_uart_uart_driver, port); +	rc = uart_add_one_port(&cdns_uart_uart_driver, port);  	if (rc) {  		dev_err(&pdev->dev,  			"uart_add_one_port() failed; err=%i\n", rc); @@ -1702,13 +1589,15 @@ static int cdns_uart_probe(struct platform_device *pdev)  #ifdef CONFIG_SERIAL_XILINX_PS_UART_CONSOLE  	/* This is not port which is used for console that's why clean it up */  	if (console_port == port && -	    !(cdns_uart_uart_driver->cons->flags & CON_ENABLED)) +	    !(cdns_uart_uart_driver.cons->flags & CON_ENABLED))  		console_port = NULL;  #endif -	uartps_major = cdns_uart_uart_driver->tty_driver->major;  	cdns_uart_data->cts_override = of_property_read_bool(pdev->dev.of_node,  							     "cts-override"); + +	instances++; +  	return 0;  err_out_pm_disable: @@ -1724,12 +1613,8 @@ err_out_clk_disable:  err_out_clk_dis_pclk:  	clk_disable_unprepare(cdns_uart_data->pclk);  err_out_unregister_driver: -	uart_unregister_driver(cdns_uart_data->cdns_uart_driver); -err_out_id: -	mutex_lock(&bitmap_lock); -	if (cdns_uart_data->id < MAX_UART_INSTANCES) -		clear_bit(cdns_uart_data->id, bitmap); -	mutex_unlock(&bitmap_lock); +	if (!instances) +		uart_unregister_driver(cdns_uart_data->cdns_uart_driver);  	return rc;  } @@ -1752,10 +1637,6 @@ static int cdns_uart_remove(struct platform_device *pdev)  #endif  	rc = uart_remove_one_port(cdns_uart_data->cdns_uart_driver, port);  	port->mapbase = 0; -	mutex_lock(&bitmap_lock); -	if (cdns_uart_data->id < MAX_UART_INSTANCES) -		clear_bit(cdns_uart_data->id, bitmap); -	mutex_unlock(&bitmap_lock);  	clk_disable_unprepare(cdns_uart_data->uartclk);  	clk_disable_unprepare(cdns_uart_data->pclk);  	pm_runtime_disable(&pdev->dev); @@ -1768,13 +1649,8 @@ static int cdns_uart_remove(struct platform_device *pdev)  		console_port = NULL;  #endif -	/* If this is last instance major number should be initialized */ -	mutex_lock(&bitmap_lock); -	if (bitmap_empty(bitmap, MAX_UART_INSTANCES)) -		uartps_major = 0; -	mutex_unlock(&bitmap_lock); - -	uart_unregister_driver(cdns_uart_data->cdns_uart_driver); +	if (!--instances) +		uart_unregister_driver(cdns_uart_data->cdns_uart_driver);  	return rc;  } diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index f724962a5906..0dc3878794fd 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -63,6 +63,19 @@ static bool sysrq_on(void)  	return sysrq_enabled || sysrq_always_enabled;  } +/** + * sysrq_mask - Getter for sysrq_enabled mask. + * + * Return: 1 if sysrq is always enabled, enabled sysrq_key_op mask otherwise. + */ +int sysrq_mask(void) +{ +	if (sysrq_always_enabled) +		return 1; +	return sysrq_enabled; +} +EXPORT_SYMBOL_GPL(sysrq_mask); +  /*   * A value of 1 means 'all', other nonzero values are an op mask:   */ @@ -1046,6 +1059,7 @@ int sysrq_toggle_support(int enable_mask)  	return 0;  } +EXPORT_SYMBOL_GPL(sysrq_toggle_support);  static int __sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,                                  struct sysrq_key_op *remove_op_p) diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index d7d2e4b844bc..d54a549c5892 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -35,18 +35,18 @@  /* Don't take this from <ctype.h>: 011-015 on the screen aren't spaces */  #define isspace(c)	((c) == ' ') -extern void poke_blanked_console(void); -  /* FIXME: all this needs locking */ -/* Variables for selection control. */ -/* Use a dynamic buffer, instead of static (Dec 1994) */ -struct vc_data *sel_cons;		/* must not be deallocated */ -static int use_unicode; -static volatile int sel_start = -1; 	/* cleared by clear_selection */ -static int sel_end; -static int sel_buffer_lth; -static char *sel_buffer; -static DEFINE_MUTEX(sel_lock); +static struct vc_selection { +	struct mutex lock; +	struct vc_data *cons;			/* must not be deallocated */ +	char *buffer; +	unsigned int buf_len; +	volatile int start;			/* cleared by clear_selection */ +	int end; +} vc_sel = { +	.lock = __MUTEX_INITIALIZER(vc_sel.lock), +	.start = -1, +};  /* clear_selection, highlight and highlight_pointer can be called     from interrupt (via scrollback/front) */ @@ -54,22 +54,21 @@ static DEFINE_MUTEX(sel_lock);  /* set reverse video on characters s-e of console with selection. */  static inline void highlight(const int s, const int e)  { -	invert_screen(sel_cons, s, e-s+2, 1); +	invert_screen(vc_sel.cons, s, e-s+2, 1);  }  /* use complementary color to show the pointer */  static inline void highlight_pointer(const int where)  { -	complement_pos(sel_cons, where); +	complement_pos(vc_sel.cons, where);  }  static u32 -sel_pos(int n) +sel_pos(int n, bool unicode)  { -	if (use_unicode) -		return screen_glyph_unicode(sel_cons, n / 2); -	return inverse_translate(sel_cons, screen_glyph(sel_cons, n), -				0); +	if (unicode) +		return screen_glyph_unicode(vc_sel.cons, n / 2); +	return inverse_translate(vc_sel.cons, screen_glyph(vc_sel.cons, n), 0);  }  /** @@ -81,13 +80,18 @@ sel_pos(int n)  void clear_selection(void)  {  	highlight_pointer(-1); /* hide the pointer */ -	if (sel_start != -1) { -		highlight(sel_start, sel_end); -		sel_start = -1; +	if (vc_sel.start != -1) { +		highlight(vc_sel.start, vc_sel.end); +		vc_sel.start = -1;  	}  }  EXPORT_SYMBOL_GPL(clear_selection); +bool vc_is_sel(struct vc_data *vc) +{ +	return vc == vc_sel.cons; +} +  /*   * User settable table: what characters are to be considered alphabetic?   * 128 bits. Locked by the console lock. @@ -186,9 +190,10 @@ static int __set_selection_kernel(struct tiocl_selection *v, struct tty_struct *  	struct vc_data *vc = vc_cons[fg_console].d;  	int new_sel_start, new_sel_end, spc;  	char *bp, *obp; -	int i, ps, pe, multiplier; +	int i, ps, pe;  	u32 c; -	int mode, ret = 0; +	int ret = 0; +	bool unicode;  	poke_blanked_console(); @@ -211,57 +216,51 @@ static int __set_selection_kernel(struct tiocl_selection *v, struct tty_struct *  		return 0;  	} -	if (ps > pe)	/* make sel_start <= sel_end */ +	if (ps > pe)	/* make vc_sel.start <= vc_sel.end */  		swap(ps, pe); -	if (sel_cons != vc_cons[fg_console].d) { +	if (vc_sel.cons != vc_cons[fg_console].d) {  		clear_selection(); -		sel_cons = vc_cons[fg_console].d; +		vc_sel.cons = vc_cons[fg_console].d;  	} -	mode = vt_do_kdgkbmode(fg_console); -	if (mode == K_UNICODE) -		use_unicode = 1; -	else -		use_unicode = 0; - -	switch (v->sel_mode) -	{ -		case TIOCL_SELCHAR:	/* character-by-character selection */ +	unicode = vt_do_kdgkbmode(fg_console) == K_UNICODE; + +	switch (v->sel_mode) { +	case TIOCL_SELCHAR:	/* character-by-character selection */ +		new_sel_start = ps; +		new_sel_end = pe; +		break; +	case TIOCL_SELWORD:	/* word-by-word selection */ +		spc = isspace(sel_pos(ps, unicode)); +		for (new_sel_start = ps; ; ps -= 2) { +			if ((spc && !isspace(sel_pos(ps, unicode))) || +			    (!spc && !inword(sel_pos(ps, unicode)))) +				break;  			new_sel_start = ps; +			if (!(ps % vc->vc_size_row)) +				break; +		} + +		spc = isspace(sel_pos(pe, unicode)); +		for (new_sel_end = pe; ; pe += 2) { +			if ((spc && !isspace(sel_pos(pe, unicode))) || +			    (!spc && !inword(sel_pos(pe, unicode)))) +				break;  			new_sel_end = pe; -			break; -		case TIOCL_SELWORD:	/* word-by-word selection */ -			spc = isspace(sel_pos(ps)); -			for (new_sel_start = ps; ; ps -= 2) -			{ -				if ((spc && !isspace(sel_pos(ps))) || -				    (!spc && !inword(sel_pos(ps)))) -					break; -				new_sel_start = ps; -				if (!(ps % vc->vc_size_row)) -					break; -			} -			spc = isspace(sel_pos(pe)); -			for (new_sel_end = pe; ; pe += 2) -			{ -				if ((spc && !isspace(sel_pos(pe))) || -				    (!spc && !inword(sel_pos(pe)))) -					break; -				new_sel_end = pe; -				if (!((pe + 2) % vc->vc_size_row)) -					break; -			} -			break; -		case TIOCL_SELLINE:	/* line-by-line selection */ -			new_sel_start = ps - ps % vc->vc_size_row; -			new_sel_end = pe + vc->vc_size_row -				    - pe % vc->vc_size_row - 2; -			break; -		case TIOCL_SELPOINTER: -			highlight_pointer(pe); -			return 0; -		default: -			return -EINVAL; +			if (!((pe + 2) % vc->vc_size_row)) +				break; +		} +		break; +	case TIOCL_SELLINE:	/* line-by-line selection */ +		new_sel_start = rounddown(ps, vc->vc_size_row); +		new_sel_end = rounddown(pe, vc->vc_size_row) + +			vc->vc_size_row - 2; +		break; +	case TIOCL_SELPOINTER: +		highlight_pointer(pe); +		return 0; +	default: +		return -EINVAL;  	}  	/* remove the pointer */ @@ -270,56 +269,56 @@ static int __set_selection_kernel(struct tiocl_selection *v, struct tty_struct *  	/* select to end of line if on trailing space */  	if (new_sel_end > new_sel_start &&  		!atedge(new_sel_end, vc->vc_size_row) && -		isspace(sel_pos(new_sel_end))) { +		isspace(sel_pos(new_sel_end, unicode))) {  		for (pe = new_sel_end + 2; ; pe += 2) -			if (!isspace(sel_pos(pe)) || +			if (!isspace(sel_pos(pe, unicode)) ||  			    atedge(pe, vc->vc_size_row))  				break; -		if (isspace(sel_pos(pe))) +		if (isspace(sel_pos(pe, unicode)))  			new_sel_end = pe;  	} -	if (sel_start == -1)	/* no current selection */ +	if (vc_sel.start == -1)	/* no current selection */  		highlight(new_sel_start, new_sel_end); -	else if (new_sel_start == sel_start) +	else if (new_sel_start == vc_sel.start)  	{ -		if (new_sel_end == sel_end)	/* no action required */ +		if (new_sel_end == vc_sel.end)	/* no action required */  			return 0; -		else if (new_sel_end > sel_end)	/* extend to right */ -			highlight(sel_end + 2, new_sel_end); +		else if (new_sel_end > vc_sel.end)	/* extend to right */ +			highlight(vc_sel.end + 2, new_sel_end);  		else				/* contract from right */ -			highlight(new_sel_end + 2, sel_end); +			highlight(new_sel_end + 2, vc_sel.end);  	} -	else if (new_sel_end == sel_end) +	else if (new_sel_end == vc_sel.end)  	{ -		if (new_sel_start < sel_start)	/* extend to left */ -			highlight(new_sel_start, sel_start - 2); +		if (new_sel_start < vc_sel.start) /* extend to left */ +			highlight(new_sel_start, vc_sel.start - 2);  		else				/* contract from left */ -			highlight(sel_start, new_sel_start - 2); +			highlight(vc_sel.start, new_sel_start - 2);  	}  	else	/* some other case; start selection from scratch */  	{  		clear_selection();  		highlight(new_sel_start, new_sel_end);  	} -	sel_start = new_sel_start; -	sel_end = new_sel_end; +	vc_sel.start = new_sel_start; +	vc_sel.end = new_sel_end;  	/* Allocate a new buffer before freeing the old one ... */ -	multiplier = use_unicode ? 4 : 1;  /* chars can take up to 4 bytes */ -	bp = kmalloc_array((sel_end - sel_start) / 2 + 1, multiplier, +	/* chars can take up to 4 bytes with unicode */ +	bp = kmalloc_array((vc_sel.end - vc_sel.start) / 2 + 1, unicode ? 4 : 1,  			   GFP_KERNEL);  	if (!bp) {  		printk(KERN_WARNING "selection: kmalloc() failed\n");  		clear_selection();  		return -ENOMEM;  	} -	kfree(sel_buffer); -	sel_buffer = bp; +	kfree(vc_sel.buffer); +	vc_sel.buffer = bp;  	obp = bp; -	for (i = sel_start; i <= sel_end; i += 2) { -		c = sel_pos(i); -		if (use_unicode) +	for (i = vc_sel.start; i <= vc_sel.end; i += 2) { +		c = sel_pos(i, unicode); +		if (unicode)  			bp += store_utf8(c, bp);  		else  			*bp++ = c; @@ -335,7 +334,7 @@ static int __set_selection_kernel(struct tiocl_selection *v, struct tty_struct *  			obp = bp;  		}  	} -	sel_buffer_lth = bp - sel_buffer; +	vc_sel.buf_len = bp - vc_sel.buffer;  	return ret;  } @@ -344,11 +343,11 @@ int set_selection_kernel(struct tiocl_selection *v, struct tty_struct *tty)  {  	int ret; -	mutex_lock(&sel_lock); +	mutex_lock(&vc_sel.lock);  	console_lock();  	ret = __set_selection_kernel(v, tty);  	console_unlock(); -	mutex_unlock(&sel_lock); +	mutex_unlock(&vc_sel.lock);  	return ret;  } @@ -380,26 +379,26 @@ int paste_selection(struct tty_struct *tty)  	tty_buffer_lock_exclusive(&vc->port);  	add_wait_queue(&vc->paste_wait, &wait); -	mutex_lock(&sel_lock); -	while (sel_buffer && sel_buffer_lth > pasted) { +	mutex_lock(&vc_sel.lock); +	while (vc_sel.buffer && vc_sel.buf_len > pasted) {  		set_current_state(TASK_INTERRUPTIBLE);  		if (signal_pending(current)) {  			ret = -EINTR;  			break;  		}  		if (tty_throttled(tty)) { -			mutex_unlock(&sel_lock); +			mutex_unlock(&vc_sel.lock);  			schedule(); -			mutex_lock(&sel_lock); +			mutex_lock(&vc_sel.lock);  			continue;  		}  		__set_current_state(TASK_RUNNING); -		count = sel_buffer_lth - pasted; -		count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, NULL, +		count = vc_sel.buf_len - pasted; +		count = tty_ldisc_receive_buf(ld, vc_sel.buffer + pasted, NULL,  					      count);  		pasted += count;  	} -	mutex_unlock(&sel_lock); +	mutex_unlock(&vc_sel.lock);  	remove_wait_queue(&vc->paste_wait, &wait);  	__set_current_state(TASK_RUNNING); diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 15d27698054a..48a8199f7845 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -81,6 +81,7 @@  #include <linux/errno.h>  #include <linux/kd.h>  #include <linux/slab.h> +#include <linux/vmalloc.h>  #include <linux/major.h>  #include <linux/mm.h>  #include <linux/console.h> @@ -350,7 +351,7 @@ static struct uni_screen *vc_uniscr_alloc(unsigned int cols, unsigned int rows)  	/* allocate everything in one go */  	memsize = cols * rows * sizeof(char32_t);  	memsize += rows * sizeof(char32_t *); -	p = kmalloc(memsize, GFP_KERNEL); +	p = vmalloc(memsize);  	if (!p)  		return NULL; @@ -364,9 +365,14 @@ static struct uni_screen *vc_uniscr_alloc(unsigned int cols, unsigned int rows)  	return uniscr;  } +static void vc_uniscr_free(struct uni_screen *uniscr) +{ +	vfree(uniscr); +} +  static void vc_uniscr_set(struct vc_data *vc, struct uni_screen *new_uniscr)  { -	kfree(vc->vc_uni_screen); +	vc_uniscr_free(vc->vc_uni_screen);  	vc->vc_uni_screen = new_uniscr;  } @@ -890,8 +896,9 @@ static void hide_softcursor(struct vc_data *vc)  static void hide_cursor(struct vc_data *vc)  { -	if (vc == sel_cons) +	if (vc_is_sel(vc))  		clear_selection(); +  	vc->vc_sw->con_cursor(vc, CM_ERASE);  	hide_softcursor(vc);  } @@ -901,7 +908,7 @@ static void set_cursor(struct vc_data *vc)  	if (!con_is_fg(vc) || console_blanked || vc->vc_mode == KD_GRAPHICS)  		return;  	if (vc->vc_deccm) { -		if (vc == sel_cons) +		if (vc_is_sel(vc))  			clear_selection();  		add_softcursor(vc);  		if ((vc->vc_cursor_type & 0x0f) != 1) @@ -1074,6 +1081,17 @@ static void visual_deinit(struct vc_data *vc)  	module_put(vc->vc_sw->owner);  } +static void vc_port_destruct(struct tty_port *port) +{ +	struct vc_data *vc = container_of(port, struct vc_data, port); + +	kfree(vc); +} + +static const struct tty_port_operations vc_port_ops = { +	.destruct = vc_port_destruct, +}; +  int vc_allocate(unsigned int currcons)	/* return 0 on success */  {  	struct vt_notifier_param param; @@ -1099,6 +1117,7 @@ int vc_allocate(unsigned int currcons)	/* return 0 on success */  	vc_cons[currcons].d = vc;  	tty_port_init(&vc->port); +	vc->port.ops = &vc_port_ops;  	INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);  	visual_init(vc, currcons, 1); @@ -1193,7 +1212,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,  	if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)  		return 0; -	if (new_screen_size > (4 << 20)) +	if (new_screen_size > KMALLOC_MAX_SIZE)  		return -EINVAL;  	newscreen = kzalloc(new_screen_size, GFP_USER);  	if (!newscreen) @@ -1207,7 +1226,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,  		}  	} -	if (vc == sel_cons) +	if (vc_is_sel(vc))  		clear_selection();  	old_rows = vc->vc_rows; @@ -1216,7 +1235,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,  	err = resize_screen(vc, new_cols, new_rows, user);  	if (err) {  		kfree(newscreen); -		kfree(new_uniscr); +		vc_uniscr_free(new_uniscr);  		return err;  	} @@ -1901,67 +1920,65 @@ static void set_mode(struct vc_data *vc, int on_off)  /* console_lock is held */  static void setterm_command(struct vc_data *vc)  { -	switch(vc->vc_par[0]) { -		case 1:	/* set color for underline mode */ -			if (vc->vc_can_do_color && -					vc->vc_par[1] < 16) { -				vc->vc_ulcolor = color_table[vc->vc_par[1]]; -				if (vc->vc_underline) -					update_attr(vc); -			} -			break; -		case 2:	/* set color for half intensity mode */ -			if (vc->vc_can_do_color && -					vc->vc_par[1] < 16) { -				vc->vc_halfcolor = color_table[vc->vc_par[1]]; -				if (vc->vc_intensity == 0) -					update_attr(vc); -			} -			break; -		case 8:	/* store colors as defaults */ -			vc->vc_def_color = vc->vc_attr; -			if (vc->vc_hi_font_mask == 0x100) -				vc->vc_def_color >>= 1; -			default_attr(vc); -			update_attr(vc); -			break; -		case 9:	/* set blanking interval */ -			blankinterval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60; -			poke_blanked_console(); -			break; -		case 10: /* set bell frequency in Hz */ -			if (vc->vc_npar >= 1) -				vc->vc_bell_pitch = vc->vc_par[1]; -			else -				vc->vc_bell_pitch = DEFAULT_BELL_PITCH; -			break; -		case 11: /* set bell duration in msec */ -			if (vc->vc_npar >= 1) -				vc->vc_bell_duration = (vc->vc_par[1] < 2000) ? -					msecs_to_jiffies(vc->vc_par[1]) : 0; -			else -				vc->vc_bell_duration = DEFAULT_BELL_DURATION; -			break; -		case 12: /* bring specified console to the front */ -			if (vc->vc_par[1] >= 1 && vc_cons_allocated(vc->vc_par[1] - 1)) -				set_console(vc->vc_par[1] - 1); -			break; -		case 13: /* unblank the screen */ -			poke_blanked_console(); -			break; -		case 14: /* set vesa powerdown interval */ -			vesa_off_interval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60 * HZ; -			break; -		case 15: /* activate the previous console */ -			set_console(last_console); -			break; -		case 16: /* set cursor blink duration in msec */ -			if (vc->vc_npar >= 1 && vc->vc_par[1] >= 50 && -					vc->vc_par[1] <= USHRT_MAX) -				vc->vc_cur_blink_ms = vc->vc_par[1]; -			else -				vc->vc_cur_blink_ms = DEFAULT_CURSOR_BLINK_MS; -			break; +	switch (vc->vc_par[0]) { +	case 1:	/* set color for underline mode */ +		if (vc->vc_can_do_color && vc->vc_par[1] < 16) { +			vc->vc_ulcolor = color_table[vc->vc_par[1]]; +			if (vc->vc_underline) +				update_attr(vc); +		} +		break; +	case 2:	/* set color for half intensity mode */ +		if (vc->vc_can_do_color && vc->vc_par[1] < 16) { +			vc->vc_halfcolor = color_table[vc->vc_par[1]]; +			if (vc->vc_intensity == 0) +				update_attr(vc); +		} +		break; +	case 8:	/* store colors as defaults */ +		vc->vc_def_color = vc->vc_attr; +		if (vc->vc_hi_font_mask == 0x100) +			vc->vc_def_color >>= 1; +		default_attr(vc); +		update_attr(vc); +		break; +	case 9:	/* set blanking interval */ +		blankinterval = min(vc->vc_par[1], 60U) * 60; +		poke_blanked_console(); +		break; +	case 10: /* set bell frequency in Hz */ +		if (vc->vc_npar >= 1) +			vc->vc_bell_pitch = vc->vc_par[1]; +		else +			vc->vc_bell_pitch = DEFAULT_BELL_PITCH; +		break; +	case 11: /* set bell duration in msec */ +		if (vc->vc_npar >= 1) +			vc->vc_bell_duration = (vc->vc_par[1] < 2000) ? +				msecs_to_jiffies(vc->vc_par[1]) : 0; +		else +			vc->vc_bell_duration = DEFAULT_BELL_DURATION; +		break; +	case 12: /* bring specified console to the front */ +		if (vc->vc_par[1] >= 1 && vc_cons_allocated(vc->vc_par[1] - 1)) +			set_console(vc->vc_par[1] - 1); +		break; +	case 13: /* unblank the screen */ +		poke_blanked_console(); +		break; +	case 14: /* set vesa powerdown interval */ +		vesa_off_interval = min(vc->vc_par[1], 60U) * 60 * HZ; +		break; +	case 15: /* activate the previous console */ +		set_console(last_console); +		break; +	case 16: /* set cursor blink duration in msec */ +		if (vc->vc_npar >= 1 && vc->vc_par[1] >= 50 && +				vc->vc_par[1] <= USHRT_MAX) +			vc->vc_cur_blink_ms = vc->vc_par[1]; +		else +			vc->vc_cur_blink_ms = DEFAULT_CURSOR_BLINK_MS; +		break;  	}  } @@ -2576,8 +2593,6 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co  	if (in_interrupt())  		return count; -	might_sleep(); -  	console_lock();  	vc = tty->driver_data;  	if (vc == NULL) { @@ -3253,6 +3268,7 @@ static int con_install(struct tty_driver *driver, struct tty_struct *tty)  	tty->driver_data = vc;  	vc->port.tty = tty; +	tty_port_get(&vc->port);  	if (!tty->winsize.ws_row && !tty->winsize.ws_col) {  		tty->winsize.ws_row = vc_cons[currcons].d->vc_rows; @@ -3288,6 +3304,13 @@ static void con_shutdown(struct tty_struct *tty)  	console_unlock();  } +static void con_cleanup(struct tty_struct *tty) +{ +	struct vc_data *vc = tty->driver_data; + +	tty_port_put(&vc->port); +} +  static int default_color           = 7; /* white */  static int default_italic_color    = 2; // green (ASCII)  static int default_underline_color = 3; // cyan (ASCII) @@ -3413,7 +3436,8 @@ static const struct tty_operations con_ops = {  	.throttle = con_throttle,  	.unthrottle = con_unthrottle,  	.resize = vt_resize, -	.shutdown = con_shutdown +	.shutdown = con_shutdown, +	.cleanup = con_cleanup,  };  static struct cdev vc0_cdev; diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index ee6c91ef1f6c..daf61c28ba76 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -39,11 +39,32 @@  #include <linux/kbd_diacr.h>  #include <linux/selection.h> -char vt_dont_switch; -extern struct tty_driver *console_driver; +bool vt_dont_switch; -#define VT_IS_IN_USE(i)	(console_driver->ttys[i] && console_driver->ttys[i]->count) -#define VT_BUSY(i)	(VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons) +static inline bool vt_in_use(unsigned int i) +{ +	const struct vc_data *vc = vc_cons[i].d; + +	/* +	 * console_lock must be held to prevent the vc from being deallocated +	 * while we're checking whether it's in-use. +	 */ +	WARN_CONSOLE_UNLOCKED(); + +	return vc && kref_read(&vc->port.kref) > 1; +} + +static inline bool vt_busy(int i) +{ +	if (vt_in_use(i)) +		return true; +	if (i == fg_console) +		return true; +	if (vc_is_sel(vc_cons[i].d)) +		return true; + +	return false; +}  /*   * Console (vt and kd) routines, as defined by USL SVR4 manual, and by @@ -289,16 +310,14 @@ static int vt_disallocate(unsigned int vc_num)  	int ret = 0;  	console_lock(); -	if (VT_BUSY(vc_num)) +	if (vt_busy(vc_num))  		ret = -EBUSY;  	else if (vc_num)  		vc = vc_deallocate(vc_num);  	console_unlock(); -	if (vc && vc_num >= MIN_NR_CONSOLES) { -		tty_port_destroy(&vc->port); -		kfree(vc); -	} +	if (vc && vc_num >= MIN_NR_CONSOLES) +		tty_port_put(&vc->port);  	return ret;  } @@ -311,17 +330,15 @@ static void vt_disallocate_all(void)  	console_lock();  	for (i = 1; i < MAX_NR_CONSOLES; i++) -		if (!VT_BUSY(i)) +		if (!vt_busy(i))  			vc[i] = vc_deallocate(i);  		else  			vc[i] = NULL;  	console_unlock();  	for (i = 1; i < MAX_NR_CONSOLES; i++) { -		if (vc[i] && i >= MIN_NR_CONSOLES) { -			tty_port_destroy(&vc[i]->port); -			kfree(vc[i]); -		} +		if (vc[i] && i >= MIN_NR_CONSOLES) +			tty_port_put(&vc[i]->port);  	}  } @@ -335,22 +352,13 @@ int vt_ioctl(struct tty_struct *tty,  {  	struct vc_data *vc = tty->driver_data;  	struct console_font_op op;	/* used in multiple places here */ -	unsigned int console; +	unsigned int console = vc->vc_num;  	unsigned char ucval;  	unsigned int uival;  	void __user *up = (void __user *)arg;  	int i, perm;  	int ret = 0; -	console = vc->vc_num; - - -	if (!vc_cons_allocated(console)) { 	/* impossible? */ -		ret = -ENOIOCTLCMD; -		goto out; -	} - -  	/*  	 * To have permissions to do most of the vt ioctls, we either have  	 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. @@ -641,15 +649,16 @@ int vt_ioctl(struct tty_struct *tty,  		struct vt_stat __user *vtstat = up;  		unsigned short state, mask; -		/* Review: FIXME: Console lock ? */  		if (put_user(fg_console + 1, &vtstat->v_active))  			ret = -EFAULT;  		else {  			state = 1;	/* /dev/tty0 is always open */ +			console_lock(); /* required by vt_in_use() */  			for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;  							++i, mask <<= 1) -				if (VT_IS_IN_USE(i)) +				if (vt_in_use(i))  					state |= mask; +			console_unlock();  			ret = put_user(state, &vtstat->v_state);  		}  		break; @@ -659,10 +668,11 @@ int vt_ioctl(struct tty_struct *tty,  	 * Returns the first available (non-opened) console.  	 */  	case VT_OPENQRY: -		/* FIXME: locking ? - but then this is a stupid API */ +		console_lock(); /* required by vt_in_use() */  		for (i = 0; i < MAX_NR_CONSOLES; ++i) -			if (! VT_IS_IN_USE(i)) +			if (!vt_in_use(i))  				break; +		console_unlock();  		uival = i < MAX_NR_CONSOLES ? (i+1) : -1;  		goto setint;		  @@ -1011,12 +1021,12 @@ int vt_ioctl(struct tty_struct *tty,  	case VT_LOCKSWITCH:  		if (!capable(CAP_SYS_TTY_CONFIG))  			return -EPERM; -		vt_dont_switch = 1; +		vt_dont_switch = true;  		break;  	case VT_UNLOCKSWITCH:  		if (!capable(CAP_SYS_TTY_CONFIG))  			return -EPERM; -		vt_dont_switch = 0; +		vt_dont_switch = false;  		break;  	case VT_GETHIFONTMASK:  		ret = put_user(vc->vc_hi_font_mask, @@ -1180,14 +1190,9 @@ long vt_compat_ioctl(struct tty_struct *tty,  {  	struct vc_data *vc = tty->driver_data;  	struct console_font_op op;	/* used in multiple places here */ -	unsigned int console = vc->vc_num;  	void __user *up = compat_ptr(arg);  	int perm; - -	if (!vc_cons_allocated(console)) 	/* impossible? */ -		return -ENOIOCTLCMD; -  	/*  	 * To have permissions to do most of the vt ioctls, we either have  	 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. |