diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/tty/n_gsm.c | 140 | ||||
-rw-r--r-- | drivers/tty/n_hdlc.c | 558 | ||||
-rw-r--r-- | drivers/tty/n_tty.c | 6 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_bcm2835aux.c | 18 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_exar.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_of.c | 28 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_pci.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_port.c | 31 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_pxa.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_tegra.c | 198 | ||||
-rw-r--r-- | drivers/tty/serial/8250/Kconfig | 9 | ||||
-rw-r--r-- | drivers/tty/serial/8250/Makefile | 1 | ||||
-rw-r--r-- | drivers/tty/serial/Kconfig | 12 | ||||
-rw-r--r-- | drivers/tty/serial/efm32-uart.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/kgdboc.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/sc16is7xx.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/serial_core.c | 96 | ||||
-rw-r--r-- | drivers/tty/vt/selection.c | 5 | ||||
-rw-r--r-- | drivers/tty/vt/vt.c | 7 | ||||
-rw-r--r-- | drivers/tty/vt/vt_ioctl.c | 29 |
20 files changed, 606 insertions, 546 deletions
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..cd1319d26c45 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,36 @@ 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(%d)%s() called (device=%s)\n", + __FILE__, __LINE__, __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 +269,23 @@ 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("%s(%d)sending frame %p, count=%d\n", + __FILE__, __LINE__, 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 +299,22 @@ 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("%s(%d)frame %p completed\n", + __FILE__, __LINE__, 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("%s(%d)frame %p pending\n", + __FILE__, __LINE__, tbuf); /* * the buffer was not accepted by driver, @@ -436,21 +324,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 +345,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 +363,54 @@ 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(%d)%s() called count=%d\n", + __FILE__, __LINE__, __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("%s(%d) line not using HDLC discipline\n", + __FILE__, __LINE__); 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("%s(%d) rx count>maxframesize, data discarded\n", + __FILE__, __LINE__); 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("%s(%d) no more rx buffers, data discarded\n", + __FILE__, __LINE__); 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 +420,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 +470,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 +489,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 +498,35 @@ 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(%d)%s() called count=%zd\n", __FILE__, __LINE__, __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 +536,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 +546,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 +572,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(%d)%s() called %d\n", __FILE__, __LINE__, __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 +603,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 +625,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 +633,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 +641,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(%d)%s(), kmalloc() failed for %s buffer %u\n", + __FILE__, __LINE__, __func__, name, i); + return; + } + n_hdlc_buf_put(list, buf); + } +} + /** * n_hdlc_alloc - allocate an n_hdlc instance data structure * @@ -833,8 +692,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 +707,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 +756,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 +779,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 +819,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 +830,5 @@ module_exit(n_hdlc_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Paul Fulghum paulkf@microgate.com"); -module_param(debuglevel, int, 0); module_param(maxframe, int, 0); MODULE_ALIAS_LDISC(N_HDLC); 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/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c index e70e3cc30050..5cc03bf24f85 100644 --- a/drivers/tty/serial/8250/8250_bcm2835aux.c +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c @@ -137,6 +137,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 <kernel@martin.sperl.org>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 91e9b070d36d..65898ef90801 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -127,7 +127,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_of.c b/drivers/tty/serial/8250/8250_of.c index f6687756ec5e..ad92f451f3b9 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,28 +25,6 @@ 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) { @@ -210,10 +187,6 @@ static int of_platform_serial_setup(struct platform_device *ofdev, port->rs485_config = of_8250_rs485_config; switch (type) { - case PORT_TEGRA: - port->handle_break = tegra_serial_handle_break; - break; - case PORT_RT2880: port->iotype = UPIO_AU; break; @@ -358,7 +331,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_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..f398f162a1fd 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1318,8 +1318,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); @@ -1683,7 +1683,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; @@ -2134,7 +2134,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 +2166,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 +2267,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; @@ -2296,8 +2294,7 @@ dont_test_tx_en: if (up->dma) { retval = serial8250_request_dma(up); if (retval) { - pr_warn_ratelimited("%s - failed to request DMA\n", - port->name); + dev_warn_ratelimited(port->dev, "failed to request DMA\n"); up->dma = NULL; } } @@ -2880,7 +2877,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 +2923,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 +2944,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) { 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 <jbrasen@nvidia.com>"); +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..880b96201530 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -237,7 +237,6 @@ config SERIAL_CLPS711X_CONSOLE config SERIAL_SAMSUNG tristate "Samsung SoC serial support" - depends on PLAT_SAMSUNG || ARCH_EXYNOS || COMPILE_TEST select SERIAL_CORE help Support for the on-chip UARTs on the Samsung S3C24XX series CPUs, @@ -260,15 +259,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 +1101,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 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/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/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..5444293fe2e8 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1908,6 +1908,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_enabled(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 +2078,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 +2614,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 +2624,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 +2633,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 +2644,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 +2658,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 +2668,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 +2678,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 +2688,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 +2698,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 +2708,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 +2718,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 +2728,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 +2738,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,28 +2748,28 @@ 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 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 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, @@ -2824,14 +2832,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); diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 0c50d7410b31..714992693974 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -88,6 +88,11 @@ void clear_selection(void) } EXPORT_SYMBOL_GPL(clear_selection); +bool vc_is_sel(struct vc_data *vc) +{ + return vc == sel_cons; +} + /* * User settable table: what characters are to be considered alphabetic? * 128 bits. Locked by the console lock. diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 0cfbb7182b5a..8fa059ec6cc8 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -890,8 +890,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 +902,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) @@ -1207,7 +1208,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; diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index ee6c91ef1f6c..693d9d7ffb68 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c @@ -40,10 +40,25 @@ #include <linux/selection.h> char vt_dont_switch; -extern struct tty_driver *console_driver; -#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) +{ + extern struct tty_driver *console_driver; + + return console_driver->ttys[i] && console_driver->ttys[i]->count; +} + +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,7 +304,7 @@ 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); @@ -311,7 +326,7 @@ 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; @@ -648,7 +663,7 @@ int vt_ioctl(struct tty_struct *tty, state = 1; /* /dev/tty0 is always open */ 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; ret = put_user(state, &vtstat->v_state); } @@ -661,7 +676,7 @@ int vt_ioctl(struct tty_struct *tty, case VT_OPENQRY: /* FIXME: locking ? - but then this is a stupid API */ for (i = 0; i < MAX_NR_CONSOLES; ++i) - if (! VT_IS_IN_USE(i)) + if (!vt_in_use(i)) break; uival = i < MAX_NR_CONSOLES ? (i+1) : -1; goto setint; |