diff options
Diffstat (limited to 'drivers/tty/n_hdlc.c')
| -rw-r--r-- | drivers/tty/n_hdlc.c | 130 |
1 files changed, 41 insertions, 89 deletions
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index 94c1ec2dd754..3c9dcb0928c6 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -76,8 +76,6 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#define HDLC_MAGIC 0x239e - #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> @@ -98,7 +96,6 @@ #include <linux/if.h> #include <linux/bitops.h> -#include <asm/termios.h> #include <linux/uaccess.h> #include "tty.h" @@ -112,8 +109,8 @@ struct n_hdlc_buf { struct list_head list_item; - int count; - char buf[]; + size_t count; + u8 buf[]; }; struct n_hdlc_buf_list { @@ -124,7 +121,6 @@ struct n_hdlc_buf_list { /** * struct n_hdlc - per device instance data structure - * @magic: magic value for structure * @tbusy: reentrancy flag for tx wakeup code * @woke_up: tx wakeup needs to be run again as it was called while @tbusy * @tx_buf_list: list of pending transmit frame buffers @@ -133,7 +129,6 @@ struct n_hdlc_buf_list { * @rx_free_buf_list: list unused received frame buffers */ struct n_hdlc { - int magic; bool tbusy; bool woke_up; struct n_hdlc_buf_list tx_buf_list; @@ -200,10 +195,6 @@ static void n_hdlc_tty_close(struct tty_struct *tty) { 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); #endif @@ -272,25 +263,22 @@ static int n_hdlc_tty_open(struct tty_struct *tty) */ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty) { - register int actual; - unsigned long flags; struct n_hdlc_buf *tbuf; + ssize_t actual; check_again: - - spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock, flags); - if (n_hdlc->tbusy) { - n_hdlc->woke_up = true; - spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); - return; + scoped_guard(spinlock_irqsave, &n_hdlc->tx_buf_list.spinlock) { + if (n_hdlc->tbusy) { + n_hdlc->woke_up = true; + return; + } + n_hdlc->tbusy = true; + n_hdlc->woke_up = false; } - 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) { - pr_debug("sending frame %p, count=%d\n", tbuf, tbuf->count); + pr_debug("sending frame %p, count=%zu\n", tbuf, tbuf->count); /* Send the next block of data to device */ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); @@ -333,9 +321,8 @@ check_again: 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 = false; - spin_unlock_irqrestore(&n_hdlc->tx_buf_list.spinlock, flags); + scoped_guard(spinlock_irqsave, &n_hdlc->tx_buf_list.spinlock) + n_hdlc->tbusy = false; if (n_hdlc->woke_up) goto check_again; @@ -378,19 +365,13 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty) * Called by tty low level driver when receive data is available. Data is * interpreted as one HDLC frame. */ -static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, - const char *flags, int count) +static void n_hdlc_tty_receive(struct tty_struct *tty, const u8 *data, + const u8 *flags, size_t count) { register struct n_hdlc *n_hdlc = tty->disc_data; register struct n_hdlc_buf *buf; - pr_debug("%s() called count=%d\n", __func__, count); - - /* verify line is using HDLC discipline */ - if (n_hdlc->magic != HDLC_MAGIC) { - pr_err("line not using HDLC discipline\n"); - return; - } + pr_debug("%s() called count=%zu\n", __func__, count); if (count > maxframe) { pr_debug("rx count>maxframesize, data discarded\n"); @@ -440,8 +421,8 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data, * Returns the number of bytes returned or error code. */ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, - __u8 *kbuf, size_t nr, - void **cookie, unsigned long offset) + u8 *kbuf, size_t nr, void **cookie, + unsigned long offset) { struct n_hdlc *n_hdlc = tty->disc_data; int ret = 0; @@ -533,18 +514,15 @@ done_with_rbuf: * 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) + const u8 *data, size_t count) { struct n_hdlc *n_hdlc = tty->disc_data; - int error = 0; DECLARE_WAITQUEUE(wait, current); struct n_hdlc_buf *tbuf; + ssize_t error = 0; pr_debug("%s() called count=%zd\n", __func__, count); - if (n_hdlc->magic != HDLC_MAGIC) - return -EIO; - /* verify frame size */ if (count > maxframe) { pr_debug("%s: truncating user packet from %zu to %d\n", @@ -602,44 +580,36 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct n_hdlc *n_hdlc = tty->disc_data; - int error = 0; int count; - unsigned long flags; struct n_hdlc_buf *buf = NULL; pr_debug("%s() called %d\n", __func__, cmd); - /* Verify the status of the device */ - 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); - 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); - error = put_user(count, (int __user *)arg); - break; + scoped_guard(spinlock_irqsave, &n_hdlc->rx_buf_list.spinlock) { + 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; + } + return put_user(count, (int __user *)arg); case TIOCOUTQ: /* 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); - 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); - error = put_user(count, (int __user *)arg); - break; + scoped_guard(spinlock_irqsave, &n_hdlc->tx_buf_list.spinlock) { + buf = list_first_entry_or_null(&n_hdlc->tx_buf_list.list, + struct n_hdlc_buf, list_item); + if (buf) + count += buf->count; + } + return put_user(count, (int __user *)arg); case TCFLSH: switch (arg) { @@ -650,11 +620,8 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, fallthrough; /* to default */ default: - error = n_tty_ioctl_helper(tty, cmd, arg); - break; + return n_tty_ioctl_helper(tty, cmd, arg); } - return error; - } /* end of n_hdlc_tty_ioctl() */ /** @@ -673,9 +640,6 @@ static __poll_t n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp, struct n_hdlc *n_hdlc = tty->disc_data; __poll_t mask = 0; - 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) @@ -739,9 +703,6 @@ static struct n_hdlc *n_hdlc_alloc(void) 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; - return n_hdlc; } /* end of n_hdlc_alloc() */ @@ -754,14 +715,10 @@ static struct n_hdlc *n_hdlc_alloc(void) static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list, struct n_hdlc_buf *buf) { - unsigned long flags; - - spin_lock_irqsave(&buf_list->spinlock, flags); + guard(spinlock_irqsave)(&buf_list->spinlock); list_add(&buf->list_item, &buf_list->list); buf_list->count++; - - spin_unlock_irqrestore(&buf_list->spinlock, flags); } /** @@ -772,14 +729,10 @@ static void n_hdlc_buf_return(struct n_hdlc_buf_list *buf_list, static void n_hdlc_buf_put(struct n_hdlc_buf_list *buf_list, struct n_hdlc_buf *buf) { - unsigned long flags; - - spin_lock_irqsave(&buf_list->spinlock, flags); + guard(spinlock_irqsave)(&buf_list->spinlock); list_add_tail(&buf->list_item, &buf_list->list); buf_list->count++; - - spin_unlock_irqrestore(&buf_list->spinlock, flags); } /* end of n_hdlc_buf_put() */ /** @@ -792,10 +745,9 @@ static void n_hdlc_buf_put(struct n_hdlc_buf_list *buf_list, */ static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list) { - unsigned long flags; struct n_hdlc_buf *buf; - spin_lock_irqsave(&buf_list->spinlock, flags); + guard(spinlock_irqsave)(&buf_list->spinlock); buf = list_first_entry_or_null(&buf_list->list, struct n_hdlc_buf, list_item); @@ -804,7 +756,6 @@ static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list) buf_list->count--; } - spin_unlock_irqrestore(&buf_list->spinlock, flags); return buf; } /* end of n_hdlc_buf_get() */ @@ -850,6 +801,7 @@ static void __exit n_hdlc_exit(void) module_init(n_hdlc_init); module_exit(n_hdlc_exit); +MODULE_DESCRIPTION("HDLC line discipline support"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Paul Fulghum paulkf@microgate.com"); module_param(maxframe, int, 0); |
