]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - drivers/tty/n_hdlc.c
net: axienet: setup mdio unconditionally
[mirror_ubuntu-jammy-kernel.git] / drivers / tty / n_hdlc.c
index b0f33e8ac819ac1ad33af23cd753fad53dbc48fb..166f651fde33a29991645c0e4402e5ea28813b44 100644 (file)
@@ -140,6 +140,8 @@ struct n_hdlc {
        struct n_hdlc_buf_list  rx_buf_list;
        struct n_hdlc_buf_list  tx_free_buf_list;
        struct n_hdlc_buf_list  rx_free_buf_list;
+       struct work_struct      write_work;
+       struct tty_struct       *tty_for_write_work;
 };
 
 /*
@@ -154,6 +156,7 @@ 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);
+static void n_hdlc_tty_write_work(struct work_struct *work);
 
 /* max frame size for memory allocations */
 static int maxframe = 4096;
@@ -210,6 +213,8 @@ static void n_hdlc_tty_close(struct tty_struct *tty)
        wake_up_interruptible(&tty->read_wait);
        wake_up_interruptible(&tty->write_wait);
 
+       cancel_work_sync(&n_hdlc->write_work);
+
        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);
@@ -241,6 +246,8 @@ static int n_hdlc_tty_open(struct tty_struct *tty)
                return -ENFILE;
        }
 
+       INIT_WORK(&n_hdlc->write_work, n_hdlc_tty_write_work);
+       n_hdlc->tty_for_write_work = tty;
        tty->disc_data = n_hdlc;
        tty->receive_room = 65536;
 
@@ -334,6 +341,20 @@ check_again:
                goto check_again;
 }      /* end of n_hdlc_send_frames() */
 
+/**
+ * n_hdlc_tty_write_work - Asynchronous callback for transmit wakeup
+ * @work: pointer to work_struct
+ *
+ * Called when low level device driver can accept more send data.
+ */
+static void n_hdlc_tty_write_work(struct work_struct *work)
+{
+       struct n_hdlc *n_hdlc = container_of(work, struct n_hdlc, write_work);
+       struct tty_struct *tty = n_hdlc->tty_for_write_work;
+
+       n_hdlc_send_frames(n_hdlc, tty);
+}      /* end of n_hdlc_tty_write_work() */
+
 /**
  * n_hdlc_tty_wakeup - Callback for transmit wakeup
  * @tty: pointer to associated tty instance data
@@ -344,7 +365,7 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty)
 {
        struct n_hdlc *n_hdlc = tty->disc_data;
 
-       n_hdlc_send_frames(n_hdlc, tty);
+       schedule_work(&n_hdlc->write_work);
 }      /* end of n_hdlc_tty_wakeup() */
 
 /**
@@ -358,7 +379,7 @@ static void n_hdlc_tty_wakeup(struct tty_struct *tty)
  * interpreted as one HDLC frame.
  */
 static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
-                              char *flags, int count)
+                              const char *flags, int count)
 {
        register struct n_hdlc *n_hdlc = tty->disc_data;
        register struct n_hdlc_buf *buf;
@@ -411,8 +432,10 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,
  * n_hdlc_tty_read - Called to retrieve one frame of data (if available)
  * @tty: pointer to tty instance data
  * @file: pointer to open file object
- * @buf: pointer to returned data buffer
+ * @kbuf: pointer to returned data buffer
  * @nr: size of returned data buffer
+ * @cookie: stored rbuf from previous run
+ * @offset: offset into the data buffer
  *
  * Returns the number of bytes returned or error code.
  */
@@ -788,6 +811,7 @@ static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list)
 
 static struct tty_ldisc_ops n_hdlc_ldisc = {
        .owner          = THIS_MODULE,
+       .num            = N_HDLC,
        .name           = "hdlc",
        .open           = n_hdlc_tty_open,
        .close          = n_hdlc_tty_close,
@@ -807,7 +831,7 @@ static int __init n_hdlc_init(void)
        /* range check maxframe arg */
        maxframe = clamp(maxframe, 4096, MAX_HDLC_FRAME_SIZE);
 
-       status = tty_register_ldisc(N_HDLC, &n_hdlc_ldisc);
+       status = tty_register_ldisc(&n_hdlc_ldisc);
        if (!status)
                pr_info("N_HDLC line discipline registered with maxframe=%d\n",
                                maxframe);
@@ -821,14 +845,7 @@ static int __init n_hdlc_init(void)
 
 static void __exit n_hdlc_exit(void)
 {
-       /* Release tty registration of line discipline */
-       int status = tty_unregister_ldisc(N_HDLC);
-
-       if (status)
-               pr_err("N_HDLC: can't unregister line discipline (err = %d)\n",
-                               status);
-       else
-               pr_info("N_HDLC: line discipline unregistered\n");
+       tty_unregister_ldisc(&n_hdlc_ldisc);
 }
 
 module_init(n_hdlc_init);