diff options
| author | Felipe Balbi <balbi@ti.com> | 2011-03-21 12:25:08 +0200 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-04-22 17:31:53 -0700 | 
| commit | b1c43f82c5aa265442f82dba31ce985ebb7aa71c (patch) | |
| tree | 8b344d8d5355b30e8deff901180edc708a653227 /drivers | |
| parent | e9a470f445271eb157ee860a93b062324402fc3a (diff) | |
| download | olio-linux-3.10-b1c43f82c5aa265442f82dba31ce985ebb7aa71c.tar.xz olio-linux-3.10-b1c43f82c5aa265442f82dba31ce985ebb7aa71c.zip  | |
tty: make receive_buf() return the amout of bytes received
it makes it simpler to keep track of the amount of
bytes received and simplifies how flush_to_ldisc counts
the remaining bytes. It also fixes a bug of lost bytes
on n_tty when flushing too many bytes via the USB
serial gadget driver.
Tested-by: Stefan Bigler <stefan.bigler@keymile.com>
Tested-by: Toby Gray <toby.gray@realvnc.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/bluetooth/hci_ldisc.c | 12 | ||||
| -rw-r--r-- | drivers/input/serio/serport.c | 10 | ||||
| -rw-r--r-- | drivers/isdn/gigaset/ser-gigaset.c | 8 | ||||
| -rw-r--r-- | drivers/misc/ti-st/st_core.c | 6 | ||||
| -rw-r--r-- | drivers/net/caif/caif_serial.c | 6 | ||||
| -rw-r--r-- | drivers/net/can/slcan.c | 9 | ||||
| -rw-r--r-- | drivers/net/hamradio/6pack.c | 8 | ||||
| -rw-r--r-- | drivers/net/hamradio/mkiss.c | 11 | ||||
| -rw-r--r-- | drivers/net/irda/irtty-sir.c | 16 | ||||
| -rw-r--r-- | drivers/net/ppp_async.c | 6 | ||||
| -rw-r--r-- | drivers/net/ppp_synctty.c | 6 | ||||
| -rw-r--r-- | drivers/net/slip.c | 11 | ||||
| -rw-r--r-- | drivers/net/wan/x25_asy.c | 7 | ||||
| -rw-r--r-- | drivers/tty/n_gsm.c | 6 | ||||
| -rw-r--r-- | drivers/tty/n_hdlc.c | 18 | ||||
| -rw-r--r-- | drivers/tty/n_r3964.c | 10 | ||||
| -rw-r--r-- | drivers/tty/n_tty.c | 61 | ||||
| -rw-r--r-- | drivers/tty/tty_buffer.c | 15 | ||||
| -rw-r--r-- | drivers/tty/vt/selection.c | 3 | 
19 files changed, 120 insertions, 109 deletions
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 48ad2a7ab08..0d4da5e14ba 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -357,22 +357,26 @@ static void hci_uart_tty_wakeup(struct tty_struct *tty)   *        * Return Value:    None   */ -static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *flags, int count) +static unsigned int hci_uart_tty_receive(struct tty_struct *tty, +		const u8 *data, char *flags, int count)  {  	struct hci_uart *hu = (void *)tty->disc_data; +	int received;  	if (!hu || tty != hu->tty) -		return; +		return -ENODEV;  	if (!test_bit(HCI_UART_PROTO_SET, &hu->flags)) -		return; +		return -EINVAL;  	spin_lock(&hu->rx_lock); -	hu->proto->recv(hu, (void *) data, count); +	received = hu->proto->recv(hu, (void *) data, count);  	hu->hdev->stat.byte_rx += count;  	spin_unlock(&hu->rx_lock);  	tty_unthrottle(tty); + +	return received;  }  static int hci_uart_register_dev(struct hci_uart *hu) diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c index 8755f5f3ad3..f3698967edf 100644 --- a/drivers/input/serio/serport.c +++ b/drivers/input/serio/serport.c @@ -120,17 +120,21 @@ static void serport_ldisc_close(struct tty_struct *tty)   * 'interrupt' routine.   */ -static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count) +static unsigned int serport_ldisc_receive(struct tty_struct *tty, +		const unsigned char *cp, char *fp, int count)  {  	struct serport *serport = (struct serport*) tty->disc_data;  	unsigned long flags;  	unsigned int ch_flags; +	int ret = 0;  	int i;  	spin_lock_irqsave(&serport->lock, flags); -	if (!test_bit(SERPORT_ACTIVE, &serport->flags)) +	if (!test_bit(SERPORT_ACTIVE, &serport->flags)) { +		ret = -EINVAL;  		goto out; +	}  	for (i = 0; i < count; i++) {  		switch (fp[i]) { @@ -152,6 +156,8 @@ static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *c  out:  	spin_unlock_irqrestore(&serport->lock, flags); + +	return ret == 0 ? count : ret;  }  /* diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index 86a5c4f7775..1d44d470897 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -674,7 +674,7 @@ gigaset_tty_ioctl(struct tty_struct *tty, struct file *file,   *	cflags	buffer containing error flags for received characters (ignored)   *	count	number of received characters   */ -static void +static unsigned int  gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,  		    char *cflags, int count)  { @@ -683,12 +683,12 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,  	struct inbuf_t *inbuf;  	if (!cs) -		return; +		return -ENODEV;  	inbuf = cs->inbuf;  	if (!inbuf) {  		dev_err(cs->dev, "%s: no inbuf\n", __func__);  		cs_put(cs); -		return; +		return -EINVAL;  	}  	tail = inbuf->tail; @@ -725,6 +725,8 @@ gigaset_tty_receive(struct tty_struct *tty, const unsigned char *buf,  	gig_dbg(DEBUG_INTR, "%s-->BH", __func__);  	gigaset_schedule_event(cs);  	cs_put(cs); + +	return count;  }  /* diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c index 486117f72c9..cb98a7da98e 100644 --- a/drivers/misc/ti-st/st_core.c +++ b/drivers/misc/ti-st/st_core.c @@ -744,8 +744,8 @@ static void st_tty_close(struct tty_struct *tty)  	pr_debug("%s: done ", __func__);  } -static void st_tty_receive(struct tty_struct *tty, const unsigned char *data, -			   char *tty_flags, int count) +static unsigned int st_tty_receive(struct tty_struct *tty, +		const unsigned char *data, char *tty_flags, int count)  {  #ifdef VERBOSE  	print_hex_dump(KERN_DEBUG, ">in>", DUMP_PREFIX_NONE, @@ -758,6 +758,8 @@ static void st_tty_receive(struct tty_struct *tty, const unsigned char *data,  	 */  	st_recv(tty->disc_data, data, count);  	pr_debug("done %s", __func__); + +	return count;  }  /* wake-up function called in from the TTY layer diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index 3df0c0f8b8b..73c7e03617e 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -167,8 +167,8 @@ static inline void debugfs_tx(struct ser_device *ser, const u8 *data, int size)  #endif -static void ldisc_receive(struct tty_struct *tty, const u8 *data, -			char *flags, int count) +static unsigned int ldisc_receive(struct tty_struct *tty, +		const u8 *data, char *flags, int count)  {  	struct sk_buff *skb = NULL;  	struct ser_device *ser; @@ -215,6 +215,8 @@ static void ldisc_receive(struct tty_struct *tty, const u8 *data,  	} else  		++ser->dev->stats.rx_dropped;  	update_tty_status(ser); + +	return count;  }  static int handle_tx(struct ser_device *ser) diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index b423965a78d..c600954998d 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -425,16 +425,17 @@ static void slc_setup(struct net_device *dev)   * in parallel   */ -static void slcan_receive_buf(struct tty_struct *tty, +static unsigned int slcan_receive_buf(struct tty_struct *tty,  			      const unsigned char *cp, char *fp, int count)  {  	struct slcan *sl = (struct slcan *) tty->disc_data; +	int bytes = count;  	if (!sl || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev)) -		return; +		return -ENODEV;  	/* Read the characters out of the buffer */ -	while (count--) { +	while (bytes--) {  		if (fp && *fp++) {  			if (!test_and_set_bit(SLF_ERROR, &sl->flags))  				sl->dev->stats.rx_errors++; @@ -443,6 +444,8 @@ static void slcan_receive_buf(struct tty_struct *tty,  		}  		slcan_unesc(sl, *cp++);  	} + +	return count;  }  /************************************ diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 3e5d0b6b651..992089639ea 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -456,7 +456,7 @@ out:   * a block of 6pack data has been received, which can now be decapsulated   * and sent on to some IP layer for further processing.   */ -static void sixpack_receive_buf(struct tty_struct *tty, +static unsigned int sixpack_receive_buf(struct tty_struct *tty,  	const unsigned char *cp, char *fp, int count)  {  	struct sixpack *sp; @@ -464,11 +464,11 @@ static void sixpack_receive_buf(struct tty_struct *tty,  	int count1;  	if (!count) -		return; +		return 0;  	sp = sp_get(tty);  	if (!sp) -		return; +		return -ENODEV;  	memcpy(buf, cp, count < sizeof(buf) ? count : sizeof(buf)); @@ -487,6 +487,8 @@ static void sixpack_receive_buf(struct tty_struct *tty,  	sp_put(sp);  	tty_unthrottle(tty); + +	return count1;  }  /* diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 4c628393c8b..0e4f2353114 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -923,13 +923,14 @@ static long mkiss_compat_ioctl(struct tty_struct *tty, struct file *file,   * a block of data has been received, which can now be decapsulated   * and sent on to the AX.25 layer for further processing.   */ -static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp, -	char *fp, int count) +static unsigned int mkiss_receive_buf(struct tty_struct *tty, +		const unsigned char *cp, char *fp, int count)  {  	struct mkiss *ax = mkiss_get(tty); +	int bytes = count;  	if (!ax) -		return; +		return -ENODEV;  	/*  	 * Argh! mtu change time! - costs us the packet part received @@ -939,7 +940,7 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,  		ax_changedmtu(ax);  	/* Read the characters out of the buffer */ -	while (count--) { +	while (bytes--) {  		if (fp != NULL && *fp++) {  			if (!test_and_set_bit(AXF_ERROR, &ax->flags))  				ax->dev->stats.rx_errors++; @@ -952,6 +953,8 @@ static void mkiss_receive_buf(struct tty_struct *tty, const unsigned char *cp,  	mkiss_put(ax);  	tty_unthrottle(tty); + +	return count;  }  /* diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c index 3352b2443e5..035861d8acb 100644 --- a/drivers/net/irda/irtty-sir.c +++ b/drivers/net/irda/irtty-sir.c @@ -216,23 +216,23 @@ static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t   * usbserial:	urb-complete-interrupt / softint   */ -static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp, -			      char *fp, int count)  +static unsigned int irtty_receive_buf(struct tty_struct *tty, +		const unsigned char *cp, char *fp, int count)  {  	struct sir_dev *dev;  	struct sirtty_cb *priv = tty->disc_data;  	int	i; -	IRDA_ASSERT(priv != NULL, return;); -	IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;); +	IRDA_ASSERT(priv != NULL, return -ENODEV;); +	IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return -EINVAL;);  	if (unlikely(count==0))		/* yes, this happens */ -		return; +		return 0;  	dev = priv->dev;  	if (!dev) {  		IRDA_WARNING("%s(), not ready yet!\n", __func__); -		return; +		return -ENODEV;  	}  	for (i = 0; i < count; i++) { @@ -242,11 +242,13 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,   		if (fp && *fp++) {   			IRDA_DEBUG(0, "Framing or parity error!\n");  			sirdev_receive(dev, NULL, 0);	/* notify sir_dev (updating stats) */ -			return; +			return -EINVAL;   		}  	}  	sirdev_receive(dev, cp, count); + +	return count;  }  /* diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c index a1b82c9c67d..53872d7d738 100644 --- a/drivers/net/ppp_async.c +++ b/drivers/net/ppp_async.c @@ -340,7 +340,7 @@ ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)  }  /* May sleep, don't call from interrupt level or with interrupts disabled */ -static void +static unsigned int  ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,  		  char *cflags, int count)  { @@ -348,7 +348,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,  	unsigned long flags;  	if (!ap) -		return; +		return -ENODEV;  	spin_lock_irqsave(&ap->recv_lock, flags);  	ppp_async_input(ap, buf, cflags, count);  	spin_unlock_irqrestore(&ap->recv_lock, flags); @@ -356,6 +356,8 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,  		tasklet_schedule(&ap->tsk);  	ap_put(ap);  	tty_unthrottle(tty); + +	return count;  }  static void diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c index 2573f525f11..0815790a5cf 100644 --- a/drivers/net/ppp_synctty.c +++ b/drivers/net/ppp_synctty.c @@ -381,7 +381,7 @@ ppp_sync_poll(struct tty_struct *tty, struct file *file, poll_table *wait)  }  /* May sleep, don't call from interrupt level or with interrupts disabled */ -static void +static unsigned int  ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,  		  char *cflags, int count)  { @@ -389,7 +389,7 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,  	unsigned long flags;  	if (!ap) -		return; +		return -ENODEV;  	spin_lock_irqsave(&ap->recv_lock, flags);  	ppp_sync_input(ap, buf, cflags, count);  	spin_unlock_irqrestore(&ap->recv_lock, flags); @@ -397,6 +397,8 @@ ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,  		tasklet_schedule(&ap->tsk);  	sp_put(ap);  	tty_unthrottle(tty); + +	return count;  }  static void diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 86cbb9ea2f2..86718d35839 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -670,16 +670,17 @@ static void sl_setup(struct net_device *dev)   * in parallel   */ -static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, -							char *fp, int count) +static unsigned int slip_receive_buf(struct tty_struct *tty, +		const unsigned char *cp, char *fp, int count)  {  	struct slip *sl = tty->disc_data; +	int bytes = count;  	if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev)) -		return; +		return -ENODEV;  	/* Read the characters out of the buffer */ -	while (count--) { +	while (bytes--) {  		if (fp && *fp++) {  			if (!test_and_set_bit(SLF_ERROR, &sl->flags))  				sl->dev->stats.rx_errors++; @@ -693,6 +694,8 @@ static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp,  #endif  			slip_unesc(sl, *cp++);  	} + +	return count;  }  /************************************ diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 24297b274cd..40398bf7d03 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -517,17 +517,18 @@ static int x25_asy_close(struct net_device *dev)   * and sent on to some IP layer for further processing.   */ -static void x25_asy_receive_buf(struct tty_struct *tty, +static unsigned int x25_asy_receive_buf(struct tty_struct *tty,  				const unsigned char *cp, char *fp, int count)  {  	struct x25_asy *sl = tty->disc_data; +	int bytes = count;  	if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))  		return;  	/* Read the characters out of the buffer */ -	while (count--) { +	while (bytes--) {  		if (fp && *fp++) {  			if (!test_and_set_bit(SLF_ERROR, &sl->flags))  				sl->dev->stats.rx_errors++; @@ -536,6 +537,8 @@ static void x25_asy_receive_buf(struct tty_struct *tty,  		}  		x25_asy_unesc(sl, *cp++);  	} + +	return count;  }  /* diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 47f8cdb207f..6abc7359884 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -2138,8 +2138,8 @@ static void gsmld_detach_gsm(struct tty_struct *tty, struct gsm_mux *gsm)  	gsm->tty = NULL;  } -static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp, -			      char *fp, int count) +static unsigned int gsmld_receive_buf(struct tty_struct *tty, +		const unsigned char *cp, char *fp, int count)  {  	struct gsm_mux *gsm = tty->disc_data;  	const unsigned char *dp; @@ -2173,6 +2173,8 @@ static void gsmld_receive_buf(struct tty_struct *tty, const unsigned char *cp,  	}  	/* FASYNC if needed ? */  	/* If clogged call tty_throttle(tty); */ + +	return count;  }  /** diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index cea56033b34..cac666314ae 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -188,8 +188,8 @@ static unsigned int 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 unsigned int 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))) @@ -509,8 +509,8 @@ 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, -			       char *flags, int count) +static unsigned int 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_buf *buf; @@ -521,20 +521,20 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,  	/* This can happen if stuff comes in on the backup tty */  	if (!n_hdlc || tty != n_hdlc->tty) -		return; +		return -ENODEV;  	/* verify line is using HDLC discipline */  	if (n_hdlc->magic != HDLC_MAGIC) {  		printk("%s(%d) line not using HDLC discipline\n",  			__FILE__,__LINE__); -		return; +		return -EINVAL;  	}  	if ( count>maxframe ) {  		if (debuglevel >= DEBUG_LEVEL_INFO)	  			printk("%s(%d) rx count>maxframesize, data discarded\n",  			       __FILE__,__LINE__); -		return; +		return -EINVAL;  	}  	/* get a free HDLC buffer */	 @@ -550,7 +550,7 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,  		if (debuglevel >= DEBUG_LEVEL_INFO)	  			printk("%s(%d) no more rx buffers, data discarded\n",  			       __FILE__,__LINE__); -		return; +		return -EINVAL;  	}  	/* copy received data to HDLC buffer */ @@ -565,6 +565,8 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, const __u8 *data,  	if (n_hdlc->tty->fasync != NULL)  		kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN); +	return count; +  }	/* end of n_hdlc_tty_receive() */  /** diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index 5c6c31459a2..a4bc39c21a4 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -139,8 +139,8 @@ static int r3964_ioctl(struct tty_struct *tty, struct file *file,  static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old);  static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,  		struct poll_table_struct *wait); -static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, -		char *fp, int count); +static unsigned int r3964_receive_buf(struct tty_struct *tty, +		const unsigned char *cp, char *fp, int count);  static struct tty_ldisc_ops tty_ldisc_N_R3964 = {  	.owner = THIS_MODULE, @@ -1239,8 +1239,8 @@ static unsigned int r3964_poll(struct tty_struct *tty, struct file *file,  	return result;  } -static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, -			char *fp, int count) +static unsigned int r3964_receive_buf(struct tty_struct *tty, +		const unsigned char *cp, char *fp, int count)  {  	struct r3964_info *pInfo = tty->disc_data;  	const unsigned char *p; @@ -1257,6 +1257,8 @@ static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp,  		}  	} + +	return count;  }  MODULE_LICENSE("GPL"); diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 0ad32888091..95d0a9c2dd1 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -81,38 +81,6 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,  	return put_user(x, ptr);  } -/** - *	n_tty_set__room	-	receive space - *	@tty: terminal - * - *	Called by the driver to find out how much data it is - *	permitted to feed to the line discipline without any being lost - *	and thus to manage flow control. Not serialized. Answers for the - *	"instant". - */ - -static void n_tty_set_room(struct tty_struct *tty) -{ -	/* tty->read_cnt is not read locked ? */ -	int	left = N_TTY_BUF_SIZE - tty->read_cnt - 1; -	int old_left; - -	/* -	 * If we are doing input canonicalization, and there are no -	 * pending newlines, let characters through without limit, so -	 * that erase characters will be handled.  Other excess -	 * characters will be beeped. -	 */ -	if (left <= 0) -		left = tty->icanon && !tty->canon_data; -	old_left = tty->receive_room; -	tty->receive_room = left; - -	/* Did this open up the receive buffer? We may need to flip */ -	if (left && !old_left) -		schedule_work(&tty->buf.work); -} -  static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)  {  	if (tty->read_cnt < N_TTY_BUF_SIZE) { @@ -184,7 +152,6 @@ static void reset_buffer_flags(struct tty_struct *tty)  	tty->canon_head = tty->canon_data = tty->erasing = 0;  	memset(&tty->read_flags, 0, sizeof tty->read_flags); -	n_tty_set_room(tty);  	check_unthrottle(tty);  } @@ -1360,17 +1327,19 @@ static void n_tty_write_wakeup(struct tty_struct *tty)   *	calls one at a time and in order (or using flush_to_ldisc)   */ -static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp, -			      char *fp, int count) +static unsigned int n_tty_receive_buf(struct tty_struct *tty, +		const unsigned char *cp, char *fp, int count)  {  	const unsigned char *p;  	char *f, flags = TTY_NORMAL;  	int	i;  	char	buf[64];  	unsigned long cpuflags; +	int left; +	int ret = 0;  	if (!tty->read_buf) -		return; +		return 0;  	if (tty->real_raw) {  		spin_lock_irqsave(&tty->read_lock, cpuflags); @@ -1380,6 +1349,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,  		memcpy(tty->read_buf + tty->read_head, cp, i);  		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);  		tty->read_cnt += i; +		ret += i;  		cp += i;  		count -= i; @@ -1389,8 +1359,10 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,  		memcpy(tty->read_buf + tty->read_head, cp, i);  		tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);  		tty->read_cnt += i; +		ret += i;  		spin_unlock_irqrestore(&tty->read_lock, cpuflags);  	} else { +		ret = count;  		for (i = count, p = cp, f = fp; i; i--, p++) {  			if (f)  				flags = *f++; @@ -1418,8 +1390,6 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,  			tty->ops->flush_chars(tty);  	} -	n_tty_set_room(tty); -  	if ((!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) ||  		L_EXTPROC(tty)) {  		kill_fasync(&tty->fasync, SIGIO, POLL_IN); @@ -1432,8 +1402,12 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,  	 * mode.  We don't want to throttle the driver if we're in  	 * canonical mode and don't have a newline yet!  	 */ -	if (tty->receive_room < TTY_THRESHOLD_THROTTLE) +	left = N_TTY_BUF_SIZE - tty->read_cnt - 1; + +	if (left < TTY_THRESHOLD_THROTTLE)  		tty_throttle(tty); + +	return ret;  }  int is_ignored(int sig) @@ -1477,7 +1451,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)  	if (test_bit(TTY_HW_COOK_IN, &tty->flags)) {  		tty->raw = 1;  		tty->real_raw = 1; -		n_tty_set_room(tty);  		return;  	}  	if (I_ISTRIP(tty) || I_IUCLC(tty) || I_IGNCR(tty) || @@ -1530,7 +1503,6 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)  		else  			tty->real_raw = 0;  	} -	n_tty_set_room(tty);  	/* The termios change make the tty ready for I/O */  	wake_up_interruptible(&tty->write_wait);  	wake_up_interruptible(&tty->read_wait); @@ -1812,8 +1784,6 @@ do_it_again:  				retval = -ERESTARTSYS;  				break;  			} -			/* FIXME: does n_tty_set_room need locking ? */ -			n_tty_set_room(tty);  			timeout = schedule_timeout(timeout);  			continue;  		} @@ -1885,10 +1855,8 @@ do_it_again:  		 * longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,  		 * we won't get any more characters.  		 */ -		if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) { -			n_tty_set_room(tty); +		if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE)  			check_unthrottle(tty); -		}  		if (b - buf >= minimum)  			break; @@ -1910,7 +1878,6 @@ do_it_again:  	} else if (test_and_clear_bit(TTY_PUSH, &tty->flags))  		 goto do_it_again; -	n_tty_set_room(tty);  	return retval;  } diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index f1a7918d71a..46de2e075da 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -416,6 +416,7 @@ static void flush_to_ldisc(struct work_struct *work)  		struct tty_buffer *head, *tail = tty->buf.tail;  		int seen_tail = 0;  		while ((head = tty->buf.head) != NULL) { +			int copied;  			int count;  			char *char_buf;  			unsigned char *flag_buf; @@ -442,17 +443,19 @@ static void flush_to_ldisc(struct work_struct *work)  			   line discipline as we want to empty the queue */  			if (test_bit(TTY_FLUSHPENDING, &tty->flags))  				break; -			if (!tty->receive_room || seen_tail) -				break; -			if (count > tty->receive_room) -				count = tty->receive_room;  			char_buf = head->char_buf_ptr + head->read;  			flag_buf = head->flag_buf_ptr + head->read; -			head->read += count;  			spin_unlock_irqrestore(&tty->buf.lock, flags); -			disc->ops->receive_buf(tty, char_buf, +			copied = disc->ops->receive_buf(tty, char_buf,  							flag_buf, count);  			spin_lock_irqsave(&tty->buf.lock, flags); + +			head->read += copied; + +			if (copied == 0 || seen_tail) { +				schedule_work(&tty->buf.work); +				break; +			}  		}  		clear_bit(TTY_FLUSHING, &tty->flags);  	} diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index fb864e7fcd1..67b1d0d7c8a 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c @@ -332,8 +332,7 @@ int paste_selection(struct tty_struct *tty)  			continue;  		}  		count = sel_buffer_lth - pasted; -		count = min(count, tty->receive_room); -		tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted, +		count = tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,  								NULL, count);  		pasted += count;  	}  |