diff options
Diffstat (limited to 'drivers/tty/n_hdlc.c')
| -rw-r--r-- | drivers/tty/n_hdlc.c | 28 | 
1 files changed, 24 insertions, 4 deletions
| diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index 7e0884ecc74f..94c1ec2dd754 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -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; @@ -335,6 +342,20 @@ 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() */  /** @@ -572,14 +593,13 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,  /**   * n_hdlc_tty_ioctl - process IOCTL system call for the tty device.   * @tty: pointer to tty instance data - * @file: pointer to open file object for device   * @cmd: IOCTL command code   * @arg: argument for IOCTL call (cmd dependent)   *   * Returns command dependent result.   */ -static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, -			    unsigned int cmd, unsigned long arg) +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; |