View | Details | Raw Unified
Collapse All | Expand All

(-) linux-2.6.7/Documentation/tty.txt (+194 lines)
Line 0    Link Here 
			The Lockronomicon
Your guide to the ancient and twisted locking policies of the tty layer and
the warped logic behind them. Beware all ye who read on.
FIXME: still need to work out the full set of BKL assumptions and document
them so they can eventually be killed off.
Line Discipline
---------------
Line disciplines are registered with tty_register_ldisc() passing the
discipline number and the ldisc structure. At the point of registration the 
discipline must be ready to use and it is possible it will get used before
the call returns success. If the call returns an error then it won't get
called. Do not re-use ldisc numbers as they are part of the userspace ABI
and writing over an existing ldisc will cause demons to eat your computer.
After the return the ldisc data has been copied so you may free your own 
copy of the structure. You must not re-register over the top of the line
discipline even with the same data or your computer again will be eaten by
demons.
In order to remove a line discipline call tty_register_ldisc passing NULL.
In ancient times this always worked. In modern times the function will
return -EBUSY if the ldisc is currently in use. Since the ldisc referencing
code manages the module counts this should not usually be a concern.
Heed this warning: the reference count field of the registered copies of the
tty_ldisc structure in the ldisc table counts the number of lines using this
discipline. The reference count of the tty_ldisc structure within a tty 
counts the number of active users of the ldisc at this instant. In effect it
counts the number of threads of execution within an ldisc method (plus those
about to enter and exit although this detail matters not).
Line Discipline Methods
-----------------------
TTY side interfaces:
close()		-	This is called on a terminal when the line
			discipline is being unplugged. At the point of
			execution no further users will enter the
			ldisc code for this tty. Can sleep.
open()		-	Called when the line discipline is attached to
			the terminal. No other call into the line
			discipline for this tty will occur until it
			completes successfully. Can sleep.
write()		-	A process is writing data from user space
			through the line discipline. Multiple write calls
			are serialized by the tty layer for the ldisc. May
			sleep.
flush_buffer()	-	May be called at any point between open and close.
chars_in_buffer() -	Report the number of bytes in the buffer.
set_termios()	-	Called on termios structure changes. The caller
			passes the old termios data and the current data
			is in the tty. Called under the termios lock so
			may not sleep. Serialized against itself only.
read()		-	Move data from the line discipline to the user.
			Multiple read calls may occur in parallel and the
			ldisc must deal with serialization issues. May 
			sleep.
poll()		-	Check the status for the poll/select calls. Multiple
			poll calls may occur in parallel. May sleep.
ioctl()		-	Called when an ioctl is handed to the tty layer
			that might be for the ldisc. Multiple ioctl calls
			may occur in parallel. May sleep. 
Driver Side Interfaces:
receive_buf()	-	Hand buffers of bytes from the driver to the ldisc
			for processing. Semantics currently rather
			mysterious 8(
receive_room()	-	Can be called by the driver layer at any time when
			the ldisc is opened. The ldisc must be able to
			handle the reported amount of data at that instant.
			Synchronization between active receive_buf and
			receive_room calls is down to the driver not the
			ldisc. Must not sleep.
write_wakeup()	-	May be called at any point between open and close.
			The TTY_DO_WRITE_WAKEUP flag indicates if a call
			is needed but always races versus calls. Thus the
			ldisc must be careful about setting order and to
			handle unexpected calls. Must not sleep.
Locking
Callers to the line discipline functions from the tty layer are required to
take line discipline locks. The same is true of calls from the driver side
but not yet enforced.
Three calls are now provided
	ldisc = tty_ldisc_ref(tty);
takes a handle to the line discipline in the tty and returns it. If no ldisc
is currently attached or the ldisc is being closed and re-opened at this
point then NULL is returned. While this handle is held the ldisc will not
change or go away.
	tty_ldisc_deref(ldisc)
Returns the ldisc reference and allows the ldisc to be closed. Returning the
reference takes away your right to call the ldisc functions until you take
a new reference.
	ldisc = tty_ldisc_ref_wait(tty);
Performs the same function as tty_ldisc_ref except that it will wait for an
ldisc change to complete and then return a reference to the new ldisc. 
While these functions are slightly slower than the old code they should have
minimal impact as most receive logic uses the flip buffers and they only
need to take a reference when they push bits up through the driver.
A caution: The ldisc->open(), ldisc->close() and driver->set_ldisc 
functions are called with the ldisc unavailable. Thus tty_ldisc_ref will
fail in this situation if used within these functions. Ldisc and driver
code calling its own functions must be careful in this case. 
Driver Interface
----------------
open()		-	Called when a device is opened. May sleep
close()		-	Called when a device is closed. At the point of
			return from this call the driver must make no 
			further ldisc calls of any kind. May sleep
write()		-	Called to write bytes to the device. May not
			sleep. May occur in parallel in special cases. 
			Because this includes panic paths drivers generally
			shouldn't try and do clever locking here.
put_char()	-	Stuff a single character onto the queue. The
			driver is guaranteed following up calls to
			flush_chars.
flush_chars()	-	Ask the kernel to write put_char queue
write_room()	-	Return the number of characters tht can be stuffed
			into the port buffers without overflow (or less).
			The ldisc is responsible for being intelligent
 			about multi-threading of write_room/write calls
ioctl()		-	Called when an ioctl may be for the driver
set_termios()	-	Called on termios change, may get parallel calls,
			may block for now (may change that)
set_ldisc()	-	Notifier for discipline change. At the point this 
			is done the discipline is not yet usable. Can now
			sleep (I think)
throttle()	-	Called by the ldisc to ask the driver to do flow
			control.  Serialization including with unthrottle
			is the job of the ldisc layer.
unthrottle()	-	Called by the ldisc to ask the driver to stop flow
			control.
stop()		-	Ldisc notifier to the driver to stop output. As with
			throttle the serializations with start() are down
			to the ldisc layer.
start()		-	Ldisc notifier to the driver to start output.
hangup()	-	Ask the tty driver to cause a hangup initiated
			from the host side. [Can sleep ??]
break_ctl()	-	Send RS232 break. Can sleep. Can get called in
			parallel, driver must serialize (for now), and
			with write calls.
wait_until_sent() -	Wait for characters to exit the hardware queue
			of the driver. Can sleep
send_xchar()	  -	Send XON/XOFF and if possible jump the queue with
			it in order to get fast flow control responses.
			Cannot sleep ??
(-) linux-2.6.7/drivers/bluetooth/hci_ldisc.c (-4 / +4 lines)
 Lines 188-196    Link Here 
	}
	}
	/* Flush any pending characters in the driver and discipline. */
	/* Flush any pending characters in the driver and discipline. */
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
 Lines 280-286    Link Here 
	spin_lock_init(&hu->rx_lock);
	spin_lock_init(&hu->rx_lock);
	/* Flush any pending characters in the driver and line discipline */
	/* Flush any pending characters in the driver and line discipline. */
	/* FIXME: why is this needed. Note don't use ldisc_ref here as the
	   open path is before the ldisc is referencable */
	if (tty->ldisc.flush_buffer)
	if (tty->ldisc.flush_buffer)
		tty->ldisc.flush_buffer(tty);
		tty->ldisc.flush_buffer(tty);
(-) linux-2.6.7/drivers/char/amiserial.c (-8 / +4 lines)
 Lines 557-565    Link Here 
		return;
		return;
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
		wake_up_interruptible(&tty->write_wait);
	}
	}
}
}
 Lines 1023-1031    Link Here 
	info->xmit.head = info->xmit.tail = 0;
	info->xmit.head = info->xmit.tail = 0;
	local_irq_restore(flags);
	local_irq_restore(flags);
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
/*
/*
 Lines 1564-1571    Link Here 
	shutdown(info);
	shutdown(info);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
		
		tty->ldisc.flush_buffer(tty);
	tty_ldisc_flush(tty);
	tty->closing = 0;
	tty->closing = 0;
	info->event = 0;
	info->event = 0;
	info->tty = 0;
	info->tty = 0;
(-) linux-2.6.7/drivers/char/cyclades.c (-9 / +3 lines)
 Lines 972-981    Link Here 
	wake_up_interruptible(&info->delta_msr_wait);
	wake_up_interruptible(&info->delta_msr_wait);
    }
    }
    if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
    if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
        if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP))
        tty_wakeup(tty);
        && tty->ldisc.write_wakeup){
            (tty->ldisc.write_wakeup)(tty);
        }
        wake_up_interruptible(&tty->write_wait);
        wake_up_interruptible(&tty->write_wait);
    }
    }
#ifdef Z_WAKE
#ifdef Z_WAKE
 Lines 2852-2859    Link Here 
    shutdown(info);
    shutdown(info);
    if (tty->driver->flush_buffer)
    if (tty->driver->flush_buffer)
        tty->driver->flush_buffer(tty);
        tty->driver->flush_buffer(tty);
    if (tty->ldisc.flush_buffer)
    tty_ldisc_flush(tty);        
        tty->ldisc.flush_buffer(tty);
    CY_LOCK(info, flags);
    CY_LOCK(info, flags);
    tty->closing = 0;
    tty->closing = 0;
 Lines 4555-4564    Link Here 
	}
	}
	CY_UNLOCK(info, flags);
	CY_UNLOCK(info, flags);
    }
    }
    tty_wakeup(tty);
    wake_up_interruptible(&tty->write_wait);
    wake_up_interruptible(&tty->write_wait);
    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
	&& tty->ldisc.write_wakeup)
	    (tty->ldisc.write_wakeup)(tty);
} /* cy_flush_buffer */
} /* cy_flush_buffer */
(-) linux-2.6.7/drivers/char/epca.c (-15 / +6 lines)
 Lines 551-559    Link Here 
		if (tty->driver->flush_buffer)
		if (tty->driver->flush_buffer)
			tty->driver->flush_buffer(tty);
			tty->driver->flush_buffer(tty);
		if (tty->ldisc.flush_buffer)
		tty_ldisc_flush(tty);
			tty->ldisc.flush_buffer(tty);
		shutdown(ch);
		shutdown(ch);
		tty->closing = 0;
		tty->closing = 0;
		ch->event = 0;
		ch->event = 0;
 Lines 657-666    Link Here 
		cli();
		cli();
		if (tty->driver->flush_buffer)
		if (tty->driver->flush_buffer)
			tty->driver->flush_buffer(tty);
			tty->driver->flush_buffer(tty);
		tty_ldisc_flush(tty);
		if (tty->ldisc.flush_buffer)
			tty->ldisc.flush_buffer(tty);
		shutdown(ch);
		shutdown(ch);
		ch->tty   = NULL;
		ch->tty   = NULL;
 Lines 1129-1136    Link Here 
	restore_flags(flags);
	restore_flags(flags);
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
	tty_wakeup(tty);
		(tty->ldisc.write_wakeup)(tty);
} /* End pc_flush_buffer */
} /* End pc_flush_buffer */
 Lines 2271-2279    Link Here 
				{ /* Begin if LOWWAIT */
				{ /* Begin if LOWWAIT */
					ch->statusflags &= ~LOWWAIT;
					ch->statusflags &= ~LOWWAIT;
					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
					tty_wakeup(tty);
						  tty->ldisc.write_wakeup)
						(tty->ldisc.write_wakeup)(tty);
					wake_up_interruptible(&tty->write_wait);
					wake_up_interruptible(&tty->write_wait);
				} /* End if LOWWAIT */
				} /* End if LOWWAIT */
 Lines 2290-2298    Link Here 
				{ /* Begin if EMPTYWAIT */
				{ /* Begin if EMPTYWAIT */
					ch->statusflags &= ~EMPTYWAIT;
					ch->statusflags &= ~EMPTYWAIT;
					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
					tty_wakeup(tty);
						  tty->ldisc.write_wakeup)
						(tty->ldisc.write_wakeup)(tty);
					wake_up_interruptible(&tty->write_wait);
					wake_up_interruptible(&tty->write_wait);
 Lines 3157-3162    Link Here 
			}
			}
			else 
			else 
			{
			{
				/* ldisc lock already held in ioctl */
				if (tty->ldisc.flush_buffer)
				if (tty->ldisc.flush_buffer)
					tty->ldisc.flush_buffer(tty);
					tty->ldisc.flush_buffer(tty);
			}
			}
(-) linux-2.6.7/drivers/char/esp.c (-10 / +3 lines)
 Lines 762-771    Link Here 
		return;
		return;
	if (test_and_clear_bit(ESP_EVENT_WRITE_WAKEUP, &info->event)) {
	if (test_and_clear_bit(ESP_EVENT_WRITE_WAKEUP, &info->event)) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
	}
	}
}
}
 Lines 1370-1379    Link Here 
	cli();
	cli();
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	sti();
	sti();
	wake_up_interruptible(&tty->write_wait);
	tty_wakeup(tty);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
/*
/*
 Lines 2073-2080    Link Here 
	shutdown(info);
	shutdown(info);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
	tty->closing = 0;
	tty->closing = 0;
	info->event = 0;
	info->event = 0;
	info->tty = 0;
	info->tty = 0;
(-) linux-2.6.7/drivers/char/generic_serial.c (-10 / +6 lines)
 Lines 436-444    Link Here 
	restore_flags(flags);
	restore_flags(flags);
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
	func_exit ();
	func_exit ();
}
}
 Lines 578-586    Link Here 
	if (!tty) return;
	if (!tty) return;
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
		wake_up_interruptible(&tty->write_wait);
	}
	}
	func_exit ();
	func_exit ();
 Lines 694-701    Link Here 
{
{
	unsigned long flags;
	unsigned long flags;
	struct gs_port *port;
	struct gs_port *port;
	
	func_enter ();
	func_enter ()
	if (!tty) return;
	if (!tty) return;
 Lines 760-767    Link Here 
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
		
		tty->ldisc.flush_buffer(tty);
	tty_ldisc_flush(tty);
	tty->closing = 0;
	tty->closing = 0;
	port->event = 0;
	port->event = 0;
(-) linux-2.6.7/drivers/char/hvc_console.c (-4 / +1 lines)
 Lines 248-257    Link Here 
		if (hp->do_wakeup) {
		if (hp->do_wakeup) {
			hp->do_wakeup = 0;
			hp->do_wakeup = 0;
			if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
			tty_wakeup(tty);
			    && tty->ldisc.write_wakeup)
				(tty->ldisc.write_wakeup)(tty);
			wake_up_interruptible(&tty->write_wait);
		}
		}
	}
	}
(-) linux-2.6.7/drivers/char/isicom.c (-9 / +5 lines)
 Lines 483-492    Link Here 
	
	
	if (!tty)
	if (!tty)
		return;
		return;
	
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);	
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
} 		
} 		
 		
 		
 Lines 1118-1125    Link Here 
	isicom_shutdown_port(port);
	isicom_shutdown_port(port);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
		
		tty->ldisc.flush_buffer(tty);
	tty_ldisc_flush(tty);
	tty->closing = 0;
	tty->closing = 0;
	port->tty = 0;
	port->tty = 0;
	if (port->blocked_open) {
	if (port->blocked_open) {
 Lines 1563-1571    Link Here 
	restore_flags(flags);
	restore_flags(flags);
	
	
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
(-) linux-2.6.7/drivers/char/moxa.c (-11 / +5 lines)
 Lines 613-620    Link Here 
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
			
	tty->closing = 0;
	tty->closing = 0;
	ch->event = 0;
	ch->event = 0;
	ch->tty = 0;
	ch->tty = 0;
 Lines 688-696    Link Here 
	if (ch == NULL)
	if (ch == NULL)
		return;
		return;
	MoxaPortFlushData(ch->port, 1);
	MoxaPortFlushData(ch->port, 1);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup) (tty);
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
}
}
 Lines 948-956    Link Here 
				if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) {
				if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) {
					if (!tp->stopped) {
					if (!tp->stopped) {
						ch->statusflags &= ~LOWWAIT;
						ch->statusflags &= ~LOWWAIT;
						if ((tp->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
						tty_wakeup(tty);
						  tp->ldisc.write_wakeup)
							(tp->ldisc.write_wakeup) (tp);
						wake_up_interruptible(&tp->write_wait);
						wake_up_interruptible(&tp->write_wait);
					}
					}
				}
				}
 Lines 1117-1125    Link Here 
	if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
	if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
		if (MoxaPortTxQueue(ch->port) == 0) {
		if (MoxaPortTxQueue(ch->port) == 0) {
			ch->statusflags &= ~EMPTYWAIT;
			ch->statusflags &= ~EMPTYWAIT;
			if ((ch->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
			tty_wakeup(tty);
			    ch->tty->ldisc.write_wakeup)
				(ch->tty->ldisc.write_wakeup) (ch->tty);
			wake_up_interruptible(&ch->tty->write_wait);
			wake_up_interruptible(&ch->tty->write_wait);
			return;
			return;
		}
		}
(-) linux-2.6.7/drivers/char/mxser.c (-8 / +4 lines)
 Lines 676-684    Link Here 
	tty = info->tty;
	tty = info->tty;
	if (tty) {
	if (tty) {
		if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) {
		if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) {
			if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
			tty_wakeup(tty);
			    tty->ldisc.write_wakeup)
				(tty->ldisc.write_wakeup) (tty);
			wake_up_interruptible(&tty->write_wait);
			wake_up_interruptible(&tty->write_wait);
		}
		}
		if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) {
		if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) {
 Lines 815-822    Link Here 
	mxser_shutdown(info);
	mxser_shutdown(info);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
	tty->closing = 0;
	tty->closing = 0;
	info->event = 0;
	info->event = 0;
	info->tty = 0;
	info->tty = 0;
 Lines 974-982    Link Here 
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	restore_flags(flags);
	restore_flags(flags);
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup) (tty);
}
}
static int mxser_ioctl(struct tty_struct *tty, struct file *file,
static int mxser_ioctl(struct tty_struct *tty, struct file *file,
(-) linux-2.6.7/drivers/char/n_tty.c (-53 / +329 lines)
 Lines 104-114    Link Here 
	spin_unlock_irqrestore(&tty->read_lock, flags);
	spin_unlock_irqrestore(&tty->read_lock, flags);
}
}
/* 
/**
 * Check whether to call the driver.unthrottle function.
 *	check_unthrottle	-	allow new receive data
 * We test the TTY_THROTTLED bit first so that it always
 *	@tty; tty device
 * indicates the current state.
 *
 *	Check whether to call the driver.unthrottle function.
 *	We test the TTY_THROTTLED bit first so that it always
 *	indicates the current state. The decision about whether
 *	it is worth allowing more input has been taken by the caller.
 *	Can sleep, may be called under the atomic_read semaphore but
 *	this is not guaranteed.
 */
 */
 
static void check_unthrottle(struct tty_struct * tty)
static void check_unthrottle(struct tty_struct * tty)
{
{
	if (tty->count &&
	if (tty->count &&
 Lines 117-126    Link Here 
		tty->driver->unthrottle(tty);
		tty->driver->unthrottle(tty);
}
}
/*
/**
 * Reset the read buffer counters, clear the flags, 
 *	reset_buffer_flags	-	reset buffer state
 * and make sure the driver is unthrottled. Called
 *	@tty: terminal to reset
 * from n_tty_open() and n_tty_flush_buffer().
 *
 *	Reset the read buffer counters, clear the flags, 
 *	and make sure the driver is unthrottled. Called
 *	from n_tty_open() and n_tty_flush_buffer().
 */
 */
static void reset_buffer_flags(struct tty_struct *tty)
static void reset_buffer_flags(struct tty_struct *tty)
{
{
 Lines 134-142    Link Here 
	check_unthrottle(tty);
	check_unthrottle(tty);
}
}
/*
/**
 * Flush the input buffer
 *	n_tty_flush_buffer	-	clean input queue
 *	@tty:	terminal device
 *
 *	Flush the input buffer. Called when the line discipline is
 *	being closed, when the tty layer wants the buffer flushed (eg
 *	at hangup) or when the N_TTY line discipline internally has to
 *	clean the pending queue (for example some signals).
 *
 *	FIXME: tty->ctrl_status is not spinlocked and relies on
 *	lock_kernel() still.
 */
 */
 
void n_tty_flush_buffer(struct tty_struct * tty)
void n_tty_flush_buffer(struct tty_struct * tty)
{
{
	/* clear everything and unthrottle the driver */
	/* clear everything and unthrottle the driver */
 Lines 151-159    Link Here 
	}
	}
}
}
/*
/**
 * Return number of characters buffered to be delivered to user
 *	n_tty_chars_in_buffer	-	report available bytes
 *	@tty: tty device
 *
 *	Report the number of characters buffered to be delivered to user
 *	at this instant in time. 
 */
 */
 
ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
ssize_t n_tty_chars_in_buffer(struct tty_struct *tty)
{
{
	unsigned long flags;
	unsigned long flags;
 Lines 171-190    Link Here 
	return n;
	return n;
}
}
/**
 *	is_utf8_continuation	-	utf8 multibyte check
 *	@c: byte to check
 *
 *	Returns true if the utf8 character 'c' is a multibyte continuation
 *	character. We use this to correctly compute the on screen size
 *	of the character when printing
 */
 
static inline int is_utf8_continuation(unsigned char c)
static inline int is_utf8_continuation(unsigned char c)
{
{
	return (c & 0xc0) == 0x80;
	return (c & 0xc0) == 0x80;
}
}
/**
 *	is_continuation		-	multibyte check
 *	@c: byte to check
 *
 *	Returns true if the utf8 character 'c' is a multibyte continuation
 *	character and the terminal is in unicode mode.
 */
 
static inline int is_continuation(unsigned char c, struct tty_struct *tty)
static inline int is_continuation(unsigned char c, struct tty_struct *tty)
{
{
	return I_IUTF8(tty) && is_utf8_continuation(c);
	return I_IUTF8(tty) && is_utf8_continuation(c);
}
}
/*
/**
 * Perform OPOST processing.  Returns -1 when the output device is
 *	opost			-	output post processor
 * full and the character must be retried.
 *	@c: character (or partial unicode symbol)
 *	@tty: terminal device
 *
 *	Perform OPOST processing.  Returns -1 when the output device is
 *	full and the character must be retried. Note that Linux currently
 *	ignores TABDLY, CRDLY, VTDLY, FFDLY and NLDLY. They simply aren't
 *	relevant in the world today. If you ever need them, add them here.
 *
 *	Called from both the receive and transmit sides and can be called
 *	re-entrantly. Relies on lock_kernel() still.
 */
 */
 
static int opost(unsigned char c, struct tty_struct *tty)
static int opost(unsigned char c, struct tty_struct *tty)
{
{
	int	space, spaces;
	int	space, spaces;
 Lines 244-253    Link Here 
	return 0;
	return 0;
}
}
/*
/**
 * opost_block --- to speed up block console writes, among other
 *	opost_block		-	block postprocess
 * things.
 *	@tty: terminal device
 *	@inbuf: user buffer
 *	@nr: number of bytes
 *
 *	This path is used to speed up block console writes, among other
 *	things when processing blocks of output data. It handles only
 *	the simple cases normally found and helps to generate blocks of
 *	symbols for the console driver and thus improve performance.
 *
 *	Called from write_chan under the tty layer write lock.
 */
 */
 
static ssize_t opost_block(struct tty_struct * tty,
static ssize_t opost_block(struct tty_struct * tty,
		       const unsigned char __user * inbuf, unsigned int nr)
		       const unsigned char __user * inbuf, unsigned int nr)
{
{
 Lines 309-321    Link Here 
}
}
/**
 *	put_char	-	write character to driver
 *	@c: character (or part of unicode symbol)
 *	@tty: terminal device
 *
 *	Queue a byte to the driver layer for output
 */
 
static inline void put_char(unsigned char c, struct tty_struct *tty)
static inline void put_char(unsigned char c, struct tty_struct *tty)
{
{
	tty->driver->put_char(tty, c);
	tty->driver->put_char(tty, c);
}
}
/* Must be called only when L_ECHO(tty) is true. */
/**
 *	echo_char	-	echo characters
 *	@c: unicode byte to echo
 *	@tty: terminal device
 *
 *	Echo user input back onto the screen. This must be called only when 
 *	L_ECHO(tty) is true. Called from the driver receive_buf path.
 */
static void echo_char(unsigned char c, struct tty_struct *tty)
static void echo_char(unsigned char c, struct tty_struct *tty)
{
{
 Lines 336-341    Link Here 
	}
	}
}
}
/**
 *	eraser		-	handle erase function
 *	@c: character input
 *	@tty: terminal device
 *
 *	Perform erase and neccessary output when an erase character is
 *	present in the stream from the driver layer. Handles the complexities
 *	of UTF-8 multibyte symbols.
 */
 
static void eraser(unsigned char c, struct tty_struct *tty)
static void eraser(unsigned char c, struct tty_struct *tty)
{
{
	enum { ERASE, WERASE, KILL } kill_type;
	enum { ERASE, WERASE, KILL } kill_type;
 Lines 468-473    Link Here 
		finish_erasing(tty);
		finish_erasing(tty);
}
}
/**
 *	isig		-	handle the ISIG optio
 *	@sig: signal
 *	@tty: terminal
 *	@flush: force flush
 *
 *	Called when a signal is being sent due to terminal input. This
 *	may caus terminal flushing to take place according to the termios
 *	settings and character used. Called from the driver receive_buf
 *	path so serialized.
 */
 
static inline void isig(int sig, struct tty_struct *tty, int flush)
static inline void isig(int sig, struct tty_struct *tty, int flush)
{
{
	if (tty->pgrp > 0)
	if (tty->pgrp > 0)
 Lines 479-484    Link Here 
	}
	}
}
}
/**
 *	n_tty_receive_break	-	handle break
 *	@tty: terminal
 *
 *	An RS232 break event has been hit in the incoming bitstream. This
 *	can cause a variety of events depending upon the termios settings.
 *
 *	Called from the receive_buf path so single threaded.
 */
 
static inline void n_tty_receive_break(struct tty_struct *tty)
static inline void n_tty_receive_break(struct tty_struct *tty)
{
{
	if (I_IGNBRK(tty))
	if (I_IGNBRK(tty))
 Lines 495-513    Link Here 
	wake_up_interruptible(&tty->read_wait);
	wake_up_interruptible(&tty->read_wait);
}
}
/**
 *	n_tty_receive_overrun	-	handle overrun reporting
 *	@tty: terminal
 *
 *	Data arrived faster than we could process it. While the tty
 *	driver has flagged this the bits that were missed are gone
 *	forever.
 *
 *	Called from the receive_buf path so single threaded. Does not
 *	need locking as num_overrun and overrun_time are function
 *	private.
 */
 
static inline void n_tty_receive_overrun(struct tty_struct *tty)
static inline void n_tty_receive_overrun(struct tty_struct *tty)
{
{
	char buf[64];
	char buf[64];
	tty->num_overrun++;
	tty->num_overrun++;
	if (time_before(tty->overrun_time, jiffies - HZ)) {
	if (time_before(tty->overrun_time, jiffies - HZ)) {
		printk("%s: %d input overrun(s)\n", tty_name(tty, buf),
		printk(KERN_WARNING "%s: %d input overrun(s)\n", tty_name(tty, buf),
		       tty->num_overrun);
		       tty->num_overrun);
		tty->overrun_time = jiffies;
		tty->overrun_time = jiffies;
		tty->num_overrun = 0;
		tty->num_overrun = 0;
	}
	}
}
}
/**
 *	n_tty_receive_parity_error	-	error notifier
 *	@tty: terminal device
 *	@c: character
 *
 *	Process a parity error and queue the right data to indicate
 *	the error case if neccessary. Locking as per n_tty_receive_buf.
 */
static inline void n_tty_receive_parity_error(struct tty_struct *tty,
static inline void n_tty_receive_parity_error(struct tty_struct *tty,
					      unsigned char c)
					      unsigned char c)
{
{
 Lines 525-530    Link Here 
	wake_up_interruptible(&tty->read_wait);
	wake_up_interruptible(&tty->read_wait);
}
}
/**
 *	n_tty_receive_char	-	perform processing
 *	@tty: terminal device
 *	@c: character
 *
 *	Process an individual character of input received from the driver.
 *	This is serialized with respect to itself by the rules for the 
 *	driver above.
 */
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
{
{
	unsigned long flags;
	unsigned long flags;
 Lines 716-721    Link Here 
	put_tty_queue(c, tty);
	put_tty_queue(c, tty);
}	
}	
/**
 *	n_tty_receive_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 int n_tty_receive_room(struct tty_struct *tty)
static int n_tty_receive_room(struct tty_struct *tty)
{
{
	int	left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
	int	left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
 Lines 734-743    Link Here 
	return 0;
	return 0;
}
}
/*
/**
 * Required for the ptys, serial driver etc. since processes
 *	n_tty_write_wakeup	-	asynchronous I/O notifier
 * that attach themselves to the master and rely on ASYNC
 *	@tty: tty device
 * IO must be woken up
 *
 *	Required for the ptys, serial driver etc. since processes
 *	that attach themselves to the master and rely on ASYNC
 *	IO must be woken up
 */
 */
static void n_tty_write_wakeup(struct tty_struct *tty)
static void n_tty_write_wakeup(struct tty_struct *tty)
 Lines 750-755    Link Here 
	return;
	return;
}
}
/**
 *	n_tty_receive_buf	-	data receive
 *	@tty: terminal device
 *	@cp: buffer
 *	@fp: flag buffer
 *	@count: characters
 *
 *	Called by the terminal driver when a block of characters has
 *	been received. This function must be called from soft contexts
 *	not from interrupt context. The driver is responsible for making
 *	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,
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
			      char *fp, int count)
			      char *fp, int count)
{
{
 Lines 833-838    Link Here 
	        current->sighand->action[sig-1].sa.sa_handler == SIG_IGN);
	        current->sighand->action[sig-1].sa.sa_handler == SIG_IGN);
}
}
/**
 *	n_tty_set_termios	-	termios data changed
 *	@tty: terminal
 *	@old: previous data
 *
 *	Called by the tty layer when the user changes termios flags so
 *	that the line discipline can plan ahead. This function cannot sleep
 *	and is protected from re-entry by the tty layer. The user is 
 *	guaranteed that this function will not be re-entered or in progress
 *	when the ldisc is closed.
 */
 
static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
static void n_tty_set_termios(struct tty_struct *tty, struct termios * old)
{
{
	if (!tty)
	if (!tty)
 Lines 848-854    Link Here 
	    I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
	    I_ICRNL(tty) || I_INLCR(tty) || L_ICANON(tty) ||
	    I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
	    I_IXON(tty) || L_ISIG(tty) || L_ECHO(tty) ||
	    I_PARMRK(tty)) {
	    I_PARMRK(tty)) {
		local_irq_disable(); // FIXME: is this safe?
		memset(tty->process_char_map, 0, 256/8);
		memset(tty->process_char_map, 0, 256/8);
		if (I_IGNCR(tty) || I_ICRNL(tty))
		if (I_IGNCR(tty) || I_ICRNL(tty))
 Lines 884-890    Link Here 
			set_bit(SUSP_CHAR(tty), tty->process_char_map);
			set_bit(SUSP_CHAR(tty), tty->process_char_map);
		}
		}
		clear_bit(__DISABLED_CHAR, tty->process_char_map);
		clear_bit(__DISABLED_CHAR, tty->process_char_map);
		local_irq_enable(); // FIXME: is this safe?
		tty->raw = 0;
		tty->raw = 0;
		tty->real_raw = 0;
		tty->real_raw = 0;
	} else {
	} else {
 Lines 898-903    Link Here 
	}
	}
}
}
/**
 *	n_tty_close		-	close the ldisc for this tty
 *	@tty: device
 *
 *	Called from the terminal layer when this line discipline is 
 *	being shut down, either because of a close or becsuse of a 
 *	discipline change. The function will not be called while other
 *	ldisc methods are in progress.
 */
 
static void n_tty_close(struct tty_struct *tty)
static void n_tty_close(struct tty_struct *tty)
{
{
	n_tty_flush_buffer(tty);
	n_tty_flush_buffer(tty);
 Lines 907-917    Link Here 
	}
	}
}
}
/**
 *	n_tty_open		-	open an ldisc
 *	@tty: terminal to open
 *
 *	Called when this line discipline is being attached to the 
 *	terminal device. Can sleep. Called serialized so that no
 *	other events will occur in parallel. No further open will occur
 *	until a close.
 */
static int n_tty_open(struct tty_struct *tty)
static int n_tty_open(struct tty_struct *tty)
{
{
	if (!tty)
	if (!tty)
		return -EINVAL;
		return -EINVAL;
	/* This one is ugly. Currently a malloc failure here can panic */
	if (!tty->read_buf) {
	if (!tty->read_buf) {
		tty->read_buf = alloc_buf();
		tty->read_buf = alloc_buf();
		if (!tty->read_buf)
		if (!tty->read_buf)
 Lines 937-950    Link Here 
	return 0;
	return 0;
}
}
/*
/**
 * Helper function to speed up read_chan.  It is only called when
 * 	copy_from_read_buf	-	copy read data directly
 * ICANON is off; it copies characters straight from the tty queue to
 *	@tty: terminal device
 * user space directly.  It can be profitably called twice; once to
 *	@b: user data
 * drain the space from the tail pointer to the (physical) end of the
 *	@nr: size of data
 * buffer, and once to drain the space from the (physical) beginning of
 *
 * the buffer to head pointer.
 *	Helper function to speed up read_chan.  It is only called when
 *	ICANON is off; it copies characters straight from the tty queue to
 *	user space directly.  It can be profitably called twice; once to
 *	drain the space from the tail pointer to the (physical) end of the
 *	buffer, and once to drain the space from the (physical) beginning of
 *	the buffer to head pointer.
 *
 *	Called under the tty->atomic_read sem and with TTY_DONT_FLIP set
 *
 */
 */
 
static inline int copy_from_read_buf(struct tty_struct *tty,
static inline int copy_from_read_buf(struct tty_struct *tty,
				      unsigned char __user **b,
				      unsigned char __user **b,
				      size_t *nr)
				      size_t *nr)
 Lines 975-999    Link Here 
extern ssize_t redirected_tty_write(struct file *,const char *,size_t,loff_t *);
extern ssize_t redirected_tty_write(struct file *,const char *,size_t,loff_t *);
static ssize_t read_chan(struct tty_struct *tty, struct file *file,
/**
			 unsigned char __user *buf, size_t nr)
 *	job_control		-	check job control
 *	@tty: tty
 *	@file: file handle
 *
 *	Perform job control management checks on this file/tty descriptor
 *	and if appropriate send any needed signals and return a negative 
 *	error code if action should be taken.
 */
 
static int job_control(struct tty_struct *tty, struct file *file)
{
{
	unsigned char __user *b = buf;
	DECLARE_WAITQUEUE(wait, current);
	int c;
	int minimum, time;
	ssize_t retval = 0;
	ssize_t size;
	long timeout;
	unsigned long flags;
do_it_again:
	if (!tty->read_buf) {
		printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
		return -EIO;
	}
	/* Job control check -- must be done at start and after
	/* Job control check -- must be done at start and after
	   every sleep (POSIX.1 7.1.1.4). */
	   every sleep (POSIX.1 7.1.1.4). */
	/* NOTE: not yet done after every sleep pending a thorough
	/* NOTE: not yet done after every sleep pending a thorough
 Lines 1011-1017    Link Here 
			return -ERESTARTSYS;
			return -ERESTARTSYS;
		}
		}
	}
	}
	return 0;
}
 
/**
 *	read_chan		-	read function for tty
 *	@tty: tty device
 *	@file: file object
 *	@buf: userspace buffer pointer
 *	@nr: size of I/O
 *
 *	Perform reads for the line discipline. We are guaranteed that the
 *	line discipline will not be closed under us but we may get multiple
 *	parallel readers and must handle this ourselves. We may also get
 *	a hangup. Always called in user context, may sleep.
 *
 *	This code must be sure never to sleep through a hangup.
 */
 
static ssize_t read_chan(struct tty_struct *tty, struct file *file,
			 unsigned char __user *buf, size_t nr)
{
	unsigned char __user *b = buf;
	DECLARE_WAITQUEUE(wait, current);
	int c;
	int minimum, time;
	ssize_t retval = 0;
	ssize_t size;
	long timeout;
	unsigned long flags;
do_it_again:
	if (!tty->read_buf) {
		printk("n_tty_read_chan: called with read_buf == NULL?!?\n");
		return -EIO;
	}
	c = job_control(tty, file);
	if(c < 0)
		return c;
	
	minimum = time = 0;
	minimum = time = 0;
	timeout = MAX_SCHEDULE_TIMEOUT;
	timeout = MAX_SCHEDULE_TIMEOUT;
	if (!tty->icanon) {
	if (!tty->icanon) {
 Lines 1033-1038    Link Here 
		}
		}
	}
	}
	/*
	 *	Internal serialization of reads.
	 */
	if (file->f_flags & O_NONBLOCK) {
	if (file->f_flags & O_NONBLOCK) {
		if (down_trylock(&tty->atomic_read))
		if (down_trylock(&tty->atomic_read))
			return -EAGAIN;
			return -EAGAIN;
 Lines 1182-1187    Link Here 
	return retval;
	return retval;
}
}
/**
 *	write_chan		-	write function for tty
 *	@tty: tty device
 *	@file: file object
 *	@buf: userspace buffer pointer
 *	@nr: size of I/O
 *
 *	Write function of the terminal device. This is serialized with
 *	respect to other write callers but not to termios changes, reads
 *	and other such events. We must be careful with N_TTY as the receive
 *	code will echo characters, thus calling driver write methods.
 *
 *	This code must be sure never to sleep through a hangup.
 */
 
static ssize_t write_chan(struct tty_struct * tty, struct file * file,
static ssize_t write_chan(struct tty_struct * tty, struct file * file,
			  const unsigned char __user * buf, size_t nr)
			  const unsigned char __user * buf, size_t nr)
{
{
 Lines 1251-1257    Link Here 
	return (b - buf) ? b - buf : retval;
	return (b - buf) ? b - buf : retval;
}
}
/* Called without the kernel lock held - fine */
/**
 *	normal_poll		-	poll method for N_TTY
 *	@tty: terminal device
 *	@file: file accessing it
 *	@wait: poll table
 *
 *	Called when the line discipline is asked to poll() for data or
 *	for special events. This code is not serialized with respect to
 *	other events save open/close.
 *
 *	This code must be sure never to sleep through a hangup.
 *	Called without the kernel lock held - fine
 *
 *	FIXME: if someone changes the VMIN or discipline settings for the
 *	terminal while another process is in poll() the poll does not
 *	recompute the new limits. Possibly set_termios should issue
 *	a read wakeup to fix this bug.
 */
 
static unsigned int normal_poll(struct tty_struct * tty, struct file * file, poll_table *wait)
static unsigned int normal_poll(struct tty_struct * tty, struct file * file, poll_table *wait)
{
{
	unsigned int mask = 0;
	unsigned int mask = 0;
 Lines 1292-1297    Link Here 
	n_tty_ioctl,		/* ioctl */
	n_tty_ioctl,		/* ioctl */
	n_tty_set_termios,	/* set_termios */
	n_tty_set_termios,	/* set_termios */
	normal_poll,		/* poll */
	normal_poll,		/* poll */
	NULL,			/* hangup */
	n_tty_receive_buf,	/* receive_buf */
	n_tty_receive_buf,	/* receive_buf */
	n_tty_receive_room,	/* receive_room */
	n_tty_receive_room,	/* receive_room */
	n_tty_write_wakeup	/* write_wakeup */
	n_tty_write_wakeup	/* write_wakeup */
(-) linux-2.6.7/drivers/char/pcmcia/synclink_cs.c (-19 / +40 lines)
 Lines 526-531    Link Here 
	return mgslpc_get_text_ptr;
	return mgslpc_get_text_ptr;
}
}
/**
 * line discipline callback wrappers
 *
 * The wrappers maintain line discipline references
 * while calling into the line discipline.
 *
 * ldisc_flush_buffer - flush line discipline receive buffers
 * ldisc_receive_buf  - pass receive data to line discipline
 */
static void ldisc_flush_buffer(struct tty_struct *tty)
{
	struct tty_ldisc *ld = tty_ldisc_ref(tty);
	if (ld) {
		if (ld->flush_buffer)
			ld->flush_buffer(tty);
		tty_ldisc_deref(ld);
	}
}
static void ldisc_receive_buf(struct tty_struct *tty,
			      const __u8 *data, char *flags, int count)
{
	struct tty_ldisc *ld;
	if (!tty)
		return;
	ld = tty_ldisc_ref(tty);
	if (ld) {
		if (ld->receive_buf)
			ld->receive_buf(tty, data, flags, count);
		tty_ldisc_deref(ld);
	}
}
static dev_link_t *mgslpc_attach(void)
static dev_link_t *mgslpc_attach(void)
{
{
    MGSLPC_INFO *info;
    MGSLPC_INFO *info;
 Lines 980-992    Link Here 
		printk("bh_transmit() entry on %s\n", info->device_name);
		printk("bh_transmit() entry on %s\n", info->device_name);
	if (tty) {
	if (tty) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup) {
			if ( debug_level >= DEBUG_LEVEL_BH )
				printk( "%s(%d):calling ldisc.write_wakeup on %s\n",
					__FILE__,__LINE__,info->device_name);
			(tty->ldisc.write_wakeup)(tty);
		}
		wake_up_interruptible(&tty->write_wait);
		wake_up_interruptible(&tty->write_wait);
	}
	}
}
}
 Lines 1871-1881    Link Here 
	info->tx_count = info->tx_put = info->tx_get = 0;
	info->tx_count = info->tx_put = info->tx_get = 0;
	del_timer(&info->tx_timer);	
	del_timer(&info->tx_timer);	
	spin_unlock_irqrestore(&info->lock,flags);
	spin_unlock_irqrestore(&info->lock,flags);
	
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
/* Send a high-priority XON/XOFF character
/* Send a high-priority XON/XOFF character
 Lines 2584-2592    Link Here 
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
		
	if (tty->ldisc.flush_buffer)
	ldisc_flush_buffer(tty);
		tty->ldisc.flush_buffer(tty);
		
		
	shutdown(info);
	shutdown(info);
	
	
 Lines 4055-4065    Link Here 
			} 
			} 
			else
			else
#endif
#endif
			{
				ldisc_receive_buf(tty, buf->data, info->flag_buf, framesize);
				/* Call the line discipline receive callback directly. */
				if (tty && tty->ldisc.receive_buf)
					tty->ldisc.receive_buf(tty, buf->data, info->flag_buf, framesize);
			}
		}
		}
	}
	}
(-) linux-2.6.7/drivers/char/pcxx.c (-31 / +5 lines)
 Lines 538-565    Link Here 
	
	
		if(tty->driver->flush_buffer)
		if(tty->driver->flush_buffer)
			tty->driver->flush_buffer(tty);
			tty->driver->flush_buffer(tty);
		if(tty->ldisc.flush_buffer)
		tty_ldisc_flush(tty);
			tty->ldisc.flush_buffer(tty);
		shutdown(info);
		shutdown(info);
		tty->closing = 0;
		tty->closing = 0;
		info->event = 0;
		info->event = 0;
		info->tty = NULL;
		info->tty = NULL;
#ifndef MODULE
/* ldiscs[] is not available in a MODULE
** worth noting that while I'm not sure what this hunk of code is supposed
** to do, it is not present in the serial.c driver.  Hmmm.  If you know,
** please send me a note.  brian@ilinx.com
** Don't know either what this is supposed to do christoph@lameter.com.
*/
		if(tty->ldisc.num != ldiscs[N_TTY].num) {
			if(tty->ldisc.close)
				(tty->ldisc.close)(tty);
			tty->ldisc = ldiscs[N_TTY];
			tty->termios->c_line = N_TTY;
			if(tty->ldisc.open)
				(tty->ldisc.open)(tty);
		}
#endif
		if(info->blocked_open) {
		if(info->blocked_open) {
			if(info->close_delay) {
			if(info->close_delay) {
				current->state = TASK_INTERRUPTIBLE;
				current->state = TASK_INTERRUPTIBLE;
 Lines 800-808    Link Here 
	memoff(ch);
	memoff(ch);
	restore_flags(flags);
	restore_flags(flags);
	wake_up_interruptible(&tty->write_wait);
	tty_wakeup(tty);
	if((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
static void pcxe_flush_chars(struct tty_struct *tty)
static void pcxe_flush_chars(struct tty_struct *tty)
 Lines 1675-1684    Link Here 
			if (event & LOWTX_IND) {
			if (event & LOWTX_IND) {
				if (ch->statusflags & LOWWAIT) {
				if (ch->statusflags & LOWWAIT) {
					ch->statusflags &= ~LOWWAIT;
					ch->statusflags &= ~LOWWAIT;
					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
					tty_wakeup(tty);
						tty->ldisc.write_wakeup)
						(tty->ldisc.write_wakeup)(tty);
					wake_up_interruptible(&tty->write_wait);
				}
				}
			}
			}
 Lines 1686-1695    Link Here 
				ch->statusflags &= ~TXBUSY;
				ch->statusflags &= ~TXBUSY;
				if (ch->statusflags & EMPTYWAIT) {
				if (ch->statusflags & EMPTYWAIT) {
					ch->statusflags &= ~EMPTYWAIT;
					ch->statusflags &= ~EMPTYWAIT;
					if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
					tty_wakeup(tty);
						tty->ldisc.write_wakeup)
						(tty->ldisc.write_wakeup)(tty);
					wake_up_interruptible(&tty->write_wait);
				}
				}
			}
			}
		}
		}
 Lines 2165-2172    Link Here 
				tty_wait_until_sent(tty, 0);
				tty_wait_until_sent(tty, 0);
			}
			}
			else {
			else {
				if(tty->ldisc.flush_buffer)
				tty_ldisc_flush(tty);
					tty->ldisc.flush_buffer(tty);
			}
			}
			/* Fall Thru */
			/* Fall Thru */
(-) linux-2.6.7/drivers/char/pty.c (-4 / +5 lines)
 Lines 91-100    Link Here 
	if (!o_tty)
	if (!o_tty)
		return;
		return;
	if ((o_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(o_tty);
	    o_tty->ldisc.write_wakeup)
		(o_tty->ldisc.write_wakeup)(o_tty);
	wake_up_interruptible(&o_tty->write_wait);
	set_bit(TTY_THROTTLED, &tty->flags);
	set_bit(TTY_THROTTLED, &tty->flags);
}
}
 Lines 107-112    Link Here 
 *   (2) avoid redundant copying for cases where count >> receive_room
 *   (2) avoid redundant copying for cases where count >> receive_room
 * N.B. Calls from user space may now return an error code instead of
 * N.B. Calls from user space may now return an error code instead of
 * a count.
 * a count.
 *
 * FIXME: Our pty_write method is called with our ldisc lock held but
 * not our partners. We can't just take the other one blindly without
 * risking deadlocks.  There is also the small matter of TTY_DONT_FLIP
 */
 */
static int pty_write(struct tty_struct * tty, int from_user,
static int pty_write(struct tty_struct * tty, int from_user,
		       const unsigned char *buf, int count)
		       const unsigned char *buf, int count)
(-) linux-2.6.7/drivers/char/riscom8.c (-8 / +4 lines)
 Lines 1127-1134    Link Here 
	rc_shutdown_port(bp, port);
	rc_shutdown_port(bp, port);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
	tty->closing = 0;
	tty->closing = 0;
	port->event = 0;
	port->event = 0;
	port->tty = 0;
	port->tty = 0;
 Lines 1301-1309    Link Here 
	restore_flags(flags);
	restore_flags(flags);
	
	
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
static int rc_tiocmget(struct tty_struct *tty, struct file *file)
static int rc_tiocmget(struct tty_struct *tty, struct file *file)
 Lines 1643-1651    Link Here 
		return;
		return;
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
		wake_up_interruptible(&tty->write_wait);
	}
	}
}
}
(-) linux-2.6.7/drivers/char/rocket.c (-12 / +14 lines)
 Lines 250-261    Link Here 
			  CHANNEL_t * cp, unsigned int ChanStatus)
			  CHANNEL_t * cp, unsigned int ChanStatus)
{
{
	unsigned int CharNStat;
	unsigned int CharNStat;
	int ToRecv, wRecv, space, count;
	int ToRecv, wRecv, space = 0, count;
	unsigned char *cbuf;
	unsigned char *cbuf;
	char *fbuf;
	char *fbuf;
	struct tty_ldisc *ld;
	ld = tty_ldisc_ref(tty);
	ToRecv = sGetRxCnt(cp);
	ToRecv = sGetRxCnt(cp);
	space = tty->ldisc.receive_room(tty);
	if (ld)
		space = ld->receive_room(tty);
	if (space > 2 * TTY_FLIPBUF_SIZE)
	if (space > 2 * TTY_FLIPBUF_SIZE)
		space = 2 * TTY_FLIPBUF_SIZE;
		space = 2 * TTY_FLIPBUF_SIZE;
	cbuf = tty->flip.char_buf;
	cbuf = tty->flip.char_buf;
 Lines 354-360    Link Here 
		count += ToRecv;
		count += ToRecv;
	}
	}
	/*  Push the data up to the tty layer */
	/*  Push the data up to the tty layer */
	tty->ldisc.receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count);
	ld->receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count);
	tty_ldisc_deref(ld);
}
}
/*
/*
 Lines 408-415    Link Here 
		clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
		clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
	if (info->xmit_cnt < WAKEUP_CHARS) {
	if (info->xmit_cnt < WAKEUP_CHARS) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
		tty_wakeup(tty);
			(tty->ldisc.write_wakeup) (tty);
		wake_up_interruptible(&tty->write_wait);
		wake_up_interruptible(&tty->write_wait);
#ifdef ROCKETPORT_HAVE_POLL_WAIT
#ifdef ROCKETPORT_HAVE_POLL_WAIT
		wake_up_interruptible(&tty->poll_wait);
		wake_up_interruptible(&tty->poll_wait);
 Lines 1022-1028    Link Here 
	unsigned long flags;
	unsigned long flags;
	int timeout;
	int timeout;
	CHANNEL_t *cp;
	CHANNEL_t *cp;
	
	if (rocket_paranoia_check(info, "rp_close"))
	if (rocket_paranoia_check(info, "rp_close"))
		return;
		return;
 Lines 1101-1108    Link Here 
	if (TTY_DRIVER_FLUSH_BUFFER_EXISTS(tty))
	if (TTY_DRIVER_FLUSH_BUFFER_EXISTS(tty))
		TTY_DRIVER_FLUSH_BUFFER(tty);
		TTY_DRIVER_FLUSH_BUFFER(tty);
	if (tty->ldisc.flush_buffer)
		
		tty->ldisc.flush_buffer(tty);
	tty_ldisc_flush(tty);
	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
 Lines 1730-1737    Link Here 
	
	
end:
end:
 	if (info->xmit_cnt < WAKEUP_CHARS) {
 	if (info->xmit_cnt < WAKEUP_CHARS) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))  && tty->ldisc.write_wakeup)
 		tty_wakeup(tty);
			(tty->ldisc.write_wakeup) (tty);
		wake_up_interruptible(&tty->write_wait);
		wake_up_interruptible(&tty->write_wait);
#ifdef ROCKETPORT_HAVE_POLL_WAIT
#ifdef ROCKETPORT_HAVE_POLL_WAIT
		wake_up_interruptible(&tty->poll_wait);
		wake_up_interruptible(&tty->poll_wait);
 Lines 1805-1812    Link Here 
#ifdef ROCKETPORT_HAVE_POLL_WAIT
#ifdef ROCKETPORT_HAVE_POLL_WAIT
	wake_up_interruptible(&tty->poll_wait);
	wake_up_interruptible(&tty->poll_wait);
#endif
#endif
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
	tty_wakeup(tty);
		(tty->ldisc.write_wakeup) (tty);
	cp = &info->channel;
	cp = &info->channel;
	sFlushTxFIFO(cp);
	sFlushTxFIFO(cp);
(-) linux-2.6.7/drivers/char/selection.c (+5 lines)
 Lines 281-292    Link Here 
{
{
	struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
	struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
	int	pasted = 0, count;
	int	pasted = 0, count;
	struct  tty_ldisc *ld;
	DECLARE_WAITQUEUE(wait, current);
	DECLARE_WAITQUEUE(wait, current);
	acquire_console_sem();
	acquire_console_sem();
	poke_blanked_console();
	poke_blanked_console();
	release_console_sem();
	release_console_sem();
	ld = tty_ldisc_ref_wait(tty);
	
	add_wait_queue(&vt->paste_wait, &wait);
	add_wait_queue(&vt->paste_wait, &wait);
	while (sel_buffer && sel_buffer_lth > pasted) {
	while (sel_buffer && sel_buffer_lth > pasted) {
		set_current_state(TASK_INTERRUPTIBLE);
		set_current_state(TASK_INTERRUPTIBLE);
 Lines 301-306    Link Here 
	}
	}
	remove_wait_queue(&vt->paste_wait, &wait);
	remove_wait_queue(&vt->paste_wait, &wait);
	current->state = TASK_RUNNING;
	current->state = TASK_RUNNING;
	tty_ldisc_deref(ld);
	return 0;
	return 0;
}
}
(-) linux-2.6.7/drivers/char/ser_a2232.c (-4 / +1 lines)
 Lines 603-612    Link Here 
					
					
				/* WakeUp if output buffer runs low */
				/* WakeUp if output buffer runs low */
				if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
				if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
					if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && port->gs.tty->ldisc.write_wakeup){
					tty_wakeup(port->gs.tty);
						(port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
					}
					wake_up_interruptible(&port->gs.tty->write_wait);
				}
				}
			} // if the port is used
			} // if the port is used
		} // for every port on the board
		} // for every port on the board
(-) linux-2.6.7/drivers/char/serial167.c (-19 / +3 lines)
 Lines 760-770    Link Here 
	wake_up_interruptible(&info->open_wait);
	wake_up_interruptible(&info->open_wait);
    }
    }
    if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
    if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
	if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP))
    	tty_wakeup(tty);
	&& tty->ldisc.write_wakeup){
	    (tty->ldisc.write_wakeup)(tty);
	}
	wake_up_interruptible(&tty->write_wait);
    }
    }
} /* do_softint */
} /* do_softint */
 Lines 1343-1352    Link Here 
    local_irq_save(flags);
    local_irq_save(flags);
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
    local_irq_restore(flags);
    local_irq_restore(flags);
    wake_up_interruptible(&tty->write_wait);
    tty_wakeup(tty);
    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
    && tty->ldisc.write_wakeup)
	(tty->ldisc.write_wakeup)(tty);
} /* cy_flush_buffer */
} /* cy_flush_buffer */
 Lines 1846-1863    Link Here 
    shutdown(info);
    shutdown(info);
    if (tty->driver->flush_buffer)
    if (tty->driver->flush_buffer)
	tty->driver->flush_buffer(tty);
	tty->driver->flush_buffer(tty);
    if (tty->ldisc.flush_buffer)
    tty_ldisc_flush(tty);
	tty->ldisc.flush_buffer(tty);
    info->event = 0;
    info->event = 0;
    info->tty = 0;
    info->tty = 0;
    if (tty->ldisc.num != ldiscs[N_TTY].num) {
	if (tty->ldisc.close)
	    (tty->ldisc.close)(tty);
	tty->ldisc = ldiscs[N_TTY];
	tty->termios->c_line = N_TTY;
	if (tty->ldisc.open)
	    (tty->ldisc.open)(tty);
    }
    if (info->blocked_open) {
    if (info->blocked_open) {
	if (info->close_delay) {
	if (info->close_delay) {
	    current->state = TASK_INTERRUPTIBLE;
	    current->state = TASK_INTERRUPTIBLE;
(-) linux-2.6.7/drivers/char/serial_tx3912.c (-4 / +1 lines)
 Lines 191-202    Link Here 
	}
	}
	
	
        if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
        if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
                if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
        	tty_wakeup(port->gs.tty);
                    port->gs.tty->ldisc.write_wakeup)
                        (port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
                rs_dprintk (TX3912_UART_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
                rs_dprintk (TX3912_UART_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
                            port->gs.wakeup_chars); 
                            port->gs.wakeup_chars); 
                wake_up_interruptible(&port->gs.tty->write_wait);
       	}	
       	}	
}
}
(-) linux-2.6.7/drivers/char/specialix.c (-11 / +4 lines)
 Lines 1468-1475    Link Here 
	sx_shutdown_port(bp, port);
	sx_shutdown_port(bp, port);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
	tty->closing = 0;
	tty->closing = 0;
	port->event = 0;
	port->event = 0;
	port->tty = 0;
	port->tty = 0;
 Lines 1646-1655    Link Here 
	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
	restore_flags(flags);
	restore_flags(flags);
	
	
	tty_wakeup(tty);
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
 Lines 2064-2075    Link Here 
	if(!(tty = port->tty)) 
	if(!(tty = port->tty)) 
		return;
		return;
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event))
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
	}
}
}
static struct tty_operations sx_ops = {
static struct tty_operations sx_ops = {
(-) linux-2.6.7/drivers/char/stallion.c (-10 / +3 lines)
 Lines 1197-1204    Link Here 
		portp->tx.tail = (char *) NULL;
		portp->tx.tail = (char *) NULL;
	}
	}
	set_bit(TTY_IO_ERROR, &tty->flags);
	set_bit(TTY_IO_ERROR, &tty->flags);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		(tty->ldisc.flush_buffer)(tty);
	tty->closing = 0;
	tty->closing = 0;
	portp->tty = (struct tty_struct *) NULL;
	portp->tty = (struct tty_struct *) NULL;
 Lines 1818-1827    Link Here 
		return;
		return;
	stl_flush(portp);
	stl_flush(portp);
	wake_up_interruptible(&tty->write_wait);
	tty_wakeup(tty);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
/*****************************************************************************/
/*****************************************************************************/
 Lines 2202-2211    Link Here 
	lock_kernel();
	lock_kernel();
	if (test_bit(ASYI_TXLOW, &portp->istate)) {
	if (test_bit(ASYI_TXLOW, &portp->istate)) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
	}
	}
	if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
	if (test_bit(ASYI_DCDCHANGE, &portp->istate)) {
		clear_bit(ASYI_DCDCHANGE, &portp->istate);
		clear_bit(ASYI_DCDCHANGE, &portp->istate);
(-) linux-2.6.7/drivers/char/sx.c (-4 / +1 lines)
 Lines 1044-1055    Link Here 
	}
	}
	if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
	if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
		if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(port->gs.tty);
		    port->gs.tty->ldisc.write_wakeup)
			(port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
		sx_dprintk (SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
		sx_dprintk (SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
		            port->gs.wakeup_chars); 
		            port->gs.wakeup_chars); 
		wake_up_interruptible(&port->gs.tty->write_wait);
	}
	}
	clear_bit (SX_PORT_TRANSMIT_LOCK, &port->locks);
	clear_bit (SX_PORT_TRANSMIT_LOCK, &port->locks);
(-) linux-2.6.7/drivers/char/synclink.c (-23 / +30 lines)
 Lines 993-998    Link Here 
	return 0;
	return 0;
}
}
/**
 * line discipline callback wrappers
 *
 * The wrappers maintain line discipline references
 * while calling into the line discipline.
 *
 * ldisc_receive_buf  - pass receive data to line discipline
 */
static void ldisc_receive_buf(struct tty_struct *tty,
			      const __u8 *data, char *flags, int count)
{
	struct tty_ldisc *ld;
	if (!tty)
		return;
	ld = tty_ldisc_ref(tty);
	if (ld) {
		if (ld->receive_buf)
			ld->receive_buf(tty, data, flags, count);
		tty_ldisc_deref(ld);
	}
}
/* mgsl_stop()		throttle (stop) transmitter
/* mgsl_stop()		throttle (stop) transmitter
 * 	
 * 	
 * Arguments:		tty	pointer to tty info structure
 * Arguments:		tty	pointer to tty info structure
 Lines 1153-1165    Link Here 
			__FILE__,__LINE__,info->device_name);
			__FILE__,__LINE__,info->device_name);
	if (tty) {
	if (tty) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup) {
			if ( debug_level >= DEBUG_LEVEL_BH )
				printk( "%s(%d):calling ldisc.write_wakeup on %s\n",
					__FILE__,__LINE__,info->device_name);
			(tty->ldisc.write_wakeup)(tty);
		}
		wake_up_interruptible(&tty->write_wait);
		wake_up_interruptible(&tty->write_wait);
	}
	}
 Lines 2415-2425    Link Here 
	spin_unlock_irqrestore(&info->irq_spinlock,flags);
	spin_unlock_irqrestore(&info->irq_spinlock,flags);
	
	
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);
	    tty->ldisc.write_wakeup)
}
		(tty->ldisc.write_wakeup)(tty);
		
}	/* end of mgsl_flush_buffer() */
/* mgsl_send_xchar()
/* mgsl_send_xchar()
 *
 *
 Lines 3253-3261    Link Here 
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
		
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
		
		
	shutdown(info);
	shutdown(info);
	
	
 Lines 6830-6840    Link Here 
			} 
			} 
			else
			else
#endif
#endif
			{
				ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
				/* Call the line discipline receive callback directly. */
				if ( tty && tty->ldisc.receive_buf )
				tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
			}
		}
		}
	}
	}
	/* Free the buffers used by this frame. */
	/* Free the buffers used by this frame. */
 Lines 7006-7014    Link Here 
			memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize);
			memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize);
			info->icount.rxok++;
			info->icount.rxok++;
			/* Call the line discipline receive callback directly. */
			ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
			if ( tty && tty->ldisc.receive_buf )
				tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
		}
		}
		/* Free the buffers used by this frame. */
		/* Free the buffers used by this frame. */
(-) linux-2.6.7/drivers/char/synclinkmp.c (-21 / +28 lines)
 Lines 718-723    Link Here 
	return 0;
	return 0;
}
}
/**
 * line discipline callback wrappers
 *
 * The wrappers maintain line discipline references
 * while calling into the line discipline.
 *
 * ldisc_receive_buf  - pass receive data to line discipline
 */
static void ldisc_receive_buf(struct tty_struct *tty,
			      const __u8 *data, char *flags, int count)
{
	struct tty_ldisc *ld;
	if (!tty)
		return;
	ld = tty_ldisc_ref(tty);
	if (ld) {
		if (ld->receive_buf)
			ld->receive_buf(tty, data, flags, count);
		tty_ldisc_deref(ld);
	}
}
/* tty callbacks */
/* tty callbacks */
/* Called when a port is opened.  Init and enable port.
/* Called when a port is opened.  Init and enable port.
 Lines 865-872    Link Here 
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
	shutdown(info);
	shutdown(info);
 Lines 1271-1279    Link Here 
	spin_unlock_irqrestore(&info->lock,flags);
	spin_unlock_irqrestore(&info->lock,flags);
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
/* throttle (stop) transmitter
/* throttle (stop) transmitter
 Lines 1936-1948    Link Here 
			__FILE__,__LINE__,info->device_name);
			__FILE__,__LINE__,info->device_name);
	if (tty) {
	if (tty) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup) {
			if ( debug_level >= DEBUG_LEVEL_BH )
				printk( "%s(%d):%s calling ldisc.write_wakeup\n",
					__FILE__,__LINE__,info->device_name);
			(tty->ldisc.write_wakeup)(tty);
		}
		wake_up_interruptible(&tty->write_wait);
		wake_up_interruptible(&tty->write_wait);
	}
	}
}
}
 Lines 4864-4878    Link Here 
			}
			}
			else
			else
#endif
#endif
			{
				ldisc_receive_buf(tty,info->tmp_rx_buf,
				if ( tty && tty->ldisc.receive_buf ) {
						  info->flag_buf, framesize);
					/* Call the line discipline receive callback directly. */
					tty->ldisc.receive_buf(tty,
						info->tmp_rx_buf,
						info->flag_buf,
						framesize);
				}
			}
		}
		}
	}
	}
	/* Free the buffers used by this frame. */
	/* Free the buffers used by this frame. */
(-) linux-2.6.7/drivers/char/tty_io.c (-84 / +546 lines)
 Lines 91-96    Link Here 
#include <linux/module.h>
#include <linux/module.h>
#include <linux/smp_lock.h>
#include <linux/smp_lock.h>
#include <linux/device.h>
#include <linux/device.h>
#include <linux/wait.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/system.h>
 Lines 119-129    Link Here 
EXPORT_SYMBOL(tty_std_termios);
EXPORT_SYMBOL(tty_std_termios);
/* This list gets poked at by procfs and various bits of boot up code. This
   could do with some rationalisation such as pulling the tty proc function
   into this file */
   
LIST_HEAD(tty_drivers);			/* linked list of tty drivers */
LIST_HEAD(tty_drivers);			/* linked list of tty drivers */
struct tty_ldisc ldiscs[NR_LDISCS];	/* line disc dispatch table	*/
/* Semaphore to protect creating and releasing a tty */
/* Semaphore to protect creating and releasing a tty. This is shared with
   vt.c for deeply disgusting hack reasons */
DECLARE_MUTEX(tty_sem);
DECLARE_MUTEX(tty_sem);
/* Lock for tty_termios changes - private to tty_io/tty_ioctl */
spinlock_t tty_termios_lock = SPIN_LOCK_UNLOCKED;
#ifdef CONFIG_UNIX98_PTYS
#ifdef CONFIG_UNIX98_PTYS
extern struct tty_driver *ptm_driver;	/* Unix98 pty masters; for /dev/ptmx */
extern struct tty_driver *ptm_driver;	/* Unix98 pty masters; for /dev/ptmx */
 Lines 220-284    Link Here 
	return 0;
	return 0;
}
}
/*
 *	This is probably overkill for real world processors but
 *	they are not on hot paths so a little discipline won't do 
 *	any harm.
 */
 
static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
{
	unsigned long flags;
	spin_lock_irqsave(&tty_termios_lock, flags);
	tty->termios->c_line = num;
	spin_unlock_irqrestore(&tty_termios_lock, flags);
}
/*
 *	This guards the refcounted line discipline lists. The lock
 *	must be taken with irqs off because there are hangup path
 *	callers who will do ldisc lookups and cannot sleep.
 */
 
static spinlock_t tty_ldisc_lock = SPIN_LOCK_UNLOCKED;
static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
static struct tty_ldisc tty_ldiscs[NR_LDISCS];	/* line disc dispatch table	*/
int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
{
{
	unsigned long flags;
	int ret = 0;
	
	if (disc < N_TTY || disc >= NR_LDISCS)
	if (disc < N_TTY || disc >= NR_LDISCS)
		return -EINVAL;
		return -EINVAL;
	
	
	spin_lock_irqsave(&tty_ldisc_lock, flags);
	if (new_ldisc) {
	if (new_ldisc) {
		ldiscs[disc] = *new_ldisc;
		tty_ldiscs[disc] = *new_ldisc;
		ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
		tty_ldiscs[disc].num = disc;
		ldiscs[disc].num = disc;
		tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
	} else
		tty_ldiscs[disc].refcount = 0;
		memset(&ldiscs[disc], 0, sizeof(struct tty_ldisc));
	} else {
		if(tty_ldiscs[disc].refcount)
			ret = -EBUSY;
		else
			tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
	}
	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
	
	
	return 0;
	return ret;
}
}
EXPORT_SYMBOL(tty_register_ldisc);
EXPORT_SYMBOL(tty_register_ldisc);
/* Set the discipline of a tty line. */
struct tty_ldisc *tty_ldisc_get(int disc)
{
	unsigned long flags;
	struct tty_ldisc *ld;
	if (disc < N_TTY || disc >= NR_LDISCS)
		return NULL;
	
	spin_lock_irqsave(&tty_ldisc_lock, flags);
	ld = &tty_ldiscs[disc];
	/* Check the entry is defined */
	if(ld->flags & LDISC_FLAG_DEFINED)
	{
		/* If the module is being unloaded we can't use it */
		if (!try_module_get(ld->owner))
		       	ld = NULL;
		else /* lock it */
			ld->refcount++;
	}
	else
		ld = NULL;
	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
	return ld;
}
EXPORT_SYMBOL_GPL(tty_ldisc_get);
void tty_ldisc_put(int disc)
{
	struct tty_ldisc *ld;
	unsigned long flags;
	
	if (disc < N_TTY || disc >= NR_LDISCS)
		BUG();
		
	spin_lock_irqsave(&tty_ldisc_lock, flags);
	ld = &tty_ldiscs[disc];
	if(ld->refcount == 0)
		BUG();
	ld->refcount --;
	module_put(ld->owner);
	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
}
	
EXPORT_SYMBOL_GPL(tty_ldisc_put);
void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
{
	tty->ldisc = *ld;
	tty->ldisc.refcount = 0;
}
/**
 *	tty_ldisc_try		-	internal helper
 *	@tty: the tty
 *
 *	Make a single attempt to grab and bump the refcount on
 *	the tty ldisc. Return 0 on failure or 1 on success. This is
 *	used to implement both the waiting and non waiting versions
 *	of tty_ldisc_ref
 */
static int tty_ldisc_try(struct tty_struct *tty)
{
	unsigned long flags;
	struct tty_ldisc *ld;
	int ret = 0;
	
	spin_lock_irqsave(&tty_ldisc_lock, flags);
	ld = &tty->ldisc;
	if(test_bit(TTY_LDISC, &tty->flags))
	{
		ld->refcount++;
		ret = 1;
	}
	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
	return ret;
}
/**
 *	tty_ldisc_ref_wait	-	wait for the tty ldisc
 *	@tty: tty device
 *
 *	Dereference the line discipline for the terminal and take a 
 *	reference to it. If the line discipline is in flux then 
 *	wait patiently until it changes.
 *
 *	Note: Must not be called from an IRQ/timer context. The caller
 *	must also be careful not to hold other locks that will deadlock
 *	against a discipline change, such as an existing ldisc reference
 *	(which we check for)
 */
 
struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
{
	/* wait_event is a macro */
	wait_event(tty_ldisc_wait, tty_ldisc_try(tty));
	if(tty->ldisc.refcount == 0)
		printk(KERN_ERR "tty_ldisc_ref_wait\n");
	return &tty->ldisc;
}
EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
/**
 *	tty_ldisc_ref		-	get the tty ldisc
 *	@tty: tty device
 *
 *	Dereference the line discipline for the terminal and take a 
 *	reference to it. If the line discipline is in flux then 
 *	return NULL. Can be called from IRQ and timer functions.
 */
 
struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
{
	if(tty_ldisc_try(tty))
		return &tty->ldisc;
	return NULL;
}
EXPORT_SYMBOL_GPL(tty_ldisc_ref);
/**
 *	tty_ldisc_deref		-	free a tty ldisc reference
 *	@ld: reference to free up
 *
 *	Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
 *	be called in IRQ context.
 */
 
void tty_ldisc_deref(struct tty_ldisc *ld)
{
	unsigned long flags;
	if(ld == NULL)
		BUG();
		
	spin_lock_irqsave(&tty_ldisc_lock, flags);
	if(ld->refcount == 0)
		printk(KERN_ERR "tty_ldisc_deref: no references.\n");
	else
		ld->refcount--;
	if(ld->refcount == 0)
		wake_up(&tty_ldisc_wait);
	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
}
EXPORT_SYMBOL_GPL(tty_ldisc_deref);
/**
 *	tty_ldisc_enable	-	allow ldisc use
 *	@tty: terminal to activate ldisc on
 *
 *	Set the TTY_LDISC flag when the line discipline can be called
 *	again. Do neccessary wakeups for existing sleepers.
 *
 *	Note: nobody should set this bit except via this function. Clearing
 *	directly is allowed.
 */
static void tty_ldisc_enable(struct tty_struct *tty)
{
	set_bit(TTY_LDISC, &tty->flags);
	wake_up(&tty_ldisc_wait);
}
	
/**
 *	tty_set_ldisc		-	set line discipline
 *	@tty: the terminal to set
 *	@ldisc: the line discipline
 *
 *	Set the discipline of a tty line. Must be called from a process
 *	context.
 */
 
static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
{
{
	int	retval = 0;
	int	retval = 0;
	struct	tty_ldisc o_ldisc;
	struct	tty_ldisc o_ldisc;
	char buf[64];
	char buf[64];
	int work;
	unsigned long flags;
	struct tty_ldisc *ld;
	if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
	if ((ldisc < N_TTY) || (ldisc >= NR_LDISCS))
		return -EINVAL;
		return -EINVAL;
restart:
	if (tty->ldisc.num == ldisc)
		return 0;	/* We are already in the desired discipline */
	
	ld = tty_ldisc_get(ldisc);
	/* Eduardo Blanco <ejbs@cs.cs.com.uy> */
	/* Eduardo Blanco <ejbs@cs.cs.com.uy> */
	/* Cyrus Durgin <cider@speakeasy.org> */
	/* Cyrus Durgin <cider@speakeasy.org> */
	if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED)) {
	if (ld == NULL) {
		request_module("tty-ldisc-%d", ldisc);
		request_module("tty-ldisc-%d", ldisc);
		ld = tty_ldisc_get(ldisc);
	}
	}
	if (!(ldiscs[ldisc].flags & LDISC_FLAG_DEFINED))
	if (ld == NULL)
		return -EINVAL;
		return -EINVAL;
	if (tty->ldisc.num == ldisc)
		return 0;	/* We are already in the desired discipline */
	if (!try_module_get(ldiscs[ldisc].owner))
	       	return -EINVAL;
	
	o_ldisc = tty->ldisc;
	o_ldisc = tty->ldisc;
	tty_wait_until_sent(tty, 0);
	tty_wait_until_sent(tty, 0);
	/*
	 *	Make sure we don't change while someone holds a
	 *	reference to the line discipline. The TTY_LDISC bit
	 *	prevents anyone taking a reference once it is clear.
	 *	We need the lock to avoid racing reference takers.
	 */
	 
	spin_lock_irqsave(&tty_ldisc_lock, flags);
	if(tty->ldisc.refcount)
	{
		/* Free the new ldisc we grabbed. Must drop the lock
		   first. */
		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
		tty_ldisc_put(ldisc);
		/*
		 * There are several reasons we may be busy, including
		 * random momentary I/O traffic. We must therefore
		 * retry. We could distinguish between blocking ops
		 * and retries if we made tty_ldisc_wait() smarter. That
		 * is up for discussion.
		 */
		if(wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0)
			return -ERESTARTSYS;			
		goto restart;
	}
	clear_bit(TTY_LDISC, &tty->flags);	
	clear_bit(TTY_DONT_FLIP, &tty->flags);
	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
	
	
	/*
	 *	From this point on we know nobody has an ldisc
	 *	usage reference, nor can they obtain one until
	 *	we say so later on.
	 */
	 
	work = cancel_delayed_work(&tty->flip.work);
	/*
	 * Wait for ->hangup_work and ->flip.work handlers to terminate
	 */
	 
	flush_scheduled_work();
	/* Shutdown the current discipline. */
	/* Shutdown the current discipline. */
	if (tty->ldisc.close)
	if (tty->ldisc.close)
		(tty->ldisc.close)(tty);
		(tty->ldisc.close)(tty);
	/* Now set up the new line discipline. */
	/* Now set up the new line discipline. */
	tty->ldisc = ldiscs[ldisc];
	tty_ldisc_assign(tty, ld);
	tty->termios->c_line = ldisc;
	tty_set_termios_ldisc(tty, ldisc);
	if (tty->ldisc.open)
	if (tty->ldisc.open)
		retval = (tty->ldisc.open)(tty);
		retval = (tty->ldisc.open)(tty);
	if (retval < 0) {
	if (retval < 0) {
		tty->ldisc = o_ldisc;
		tty_ldisc_put(ldisc);
		tty->termios->c_line = tty->ldisc.num;
		/* There is an outstanding reference here so this is safe */
		tty_ldisc_assign(tty, tty_ldisc_get(o_ldisc.num));
		tty_set_termios_ldisc(tty, tty->ldisc.num);
		if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) {
		if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) {
			tty->ldisc = ldiscs[N_TTY];
			tty_ldisc_put(o_ldisc.num);
			tty->termios->c_line = N_TTY;
			/* This driver is always present */
			tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
			tty_set_termios_ldisc(tty, N_TTY);
			if (tty->ldisc.open) {
			if (tty->ldisc.open) {
				int r = tty->ldisc.open(tty);
				int r = tty->ldisc.open(tty);
 Lines 288-299    Link Here 
					      tty_name(tty, buf), r);
					      tty_name(tty, buf), r);
			}
			}
		}
		}
	} else {
		module_put(o_ldisc.owner);
	}
	}
	/* At this point we hold a reference to the new ldisc and a
	   a reference to the old ldisc. If we ended up flipping back
	   to the existing ldisc we have two references to it */
	
	
	if (tty->ldisc.num != o_ldisc.num && tty->driver->set_ldisc)
	if (tty->ldisc.num != o_ldisc.num && tty->driver->set_ldisc)
		tty->driver->set_ldisc(tty);
		tty->driver->set_ldisc(tty);
		
	tty_ldisc_put(o_ldisc.num);
	
	/*
	 *	Allow ldisc referencing to occur as soon as the driver
	 *	ldisc callback completes.
	 */
	 
	tty_ldisc_enable(tty);
	
	/* Restart it in case no characters kick it off. Safe if
	   already running */
	if(work)
		schedule_delayed_work(&tty->flip.work, 1);
	return retval;
	return retval;
}
}
 Lines 402-407    Link Here 
static spinlock_t redirect_lock = SPIN_LOCK_UNLOCKED;
static spinlock_t redirect_lock = SPIN_LOCK_UNLOCKED;
static struct file *redirect;
static struct file *redirect;
/**
 *	tty_wakeup	-	request more data
 *	@tty: terminal
 *
 *	Internal and external helper for wakeups of tty. This function
 *	informs the line discipline if present that the driver is ready
 *	to receive more output data.
 */
 
void tty_wakeup(struct tty_struct *tty)
{
	struct tty_ldisc *ld;
	
	if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) {
		ld = tty_ldisc_ref(tty);
		if(ld) {
			if(ld->write_wakeup)
				ld->write_wakeup(tty);
			tty_ldisc_deref(ld);
		}
	}
	wake_up_interruptible(&tty->write_wait);
}
EXPORT_SYMBOL_GPL(tty_wakeup);
/**
 *	tty_ldisc_flush	-	flush line discipline queue
 *	@tty: tty
 *
 *	Flush the line discipline queue (if any) for this tty. If there
 *	is no line discipline active this is a no-op.
 */
 
void tty_ldisc_flush(struct tty_struct *tty)
{
	struct tty_ldisc *ld = tty_ldisc_ref(tty);
	if(ld) {
		if(ld->flush_buffer)
			ld->flush_buffer(tty);
		tty_ldisc_deref(ld);
	}
}
EXPORT_SYMBOL_GPL(tty_ldisc_flush);
	
/*
/*
 * This can be called by the "eventd" kernel thread.  That is process synchronous,
 * This can be called by the "eventd" kernel thread.  That is process synchronous,
 * but doesn't hold any locks, so we need to make sure we have the appropriate
 * but doesn't hold any locks, so we need to make sure we have the appropriate
 Lines 413-418    Link Here 
	struct file * cons_filp = NULL;
	struct file * cons_filp = NULL;
	struct file *filp, *f = NULL;
	struct file *filp, *f = NULL;
	struct task_struct *p;
	struct task_struct *p;
	struct tty_ldisc *ld;
	struct pid *pid;
	struct pid *pid;
	int    closecount = 0, n;
	int    closecount = 0, n;
 Lines 431-436    Link Here 
	
	
	check_tty_count(tty, "do_tty_hangup");
	check_tty_count(tty, "do_tty_hangup");
	file_list_lock();
	file_list_lock();
	/* This breaks for file handles being sent over AF_UNIX sockets ? */
	list_for_each_entry(filp, &tty->tty_files, f_list) {
	list_for_each_entry(filp, &tty->tty_files, f_list) {
		if (filp->f_op->write == redirected_tty_write)
		if (filp->f_op->write == redirected_tty_write)
			cons_filp = filp;
			cons_filp = filp;
 Lines 443-463    Link Here 
	file_list_unlock();
	file_list_unlock();
	
	
	/* FIXME! What are the locking issues here? This may me overdoing things..
	/* FIXME! What are the locking issues here? This may me overdoing things..
	* this question is especially important now that we've removed the irqlock. */
	 * this question is especially important now that we've removed the irqlock. */
	{
		unsigned long flags;
		local_irq_save(flags); // FIXME: is this safe?
	ld = tty_ldisc_ref(tty);
		if (tty->ldisc.flush_buffer)
	if(ld != NULL)	/* We may have no line discipline at this point */
			tty->ldisc.flush_buffer(tty);
	{
		if (ld->flush_buffer)
			ld->flush_buffer(tty);
		if (tty->driver->flush_buffer)
		if (tty->driver->flush_buffer)
			tty->driver->flush_buffer(tty);
			tty->driver->flush_buffer(tty);
		if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
		if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
		    tty->ldisc.write_wakeup)
		    ld->write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
			ld->write_wakeup(tty);
		local_irq_restore(flags); // FIXME: is this safe?
		if (ld->hangup)
			ld->hangup(tty);
	}
	}
	/* FIXME: Once we trust the LDISC code better we can wait here for
	   ldisc completion and fix the driver call race */
	   
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->read_wait);
	wake_up_interruptible(&tty->read_wait);
 Lines 466-487    Link Here 
	 * N_TTY.
	 * N_TTY.
	 */
	 */
	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
	{
		unsigned long flags;
		spin_lock_irqsave(&tty_termios_lock, flags);
		*tty->termios = tty->driver->init_termios;
		*tty->termios = tty->driver->init_termios;
	if (tty->ldisc.num != ldiscs[N_TTY].num) {
		spin_unlock_irqrestore(&tty_termios_lock, flags);
		if (tty->ldisc.close)
			(tty->ldisc.close)(tty);
		module_put(tty->ldisc.owner);
		
		tty->ldisc = ldiscs[N_TTY];
		tty->termios->c_line = N_TTY;
		if (tty->ldisc.open) {
			int i = (tty->ldisc.open)(tty);
			if (i < 0)
				printk(KERN_ERR "do_tty_hangup: N_TTY open: "
						"error %d\n", -i);
		}
	}
	}
	
	
	/* Defer ldisc switch */
	/* tty_deferred_ldisc_switch(N_TTY);
	
	  This should get done automatically when the port closes and
	  tty_release is called */
	
	read_lock(&tasklist_lock);
	read_lock(&tasklist_lock);
	if (tty->session > 0) {
	if (tty->session > 0) {
		struct list_head *l;
		struct list_head *l;
 Lines 514-519    Link Here 
				tty->driver->close(tty, cons_filp);
				tty->driver->close(tty, cons_filp);
	} else if (tty->driver->hangup)
	} else if (tty->driver->hangup)
		(tty->driver->hangup)(tty);
		(tty->driver->hangup)(tty);
		
	/* We don't want to have driver/ldisc interactions beyond
	   the ones we did here. The driver layer expects no
	   calls after ->hangup() from the ldisc side. However we
	   can't yet guarantee all that */
	set_bit(TTY_HUPPED, &tty->flags);
	if (ld) {
		tty_ldisc_enable(tty);
		tty_ldisc_deref(ld);
	}
	unlock_kernel();
	unlock_kernel();
	if (f)
	if (f)
		fput(f);
		fput(f);
 Lines 630-638    Link Here 
	}
	}
	if (tty->driver->start)
	if (tty->driver->start)
		(tty->driver->start)(tty);
		(tty->driver->start)(tty);
	if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
	    tty->ldisc.write_wakeup)
	/* If we have a running line discipline it may need kicking */
		(tty->ldisc.write_wakeup)(tty);
	tty_wakeup(tty);
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
}
}
 Lines 644-649    Link Here 
	int i;
	int i;
	struct tty_struct * tty;
	struct tty_struct * tty;
	struct inode *inode;
	struct inode *inode;
	struct tty_ldisc *ld;
	/* Can't seek (pread) on ttys.  */
	/* Can't seek (pread) on ttys.  */
	if (ppos != &file->f_pos)
	if (ppos != &file->f_pos)
 Lines 656-666    Link Here 
	if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
	if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
		return -EIO;
		return -EIO;
	/* We want to wait for the line discipline to sort out in this
	   situation */
	ld = tty_ldisc_ref_wait(tty);
	lock_kernel();
	lock_kernel();
	if (tty->ldisc.read)
	if (ld->read)
		i = (tty->ldisc.read)(tty,file,buf,count);
		i = (ld->read)(tty,file,buf,count);
	else
	else
		i = -EIO;
		i = -EIO;
	tty_ldisc_deref(ld);
	unlock_kernel();
	unlock_kernel();
	if (i > 0)
	if (i > 0)
		inode->i_atime = CURRENT_TIME;
		inode->i_atime = CURRENT_TIME;
 Lines 722-727    Link Here 
{
{
	struct tty_struct * tty;
	struct tty_struct * tty;
	struct inode *inode = file->f_dentry->d_inode;
	struct inode *inode = file->f_dentry->d_inode;
 	ssize_t ret;
 	struct tty_ldisc *ld;
	/* Can't seek (pwrite) on ttys.  */
	/* Can't seek (pwrite) on ttys.  */
	if (ppos != &file->f_pos)
	if (ppos != &file->f_pos)
 Lines 732-741    Link Here 
		return -EIO;
		return -EIO;
	if (!tty || !tty->driver->write || (test_bit(TTY_IO_ERROR, &tty->flags)))
	if (!tty || !tty->driver->write || (test_bit(TTY_IO_ERROR, &tty->flags)))
		return -EIO;
		return -EIO;
	if (!tty->ldisc.write)
		return -EIO;
 	ld = tty_ldisc_ref_wait(tty);		
	return do_tty_write(tty->ldisc.write, tty, file,
 	if (!ld->write)
 		ret = -EIO;
 	else
 		ret = do_tty_write(ld->write, tty, file,
			    (const unsigned char __user *)buf, count);
			    (const unsigned char __user *)buf, count);
 	tty_ldisc_deref(ld);
 	return ret;
}
}
ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t count,
ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t count,
 Lines 924-929    Link Here 
	 * If we fail here just call release_mem to clean up.  No need
	 * If we fail here just call release_mem to clean up.  No need
	 * to decrement the use counts, as release_mem doesn't care.
	 * to decrement the use counts, as release_mem doesn't care.
	 */
	 */
	if (tty->ldisc.open) {
	if (tty->ldisc.open) {
		retval = (tty->ldisc.open)(tty);
		retval = (tty->ldisc.open)(tty);
		if (retval)
		if (retval)
 Lines 936-942    Link Here 
				(tty->ldisc.close)(tty);
				(tty->ldisc.close)(tty);
			goto release_mem_out;
			goto release_mem_out;
		}
		}
		tty_ldisc_enable(o_tty);
	}
	}
	tty_ldisc_enable(tty);
	goto success;
	goto success;
	/*
	/*
 Lines 965-970    Link Here 
	tty->count++;
	tty->count++;
	tty->driver = driver; /* N.B. why do this every time?? */
	tty->driver = driver; /* N.B. why do this every time?? */
	/* FIXME */
	if(!test_bit(TTY_LDISC, &tty->flags))
		printk(KERN_ERR "init_dev but no ldisc\n");
success:
success:
	*ret_tty = tty;
	*ret_tty = tty;
	
	
 Lines 1067-1072    Link Here 
	int	pty_master, tty_closing, o_tty_closing, do_sleep;
	int	pty_master, tty_closing, o_tty_closing, do_sleep;
	int	idx;
	int	idx;
	char	buf[64];
	char	buf[64];
	unsigned long flags;
	
	
	tty = (struct tty_struct *)filp->private_data;
	tty = (struct tty_struct *)filp->private_data;
	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev"))
	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "release_dev"))
 Lines 1141-1147    Link Here 
		}
		}
	}
	}
#endif
#endif
	if (tty->driver->close)
	if (tty->driver->close)
		tty->driver->close(tty, filp);
		tty->driver->close(tty, filp);
 Lines 1268-1275    Link Here 
	/*
	/*
	 * Prevent flush_to_ldisc() from rescheduling the work for later.  Then
	 * Prevent flush_to_ldisc() from rescheduling the work for later.  Then
	 * kill any delayed work.
 	 * kill any delayed work. As this is the final close it does not
 	 * race with the set_ldisc code path.
	 */
	 */
 	clear_bit(TTY_LDISC, &tty->flags);
	clear_bit(TTY_DONT_FLIP, &tty->flags);
	clear_bit(TTY_DONT_FLIP, &tty->flags);
	cancel_delayed_work(&tty->flip.work);
	cancel_delayed_work(&tty->flip.work);
 Lines 1278-1298    Link Here 
	 */
	 */
	flush_scheduled_work();
	flush_scheduled_work();
 	/*
 	 * Wait for any short term users (we know they are just driver
 	 * side waiters as the file is closing so user count on the file
 	 * side is zero.
 	 */
 	spin_lock_irqsave(&tty_ldisc_lock, flags);
 	while(tty->ldisc.refcount)
 	{
 		spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 		wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0);
 		spin_lock_irqsave(&tty_ldisc_lock, flags);
 	}
 	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
	/*
	/*
	 * Shutdown the current line discipline, and reset it to N_TTY.
	 * Shutdown the current line discipline, and reset it to N_TTY.
	 * N.B. why reset ldisc when we're releasing the memory??
	 * N.B. why reset ldisc when we're releasing the memory??
 	 *
 	 * FIXME: this MUST get fixed for the new reflocking
	 */
	 */
	if (tty->ldisc.close)
	if (tty->ldisc.close)
		(tty->ldisc.close)(tty);
		(tty->ldisc.close)(tty);
	module_put(tty->ldisc.owner);
 	tty_ldisc_put(tty->ldisc.num);
	
	
	tty->ldisc = ldiscs[N_TTY];
 	/*
	tty->termios->c_line = N_TTY;
 	 *	Switch the line discipline back
 	 */
 	tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
 	tty_set_termios_ldisc(tty,N_TTY); 
	if (o_tty) {
	if (o_tty) {
 		/* FIXME: could o_tty be in setldisc here ? */
 		clear_bit(TTY_LDISC, &o_tty->flags);
		if (o_tty->ldisc.close)
		if (o_tty->ldisc.close)
			(o_tty->ldisc.close)(o_tty);
			(o_tty->ldisc.close)(o_tty);
		module_put(o_tty->ldisc.owner);
 		tty_ldisc_put(o_tty->ldisc.num);
		o_tty->ldisc = ldiscs[N_TTY];
 		tty_ldisc_assign(o_tty, tty_ldisc_get(N_TTY));
 		tty_set_termios_ldisc(o_tty,N_TTY); 
	}
	}
	/* 
	/* 
 Lines 1454-1467    Link Here 
static unsigned int tty_poll(struct file * filp, poll_table * wait)
static unsigned int tty_poll(struct file * filp, poll_table * wait)
{
{
	struct tty_struct * tty;
	struct tty_struct * tty;
	struct tty_ldisc *ld;
	int ret = 0;
	tty = (struct tty_struct *)filp->private_data;
	tty = (struct tty_struct *)filp->private_data;
	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll"))
	if (tty_paranoia_check(tty, filp->f_dentry->d_inode, "tty_poll"))
		return 0;
		return 0;
		
	if (tty->ldisc.poll)
	ld = tty_ldisc_ref_wait(tty);
		return (tty->ldisc.poll)(tty, filp, wait);
	if (ld->poll)
	return 0;
		ret = (ld->poll)(tty, filp, wait);
	tty_ldisc_deref(ld);
	return ret;
}
}
static int tty_fasync(int fd, struct file * filp, int on)
static int tty_fasync(int fd, struct file * filp, int on)
 Lines 1493-1504    Link Here 
static int tiocsti(struct tty_struct *tty, char __user *p)
static int tiocsti(struct tty_struct *tty, char __user *p)
{
{
	char ch, mbz = 0;
	char ch, mbz = 0;
	struct tty_ldisc *ld;
	
	if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
	if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
		return -EPERM;
		return -EPERM;
	if (get_user(ch, p))
	if (get_user(ch, p))
		return -EFAULT;
		return -EFAULT;
	tty->ldisc.receive_buf(tty, &ch, &mbz, 1);
	ld = tty_ldisc_ref_wait(tty);
	ld->receive_buf(tty, &ch, &mbz, 1);
	tty_ldisc_deref(ld);
	return 0;
	return 0;
}
}
 Lines 1747-1752    Link Here 
	struct tty_struct *tty, *real_tty;
	struct tty_struct *tty, *real_tty;
	void __user *p = (void __user *)arg;
	void __user *p = (void __user *)arg;
	int retval;
	int retval;
	struct tty_ldisc *ld;
	
	
	tty = (struct tty_struct *)file->private_data;
	tty = (struct tty_struct *)file->private_data;
	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
 Lines 1836-1841    Link Here 
		case TIOCGSID:
		case TIOCGSID:
			return tiocgsid(tty, real_tty, p);
			return tiocgsid(tty, real_tty, p);
		case TIOCGETD:
		case TIOCGETD:
			/* FIXME: check this is ok */
			return put_user(tty->ldisc.num, (int __user *)p);
			return put_user(tty->ldisc.num, (int __user *)p);
		case TIOCSETD:
		case TIOCSETD:
			return tiocsetd(tty, p);
			return tiocsetd(tty, p);
 Lines 1874-1889    Link Here 
			return tty_tiocmset(tty, file, cmd, p);
			return tty_tiocmset(tty, file, cmd, p);
	}
	}
	if (tty->driver->ioctl) {
	if (tty->driver->ioctl) {
		int retval = (tty->driver->ioctl)(tty, file, cmd, arg);
		retval = (tty->driver->ioctl)(tty, file, cmd, arg);
		if (retval != -ENOIOCTLCMD)
		if (retval != -ENOIOCTLCMD)
			return retval;
			return retval;
	}
	}
	if (tty->ldisc.ioctl) {
	ld = tty_ldisc_ref_wait(tty);
		int retval = (tty->ldisc.ioctl)(tty, file, cmd, arg);
	retval = -EINVAL;
		if (retval != -ENOIOCTLCMD)
	if (ld->ioctl) {
			return retval;
		retval = ld->ioctl(tty, file, cmd, arg);
		if (retval == -ENOIOCTLCMD)
			retval = -EINVAL;
	}
	}
	return -EINVAL;
	tty_ldisc_deref(ld);
	return retval;
}
}
 Lines 1918-1931    Link Here 
	int session;
	int session;
	int		i;
	int		i;
	struct file	*filp;
	struct file	*filp;
	struct tty_ldisc *disc;
	
	
	if (!tty)
	if (!tty)
		return;
		return;
	session  = tty->session;
	session  = tty->session;
	if (tty->ldisc.flush_buffer)
	
		tty->ldisc.flush_buffer(tty);
	/* We don't want an ldisc switch during this */
	disc = tty_ldisc_ref(tty);
	if (disc && disc->flush_buffer)
		disc->flush_buffer(tty);
	tty_ldisc_deref(disc);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	
	read_lock(&tasklist_lock);
	read_lock(&tasklist_lock);
	for_each_task_pid(session, PIDTYPE_SID, p, l, pid) {
	for_each_task_pid(session, PIDTYPE_SID, p, l, pid) {
		if (p->signal->tty == tty || session > 0) {
		if (p->signal->tty == tty || session > 0) {
 Lines 1977-2000    Link Here 
/*
/*
 * This routine is called out of the software interrupt to flush data
 * This routine is called out of the software interrupt to flush data
 * from the flip buffer to the line discipline.
 * from the flip buffer to the line discipline. 
 */
 */
 
static void flush_to_ldisc(void *private_)
static void flush_to_ldisc(void *private_)
{
{
	struct tty_struct *tty = (struct tty_struct *) private_;
	struct tty_struct *tty = (struct tty_struct *) private_;
	unsigned char	*cp;
	unsigned char	*cp;
	char		*fp;
	char		*fp;
	int		count;
	int		count;
	unsigned long flags;
	unsigned long 	flags;
	struct tty_ldisc *disc;
	disc = tty_ldisc_ref(tty);
	if (disc == NULL)	/*  !TTY_LDISC */
		return;
	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
	if (test_bit(TTY_DONT_FLIP, &tty->flags)) {
		/*
		/*
		 * Do it after the next timer tick:
		 * Do it after the next timer tick:
		 */
		 */
		schedule_delayed_work(&tty->flip.work, 1);
		schedule_delayed_work(&tty->flip.work, 1);
		return;
		goto out;
	}
	}
	spin_lock_irqsave(&tty->read_lock, flags);
	spin_lock_irqsave(&tty->read_lock, flags);
	if (tty->flip.buf_num) {
	if (tty->flip.buf_num) {
		cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
		cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
 Lines 2013-2019    Link Here 
	tty->flip.count = 0;
	tty->flip.count = 0;
	spin_unlock_irqrestore(&tty->read_lock, flags);
	spin_unlock_irqrestore(&tty->read_lock, flags);
	tty->ldisc.receive_buf(tty, cp, fp, count);
	disc->receive_buf(tty, cp, fp, count);
out:
	tty_ldisc_deref(disc);
}
/*
 *	Call the ldisc flush directly from a driver. This function may
 *	return an error and need retrying by the user.
 */
int tty_push_data(struct tty_struct *tty, unsigned char *cp, unsigned char *fp, int count)
{
	int ret = 0;
	struct tty_ldisc *disc;
	
	disc = tty_ldisc_ref(tty);
	if(test_bit(TTY_DONT_FLIP, &tty->flags))
		ret = -EAGAIN;
	else if(disc == NULL)
		ret = -EIO;
	else
		disc->receive_buf(tty, cp, fp, count);
	tty_ldisc_deref(disc);
	return ret;
	
}
}
/*
/*
 Lines 2035-2043    Link Here 
static int n_baud_table = ARRAY_SIZE(baud_table);
static int n_baud_table = ARRAY_SIZE(baud_table);
/**
 *	tty_termios_baud_rate
 *	@termios: termios structure
 *
 *	Convert termios baud rate data into a speed. This should be called
 *	with the termios lock held if this termios is a terminal termios
 *	structure. May change the termios data.
 */
 
int tty_termios_baud_rate(struct termios *termios)
int tty_termios_baud_rate(struct termios *termios)
{
{
	unsigned int cbaud = termios->c_cflag & CBAUD;
	unsigned int cbaud;
	
	cbaud = termios->c_cflag & CBAUD;
	if (cbaud & CBAUDEX) {
	if (cbaud & CBAUDEX) {
		cbaud &= ~CBAUDEX;
		cbaud &= ~CBAUDEX;
 Lines 2047-2058    Link Here 
		else
		else
			cbaud += 15;
			cbaud += 15;
	}
	}
	return baud_table[cbaud];
	return baud_table[cbaud];
}
}
EXPORT_SYMBOL(tty_termios_baud_rate);
EXPORT_SYMBOL(tty_termios_baud_rate);
/**
 *	tty_get_baud_rate	-	get tty bit rates
 *	@tty: tty to query
 *
 *	Returns the baud rate as an integer for this terminal. The
 *	termios lock must be held by the caller and the terminal bit
 *	flags may be updated.
 */
 
int tty_get_baud_rate(struct tty_struct *tty)
int tty_get_baud_rate(struct tty_struct *tty)
{
{
	int baud = tty_termios_baud_rate(tty->termios);
	int baud = tty_termios_baud_rate(tty->termios);
 Lines 2071-2076    Link Here 
EXPORT_SYMBOL(tty_get_baud_rate);
EXPORT_SYMBOL(tty_get_baud_rate);
/**
 *	tty_flip_buffer_push	-	terminal
 *	@tty: tty to push
 *
 *	Queue a push of the terminal flip buffers to the line discipline. This
 *	function must not be called from IRQ context if tty->low_latency is set.
 *
 *	In the event of the queue being busy for flipping the work will be
 *	held off and retried later.
 */
void tty_flip_buffer_push(struct tty_struct *tty)
void tty_flip_buffer_push(struct tty_struct *tty)
{
{
	if (tty->low_latency)
	if (tty->low_latency)
 Lines 2088-2094    Link Here 
{
{
	memset(tty, 0, sizeof(struct tty_struct));
	memset(tty, 0, sizeof(struct tty_struct));
	tty->magic = TTY_MAGIC;
	tty->magic = TTY_MAGIC;
	tty->ldisc = ldiscs[N_TTY];
	tty_ldisc_assign(tty, tty_ldisc_get(N_TTY));
	tty->pgrp = -1;
	tty->pgrp = -1;
	tty->flip.char_buf_ptr = tty->flip.char_buf;
	tty->flip.char_buf_ptr = tty->flip.char_buf;
	tty->flip.flag_buf_ptr = tty->flip.flag_buf;
	tty->flip.flag_buf_ptr = tty->flip.flag_buf;
(-) linux-2.6.7/drivers/char/tty_ioctl.c (-13 / +54 lines)
 Lines 29-34    Link Here 
#undef	DEBUG
#undef	DEBUG
extern spinlock_t tty_termios_lock;
/*
/*
 * Internal flag options for termios setting behavior
 * Internal flag options for termios setting behavior
 */
 */
 Lines 98-105    Link Here 
{
{
	int canon_change;
	int canon_change;
	struct termios old_termios = *tty->termios;
	struct termios old_termios = *tty->termios;
	struct tty_ldisc *ld;
	unsigned long flags;
	
	/*
	 *	Perform the actual termios internal changes under lock.
	 */
	 
	/* FIXME: we need to decide on some locking/ordering semantics
	   for the set_termios notification eventually */
	spin_lock_irqsave(&tty_termios_lock, flags);
	local_irq_disable(); // FIXME: is this safe?
	*tty->termios = *new_termios;
	*tty->termios = *new_termios;
	unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
	unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
	canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
	canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
 Lines 109-120    Link Here 
		tty->canon_data = 0;
		tty->canon_data = 0;
		tty->erasing = 0;
		tty->erasing = 0;
	}
	}
	local_irq_enable(); // FIXME: is this safe?
	
	
	if (canon_change && !L_ICANON(tty) && tty->read_cnt)
	if (canon_change && !L_ICANON(tty) && tty->read_cnt)
		/* Get characters left over from canonical mode. */
		/* Get characters left over from canonical mode. */
		wake_up_interruptible(&tty->read_wait);
		wake_up_interruptible(&tty->read_wait);
	/* see if packet mode change of state */
	/* See if packet mode change of state. */
	if (tty->link && tty->link->packet) {
	if (tty->link && tty->link->packet) {
		int old_flow = ((old_termios.c_iflag & IXON) &&
		int old_flow = ((old_termios.c_iflag & IXON) &&
 Lines 136-148    Link Here 
	if (tty->driver->set_termios)
	if (tty->driver->set_termios)
		(*tty->driver->set_termios)(tty, &old_termios);
		(*tty->driver->set_termios)(tty, &old_termios);
	if (tty->ldisc.set_termios)
 	ld = tty_ldisc_ref(tty);
		(*tty->ldisc.set_termios)(tty, &old_termios);
 	if (ld != NULL) {
 		if (ld->set_termios)
 			(ld->set_termios)(tty, &old_termios);
 		tty_ldisc_deref(ld);
 	}
 	spin_unlock_irqrestore(&tty_termios_lock, flags);
}
}
static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
{
{
	struct termios tmp_termios;
	struct termios tmp_termios;
 	struct tty_ldisc *ld;
	int retval = tty_check_change(tty);
	int retval = tty_check_change(tty);
	if (retval)
	if (retval)
 Lines 159-167    Link Here 
			return -EFAULT;
			return -EFAULT;
	}
	}
	if ((opt & TERMIOS_FLUSH) && tty->ldisc.flush_buffer)
	ld = tty_ldisc_ref(tty);
		tty->ldisc.flush_buffer(tty);
	
	if (ld != NULL) {
		if ((opt & TERMIOS_FLUSH) && ld->flush_buffer)
			ld->flush_buffer(tty);
		tty_ldisc_deref(ld);
	}
	
	if (opt & TERMIOS_WAIT) {
	if (opt & TERMIOS_WAIT) {
		tty_wait_until_sent(tty, 0);
		tty_wait_until_sent(tty, 0);
		if (signal_pending(current))
		if (signal_pending(current))
 Lines 225-236    Link Here 
static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
static int get_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
{
{
	struct sgttyb tmp;
	struct sgttyb tmp;
	unsigned long flags;
	spin_lock_irqsave(&tty_termios_lock, flags);
	tmp.sg_ispeed = 0;
	tmp.sg_ispeed = 0;
	tmp.sg_ospeed = 0;
	tmp.sg_ospeed = 0;
	tmp.sg_erase = tty->termios->c_cc[VERASE];
	tmp.sg_erase = tty->termios->c_cc[VERASE];
	tmp.sg_kill = tty->termios->c_cc[VKILL];
	tmp.sg_kill = tty->termios->c_cc[VKILL];
	tmp.sg_flags = get_sgflags(tty);
	tmp.sg_flags = get_sgflags(tty);
	spin_unlock_irqrestore(&tty_termios_lock, flags);
	
	return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
	return copy_to_user(sgttyb, &tmp, sizeof(tmp)) ? -EFAULT : 0;
}
}
 Lines 265-280    Link Here 
	int retval;
	int retval;
	struct sgttyb tmp;
	struct sgttyb tmp;
	struct termios termios;
	struct termios termios;
	unsigned long flags;
	retval = tty_check_change(tty);
	retval = tty_check_change(tty);
	if (retval)
	if (retval)
		return retval;
		return retval;
	termios =  *tty->termios;
	
	if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
	if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
		return -EFAULT;
		return -EFAULT;
		
	spin_lock_irqsave(&tty_termios_lock, flags);
	termios =  *tty->termios;
	termios.c_cc[VERASE] = tmp.sg_erase;
	termios.c_cc[VERASE] = tmp.sg_erase;
	termios.c_cc[VKILL] = tmp.sg_kill;
	termios.c_cc[VKILL] = tmp.sg_kill;
	set_sgflags(&termios, tmp.sg_flags);
	set_sgflags(&termios, tmp.sg_flags);
	spin_unlock_irqrestore(&tty_termios_lock, flags);
	change_termios(tty, &termios);
	change_termios(tty, &termios);
	return 0;
	return 0;
}
}
 Lines 365-370    Link Here 
	struct tty_struct * real_tty;
	struct tty_struct * real_tty;
	void __user *p = (void __user *)arg;
	void __user *p = (void __user *)arg;
	int retval;
	int retval;
	struct tty_ldisc *ld;
	unsigned long flags;
	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
	if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
	    tty->driver->subtype == PTY_TYPE_MASTER)
	    tty->driver->subtype == PTY_TYPE_MASTER)
 Lines 443-464    Link Here 
			retval = tty_check_change(tty);
			retval = tty_check_change(tty);
			if (retval)
			if (retval)
				return retval;
				return retval;
				
			ld = tty_ldisc_ref(tty);
			switch (arg) {
			switch (arg) {
			case TCIFLUSH:
			case TCIFLUSH:
				if (tty->ldisc.flush_buffer)
				if (ld->flush_buffer)
					tty->ldisc.flush_buffer(tty);
					ld->flush_buffer(tty);
				break;
				break;
			case TCIOFLUSH:
			case TCIOFLUSH:
				if (tty->ldisc.flush_buffer)
				if (ld->flush_buffer)
					tty->ldisc.flush_buffer(tty);
					ld->flush_buffer(tty);
				/* fall through */
				/* fall through */
			case TCOFLUSH:
			case TCOFLUSH:
				if (tty->driver->flush_buffer)
				if (tty->driver->flush_buffer)
					tty->driver->flush_buffer(tty);
					tty->driver->flush_buffer(tty);
				break;
				break;
			default:
			default:
				tty_ldisc_deref(ld);
				return -EINVAL;
				return -EINVAL;
			}
			}
			tty_ldisc_deref(ld);
			return 0;
			return 0;
		case TIOCOUTQ:
		case TIOCOUTQ:
			return put_user(tty->driver->chars_in_buffer ?
			return put_user(tty->driver->chars_in_buffer ?
 Lines 504-512    Link Here 
		case TIOCSSOFTCAR:
		case TIOCSSOFTCAR:
			if (get_user(arg, (unsigned int __user *) arg))
			if (get_user(arg, (unsigned int __user *) arg))
				return -EFAULT;
				return -EFAULT;
			spin_lock_irqsave(&tty_termios_lock, flags);
			tty->termios->c_cflag =
			tty->termios->c_cflag =
				((tty->termios->c_cflag & ~CLOCAL) |
				((tty->termios->c_cflag & ~CLOCAL) |
				 (arg ? CLOCAL : 0));
				 (arg ? CLOCAL : 0));
			spin_unlock_irqrestore(&tty_termios_lock, flags);
			return 0;
			return 0;
		default:
		default:
			return -ENOIOCTLCMD;
			return -ENOIOCTLCMD;
(-) linux-2.6.7/drivers/char/viocons.c (-4 / +1 lines)
 Lines 422-431    Link Here 
			pi->overflowMessage = 0;
			pi->overflowMessage = 0;
		if (pi->tty) {
		if (pi->tty) {
			if ((pi->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
			tty_wakeup(pi->tty);
			    (pi->tty->ldisc.write_wakeup))
				(pi->tty->ldisc.write_wakeup)(pi->tty);
			wake_up_interruptible(&pi->tty->write_wait);
		}
		}
	}
	}
(-) linux-2.6.7/drivers/char/vme_scc.c (-6 / +2 lines)
 Lines 544-555    Link Here 
		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);   /* disable tx_int on next tx underrun? */
		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);   /* disable tx_int on next tx underrun? */
		port->gs.flags &= ~GS_TX_INTEN;
		port->gs.flags &= ~GS_TX_INTEN;
	}
	}
	if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) {
	if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars)
		if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(port->gs.tty);
				port->gs.tty->ldisc.write_wakeup)
			(port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
		wake_up_interruptible(&port->gs.tty->write_wait);
	}
	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
	return IRQ_HANDLED;
	return IRQ_HANDLED;
(-) linux-2.6.7/drivers/char/vt_ioctl.c (-2 / +1 lines)
 Lines 536-543    Link Here 
		  default:
		  default:
			return -EINVAL;
			return -EINVAL;
		}
		}
		if (tty->ldisc.flush_buffer)
		tty_ldisc_flush(tty);
			tty->ldisc.flush_buffer(tty);
		return 0;
		return 0;
	case KDGKBMODE:
	case KDGKBMODE:
(-) linux-2.6.7/drivers/isdn/capi/capi.c (-39 / +49 lines)
 Lines 436-486    Link Here 
	struct sk_buff *nskb;
	struct sk_buff *nskb;
	int datalen;
	int datalen;
	u16 errcode, datahandle;
	u16 errcode, datahandle;
	struct tty_ldisc *ld;
	datalen = skb->len - CAPIMSG_LEN(skb->data);
	datalen = skb->len - CAPIMSG_LEN(skb->data);
	if (mp->tty) {
	if (mp->tty == NULL)
		if (mp->tty->ldisc.receive_buf == 0) {
	{
			printk(KERN_ERR "capi: ldisc has no receive_buf function\n");
#ifdef _DEBUG_DATAFLOW
			return -1;
		printk(KERN_DEBUG "capi: currently no receiver\n");
		}
#endif
		if (mp->ttyinstop) {
		return -1;
	}
	
	ld = tty_ldisc_ref(mp->tty);
	if (ld == NULL)
		return -1;
	if (ld->receive_buf == NULL) {
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
			printk(KERN_DEBUG "capi: recv tty throttled\n");
		printk(KERN_DEBUG "capi: ldisc has no receive_buf function\n");
#endif
#endif
			return -1;
		goto bad;
		}
	}
		if (mp->tty->ldisc.receive_room &&
	if (mp->ttyinstop) {
		    mp->tty->ldisc.receive_room(mp->tty) < datalen) {
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
			printk(KERN_DEBUG "capi: no room in tty\n");
		printk(KERN_DEBUG "capi: recv tty throttled\n");
#endif
#endif
			return -1;
		goto bad;
		}
	}
		if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) {
	if (ld->receive_room &&
			printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
	    ld->receive_room(mp->tty) < datalen) {
			return -1;
#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
		}
		printk(KERN_DEBUG "capi: no room in tty\n");
		datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4);
		errcode = capi20_put_message(mp->ap, nskb);
		if (errcode != CAPI_NOERROR) {
			printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
					errcode);
			kfree_skb(nskb);
			return -1;
		}
		(void)skb_pull(skb, CAPIMSG_LEN(skb->data));
#ifdef _DEBUG_DATAFLOW
		printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n",
					datahandle, skb->len);
#endif
#endif
		mp->tty->ldisc.receive_buf(mp->tty, skb->data, 0, skb->len);
		goto bad;
		kfree_skb(skb);
	}
		return 0;
	if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) {
		printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
		goto bad;
	}
	datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4);
	errcode = capi20_put_message(mp->ap, nskb);
	if (errcode != CAPI_NOERROR) {
		printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
				errcode);
		kfree_skb(nskb);
		goto bad;
	}
	}
	(void)skb_pull(skb, CAPIMSG_LEN(skb->data));
#ifdef _DEBUG_DATAFLOW
#ifdef _DEBUG_DATAFLOW
	printk(KERN_DEBUG "capi: currently no receiver\n");
	printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ldisc\n",
				datahandle, skb->len);
#endif
#endif
	ld->receive_buf(mp->tty, skb->data, NULL, skb->len);
	kfree_skb(skb);
	tty_ldisc_deref(ld);
	return 0;
bad:
	tty_ldisc_deref(ld);
	return -1;
	return -1;
}
}
 Lines 614-619    Link Here 
	if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
	if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
		
		datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2);
		datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2);
#ifdef _DEBUG_DATAFLOW
#ifdef _DEBUG_DATAFLOW
		printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n",
		printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n",
 Lines 633-642    Link Here 
#endif
#endif
		kfree_skb(skb);
		kfree_skb(skb);
		(void)capiminor_del_ack(mp, datahandle);
		(void)capiminor_del_ack(mp, datahandle);
		if (mp->tty) {
		if (mp->tty)
			if (mp->tty->ldisc.write_wakeup)
			tty_wakeup(tty);
				mp->tty->ldisc.write_wakeup(mp->tty);
		}
		(void)handle_minor_send(mp);
		(void)handle_minor_send(mp);
	} else {
	} else {
(-) linux-2.6.7/drivers/isdn/i4l/isdn_tty.c (-15 / +5 lines)
 Lines 296-305    Link Here 
		info->send_outstanding++;
		info->send_outstanding++;
		info->msr &= ~UART_MSR_CTS;
		info->msr &= ~UART_MSR_CTS;
		info->lsr &= ~UART_LSR_TEMT;
		info->lsr &= ~UART_LSR_TEMT;
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup) (tty);
		wake_up_interruptible(&tty->write_wait);
		return;
		return;
	}
	}
	if (slen < 0) {
	if (slen < 0) {
 Lines 1174-1183    Link Here 
						/* If DLE decoding results in zero-transmit, but
						/* If DLE decoding results in zero-transmit, but
						 * c originally was non-zero, do a wakeup.
						 * c originally was non-zero, do a wakeup.
						 */
						 */
						if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
						tty_wakeup(tty);
						 tty->ldisc.write_wakeup)
							(tty->ldisc.write_wakeup) (tty);
						wake_up_interruptible(&tty->write_wait);
						info->msr |= UART_MSR_CTS;
						info->msr |= UART_MSR_CTS;
						info->lsr |= UART_LSR_TEMT;
						info->lsr |= UART_LSR_TEMT;
					}
					}
 Lines 1290-1298    Link Here 
	isdn_tty_cleanup_xmit(info);
	isdn_tty_cleanup_xmit(info);
	info->xmit_count = 0;
	info->xmit_count = 0;
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup) (tty);
}
}
static void
static void
 Lines 1749-1756    Link Here 
	isdn_tty_shutdown(info);
	isdn_tty_shutdown(info);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
	info->tty = 0;
	info->tty = 0;
	info->ncarrier = 0;
	info->ncarrier = 0;
	tty->closing = 0;
	tty->closing = 0;
 Lines 2681-2688    Link Here 
		if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
		if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
			return;
			return;
		}
		}
		if (info->tty->ldisc.flush_buffer)
		tty_ldisc_flush(tty);
			info->tty->ldisc.flush_buffer(info->tty);
		if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
		if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
		    (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
		    (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
		       (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
		       (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
(-) linux-2.6.7/drivers/macintosh/macserial.c (-12 / +4 lines)
 Lines 717-728    Link Here 
	if (!tty)
	if (!tty)
		return;
		return;
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
	}
}
}
static int startup(struct mac_serial * info)
static int startup(struct mac_serial * info)
 Lines 1570-1579    Link Here 
	spin_lock_irqsave(&info->lock, flags);
	spin_lock_irqsave(&info->lock, flags);
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	spin_unlock_irqrestore(&info->lock, flags);
	spin_unlock_irqrestore(&info->lock, flags);
	wake_up_interruptible(&tty->write_wait);
	tty_wakeup(tty);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
/*
/*
 Lines 2000-2007    Link Here 
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
	tty->closing = 0;
	tty->closing = 0;
	info->event = 0;
	info->event = 0;
	info->tty = 0;
	info->tty = 0;
(-) linux-2.6.7/drivers/net/hamradio/mkiss.c (-2 lines)
 Lines 602-609    Link Here 
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
		tty->ldisc.flush_buffer(tty);
	/* Restore default settings */
	/* Restore default settings */
	ax->dev->type = ARPHRD_AX25;
	ax->dev->type = ARPHRD_AX25;
(-) linux-2.6.7/drivers/net/irda/irtty-sir.c (-7 lines)
 Lines 517-529    Link Here 
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	
	
/* from old irtty - but what is it good for?
 * we _are_ the ldisc and we _don't_ implement flush_buffer!
 *
 *	if (tty->ldisc.flush_buffer)
 *		tty->ldisc.flush_buffer(tty);
 */
	/* apply mtt override */
	/* apply mtt override */
	sir_tty_drv.qos_mtt_bits = qos_mtt_bits;
	sir_tty_drv.qos_mtt_bits = qos_mtt_bits;
(-) linux-2.6.7/drivers/net/ppp_async.c (-3 / +15 lines)
 Lines 121-126    Link Here 
 * frees the memory that ppp_asynctty_receive is using.  The best
 * frees the memory that ppp_asynctty_receive is using.  The best
 * way to fix this is to use a rwlock in the tty struct, but for now
 * way to fix this is to use a rwlock in the tty struct, but for now
 * we use a single global rwlock for all ttys in ppp line discipline.
 * we use a single global rwlock for all ttys in ppp line discipline.
 *
 * FIXME: this is no longer true. The _close path for the ldisc is 
 * now guaranteed to be sane. 
 */
 */
static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
 Lines 143-149    Link Here 
}
}
/*
/*
 * Called when a tty is put into PPP line discipline.
 * Called when a tty is put into PPP line discipline. Called in process
 * context.
 */
 */
static int
static int
ppp_asynctty_open(struct tty_struct *tty)
ppp_asynctty_open(struct tty_struct *tty)
 Lines 254-259    Link Here 
	return -EAGAIN;
	return -EAGAIN;
}
}
/*
 * Called in process context only. May be re-entered by multiple
 * ioctl calling threads.
 */
 
static int
static int
ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
		   unsigned int cmd, unsigned long arg)
		   unsigned int cmd, unsigned long arg)
 Lines 749-755    Link Here 
/*
/*
 * Flush output from our internal buffers.
 * Flush output from our internal buffers.
 * Called for the TCFLSH ioctl.
 * Called for the TCFLSH ioctl. Can be entered in parallel
 * but this is covered by the xmit_lock.
 */
 */
static void
static void
ppp_async_flush_output(struct asyncppp *ap)
ppp_async_flush_output(struct asyncppp *ap)
 Lines 849-855    Link Here 
		skb_trim(skb, 0);
		skb_trim(skb, 0);
}
}
/* called when the tty driver has data for us. */
/* Called when the tty driver has data for us. Runs parallel with the
   other ldisc functions but will not be re-entered */
static void
static void
ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
		char *flags, int count)
		char *flags, int count)
(-) linux-2.6.7/drivers/net/ppp_synctty.c (+2 lines)
 Lines 172-177    Link Here 
 * frees the memory that ppp_synctty_receive is using.  The best
 * frees the memory that ppp_synctty_receive is using.  The best
 * way to fix this is to use a rwlock in the tty struct, but for now
 * way to fix this is to use a rwlock in the tty struct, but for now
 * we use a single global rwlock for all ttys in ppp line discipline.
 * we use a single global rwlock for all ttys in ppp line discipline.
 *
 * FIXME: Fixed in tty_io nowdays.
 */
 */
static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
(-) linux-2.6.7/drivers/net/slip.c (-9 / +15 lines)
 Lines 672-678    Link Here 
 * Handle the 'receiver data ready' interrupt.
 * Handle the 'receiver data ready' interrupt.
 * This function is called by the 'tty_io' module in the kernel when
 * This function is called by the 'tty_io' module in the kernel when
 * a block of SLIP data has been received, which can now be decapsulated
 * a block of SLIP data has been received, which can now be decapsulated
 * and sent on to some IP layer for further processing.
 * and sent on to some IP layer for further processing. This will not
 * be re-entered while running but other ldisc functions may be called
 * in parallel
 */
 */
 
 
static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
 Lines 841-849    Link Here 
 * SLIP line discipline is called for.  Because we are
 * SLIP line discipline is called for.  Because we are
 * sure the tty line exists, we only have to link it to
 * sure the tty line exists, we only have to link it to
 * a free SLIP channel...
 * a free SLIP channel...
 *
 * Called in process context serialized from other ldisc calls.
 */
 */
static int
slip_open(struct tty_struct *tty)
static int slip_open(struct tty_struct *tty)
{
{
	struct slip *sl;
	struct slip *sl;
	int err;
	int err;
 Lines 876-886    Link Here 
	tty->disc_data = sl;
	tty->disc_data = sl;
	sl->line = tty_devnum(tty);
	sl->line = tty_devnum(tty);
	sl->pid = current->pid;
	sl->pid = current->pid;
	
	/* FIXME: already done before we were called - seems this can go */
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
		
		tty->ldisc.flush_buffer(tty);
	if (!test_bit(SLF_INUSE, &sl->flags)) {
	if (!test_bit(SLF_INUSE, &sl->flags)) {
		/* Perform the low-level SLIP initialization. */
		/* Perform the low-level SLIP initialization. */
		if ((err = sl_alloc_bufs(sl, SL_MTU)) != 0)
		if ((err = sl_alloc_bufs(sl, SL_MTU)) != 0)
 Lines 923-928    Link Here 
}
}
/*
/*
  FIXME: 1,2 are fixed 3 was never true anyway.
  
   Let me to blame a bit.
   Let me to blame a bit.
   1. TTY module calls this funstion on soft interrupt.
   1. TTY module calls this funstion on soft interrupt.
   2. TTY module calls this function WITH MASKED INTERRUPTS!
   2. TTY module calls this function WITH MASKED INTERRUPTS!
 Lines 941-949    Link Here 
/*
/*
 * Close down a SLIP channel.
 * Close down a SLIP channel.
 * This means flushing out any pending queues, and then restoring the
 * This means flushing out any pending queues, and then returning. This
 * TTY line discipline to what it was before it got hooked to SLIP
 * call is serialized against other ldisc functions.
 * (which usually is TTY again).
 */
 */
static void
static void
slip_close(struct tty_struct *tty)
slip_close(struct tty_struct *tty)
(-) linux-2.6.7/drivers/net/wan/pc300_tty.c (-19 / +16 lines)
 Lines 634-647    Link Here 
	}
	}
	CPC_TTY_DBG("%s: call wake_up_interruptible\n",cpc_tty->name);
	CPC_TTY_DBG("%s: call wake_up_interruptible\n",cpc_tty->name);
	
	wake_up_interruptible(&tty->write_wait); 
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup){
		CPC_TTY_DBG("%s: call line disc. wake up\n",cpc_tty->name);
		tty->ldisc.write_wakeup(tty); 
	} 
	tty_wakeup(tty);	
	return; 
	return; 
} 
} 
 Lines 692-700    Link Here 
	st_cpc_tty_area *cpc_tty; 
	st_cpc_tty_area *cpc_tty; 
	volatile st_cpc_rx_buf * buf;
	volatile st_cpc_rx_buf * buf;
	char flags=0,flg_rx=1; 
	char flags=0,flg_rx=1; 
	struct tty_ldisc *ld;
	if (cpc_tty_cnt == 0) return;
	if (cpc_tty_cnt == 0) return;
	
	for (i=0; (i < 4) && flg_rx ; i++) {
	for (i=0; (i < 4) && flg_rx ; i++) {
		flg_rx = 0;
		flg_rx = 0;
		port = (int) data;
		port = (int) data;
 Lines 702-712    Link Here 
			cpc_tty = &cpc_tty_area[port];
			cpc_tty = &cpc_tty_area[port];
		
		
			if ((buf=cpc_tty->buf_rx.first) != 0) {
			if ((buf=cpc_tty->buf_rx.first) != 0) {
															
				
				if (cpc_tty->tty && (cpc_tty->tty->ldisc.receive_buf)) { 
				if(cpc_tty->tty)
					CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name);
				{											
					cpc_tty->tty->ldisc.receive_buf(cpc_tty->tty, (char *)(buf->data), 
					ld = tty_ldisc_ref(cpc_tty);
					&flags, buf->size);
					if(ld)
					{
						if (ld->receive_buf)) {
							CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name);
							ld->receive_buf(cpc_tty->tty, (char *)(buf->data), &flags, buf->size);
						}
						tty_ldisc_deref(ld);
					}
				}	
				}	
				cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
				cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
				kfree((unsigned char *)buf);
				kfree((unsigned char *)buf);
 Lines 910-922    Link Here 
		CPC_TTY_DBG("%s: the interface is not opened\n",cpc_tty->name);
		CPC_TTY_DBG("%s: the interface is not opened\n",cpc_tty->name);
		return; 
		return; 
	}
	}
	tty_wakeup(tty);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup){
		CPC_TTY_DBG("%s:call line disc. wakeup\n",cpc_tty->name);
		tty->ldisc.write_wakeup (tty); 
	}
	wake_up_interruptible(&tty->write_wait); 
}
}
/*
/*
(-) linux-2.6.7/drivers/net/wan/sdla_chdlc.c (-12 / +8 lines)
 Lines 3628-3638    Link Here 
	if ((tty=card->tty)==NULL)
	if ((tty=card->tty)==NULL)
		return;
		return;
	
	
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);
	    tty->ldisc.write_wakeup){
		(tty->ldisc.write_wakeup)(tty);
	}
	wake_up_interruptible(&tty->write_wait);
#if defined(SERIAL_HAVE_POLL_WAIT)
#if defined(SERIAL_HAVE_POLL_WAIT)
	wake_up_interruptible(&tty->poll_wait);
	wake_up_interruptible(&tty->poll_wait);
#endif	
#endif	
 Lines 3857-3862    Link Here 
	char fp=0;
	char fp=0;
	struct tty_struct *tty;
	struct tty_struct *tty;
	int i;
	int i;
	struct tty_ldisc *ld;
	
	
	if (!card->tty_open){
	if (!card->tty_open){
		dbg_printk(KERN_INFO "%s: TTY not open during receive\n",
		dbg_printk(KERN_INFO "%s: TTY not open during receive\n",
 Lines 3944-3951    Link Here 
			len -= offset;
			len -= offset;
		}
		}
		sdla_peek(&card->hw, addr, card->tty_rx+offset, len);
		sdla_peek(&card->hw, addr, card->tty_rx+offset, len);
		if (tty->ldisc.receive_buf){
		ld = tty_ldisc_ref(tty);
			tty->ldisc.receive_buf(tty,card->tty_rx,&fp,olen);
		if (ld) {
			if (ld->receive_buf)
				ld->receive_buf(tty,card->tty_rx,&fp,olen);
			tty_ldisc_deref(ld);
		}else{
		}else{
			if (net_ratelimit()){
			if (net_ratelimit()){
				printk(KERN_INFO 
				printk(KERN_INFO 
 Lines 4252-4265    Link Here 
	if (!tty)
	if (!tty)
		return;
		return;
	
	
	wake_up_interruptible(&tty->write_wait);
#if defined(SERIAL_HAVE_POLL_WAIT)
#if defined(SERIAL_HAVE_POLL_WAIT)
	wake_up_interruptible(&tty->poll_wait);
	wake_up_interruptible(&tty->poll_wait);
#endif
#endif
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
	return;
	return;
}
}
(-) linux-2.6.7/drivers/net/wireless/strip.c (-2 lines)
 Lines 2661-2668    Link Here 
	tty->disc_data = strip_info;
	tty->disc_data = strip_info;
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
		tty->ldisc.flush_buffer(tty);
	/*
	/*
	 * Restore default settings
	 * Restore default settings
(-) linux-2.6.7/drivers/s390/char/con3215.c (-8 / +2 lines)
 Lines 366-375    Link Here 
	tty = raw->tty;
	tty = raw->tty;
	if (tty != NULL &&
	if (tty != NULL &&
	    RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
	    RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	    	tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
	}
	}
}
}
 Lines 1055-1064    Link Here 
	raw = (struct raw3215_info *) tty->driver_data;
	raw = (struct raw3215_info *) tty->driver_data;
	raw3215_flush_buffer(raw);
	raw3215_flush_buffer(raw);
	wake_up_interruptible(&tty->write_wait);
	tty_wakeup(tty);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
/*
/*
(-) linux-2.6.7/drivers/s390/char/sclp_tty.c (-4 / +1 lines)
 Lines 277-286    Link Here 
	wake_up(&sclp_tty_waitq);
	wake_up(&sclp_tty_waitq);
	/* check if the tty needs a wake up call */
	/* check if the tty needs a wake up call */
	if (sclp_tty != NULL) {
	if (sclp_tty != NULL) {
		if ((sclp_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    sclp_tty->ldisc.write_wakeup)
			(sclp_tty->ldisc.write_wakeup)(sclp_tty);
		wake_up_interruptible(&sclp_tty->write_wait);
	}
	}
}
}
(-) linux-2.6.7/drivers/s390/char/sclp_vt220.c (-4 / +1 lines)
 Lines 139-148    Link Here 
	wake_up(&sclp_vt220_waitq);
	wake_up(&sclp_vt220_waitq);
	/* Check if the tty needs a wake up call */
	/* Check if the tty needs a wake up call */
	if (sclp_vt220_tty != NULL) {
	if (sclp_vt220_tty != NULL) {
		if ((sclp_vt220_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    (sclp_vt220_tty->ldisc.write_wakeup != NULL))
			(sclp_vt220_tty->ldisc.write_wakeup)(sclp_vt220_tty);
		wake_up_interruptible(&sclp_vt220_tty->write_wait);
	}
	}
}
}
(-) linux-2.6.7/drivers/s390/net/ctctty.c (-9 / +3 lines)
 Lines 300-309    Link Here 
		info->flags &= ~CTC_ASYNC_TX_LINESTAT;
		info->flags &= ~CTC_ASYNC_TX_LINESTAT;
		if (tty) {
		if (tty) {
			if (wake && (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
			tty_wakeup(tty);
			    tty->ldisc.write_wakeup)
				(tty->ldisc.write_wakeup)(tty);
			wake_up_interruptible(&tty->write_wait);
		}
		}
	}
	}
	return (skb_queue_empty(&info->tx_queue) ? 0 : 1);
	return (skb_queue_empty(&info->tx_queue) ? 0 : 1);
 Lines 571-579    Link Here 
	info->lsr |= UART_LSR_TEMT;
	info->lsr |= UART_LSR_TEMT;
	spin_unlock_irqrestore(&ctc_tty_lock, flags);
	spin_unlock_irqrestore(&ctc_tty_lock, flags);
	wake_up_interruptible(&tty->write_wait);
	wake_up_interruptible(&tty->write_wait);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	tty_wakeup(tty);
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup) (tty);
}
}
static void
static void
 Lines 1034-1041    Link Here 
	ctc_tty_shutdown(info);
	ctc_tty_shutdown(info);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
	info->tty = 0;
	info->tty = 0;
	tty->closing = 0;
	tty->closing = 0;
	if (info->blocked_open) {
	if (info->blocked_open) {
(-) linux-2.6.7/drivers/sbus/char/aurora.c (-10 / +3 lines)
 Lines 1531-1538    Link Here 
	aurora_shutdown_port(bp, port);
	aurora_shutdown_port(bp, port);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
	tty->closing = 0;
	tty->closing = 0;
	port->event = 0;
	port->event = 0;
	port->tty = 0;
	port->tty = 0;
 Lines 1743-1752    Link Here 
	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
	restore_flags(flags);
	restore_flags(flags);
	
	
	wake_up_interruptible(&tty->write_wait);
	tty_wakeup(tty);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
#ifdef AURORA_DEBUG
#ifdef AURORA_DEBUG
	printk("aurora_flush_buffer: end\n");
	printk("aurora_flush_buffer: end\n");
#endif
#endif
 Lines 2223-2232    Link Here 
		return;
		return;
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &port->event)) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
	}
	}
#ifdef AURORA_DEBUG
#ifdef AURORA_DEBUG
	printk("do_softint: end\n");
	printk("do_softint: end\n");
(-) linux-2.6.7/drivers/serial/68328serial.c (-10 / +7 lines)
 Lines 435-444    Link Here 
		return;
		return;
#if 0
#if 0
	if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
	if (clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
	}
	}
#endif   
#endif   
}
}
 Lines 858-867    Link Here 
	cli();
	cli();
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	sti();
	sti();
	wake_up_interruptible(&tty->write_wait);
	tty_wakeup(tty);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
/*
/*
 Lines 1185-1195    Link Here 
	shutdown(info);
	shutdown(info);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
		
		tty->ldisc.flush_buffer(tty);
	tty_ldisc_flush(tty);
	tty->closing = 0;
	tty->closing = 0;
	info->event = 0;
	info->event = 0;
	info->tty = 0;
	info->tty = 0;
#warning "This is not and has never been valid so fix it"	
#if 0
	if (tty->ldisc.num != ldiscs[N_TTY].num) {
	if (tty->ldisc.num != ldiscs[N_TTY].num) {
		if (tty->ldisc.close)
		if (tty->ldisc.close)
			(tty->ldisc.close)(tty);
			(tty->ldisc.close)(tty);
 Lines 1198-1203    Link Here 
		if (tty->ldisc.open)
		if (tty->ldisc.open)
			(tty->ldisc.open)(tty);
			(tty->ldisc.open)(tty);
	}
	}
#endif	
	if (info->blocked_open) {
	if (info->blocked_open) {
		if (info->close_delay) {
		if (info->close_delay) {
			current->state = TASK_INTERRUPTIBLE;
			current->state = TASK_INTERRUPTIBLE;
(-) linux-2.6.7/drivers/serial/68360serial.c (-12 / +4 lines)
 Lines 700-711    Link Here 
	if (!tty)
	if (!tty)
		return;
		return;
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
	}
}
}
 Lines 1152-1161    Link Here 
	/* There is nothing to "flush", whatever we gave the CPM
	/* There is nothing to "flush", whatever we gave the CPM
	 * is on its way out.
	 * is on its way out.
	 */
	 */
	wake_up_interruptible(&tty->write_wait);
	tty_wakeup(tty);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
	info->flags &= ~TX_WAKEUP;
	info->flags &= ~TX_WAKEUP;
}
}
 Lines 1716-1723    Link Here 
	shutdown(info);
	shutdown(info);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);		
		tty->ldisc.flush_buffer(tty);
	tty->closing = 0;
	tty->closing = 0;
	info->event = 0;
	info->event = 0;
	info->tty = 0;
	info->tty = 0;
(-) linux-2.6.7/drivers/serial/mcfserial.c (-11 / +6 lines)
 Lines 424-434    Link Here 
	tty = info->tty;
	tty = info->tty;
	if (!tty)
	if (!tty)
		return;
		return;
	tty_wakeup(tty);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
	wake_up_interruptible(&tty->write_wait);
}
}
 Lines 835-844    Link Here 
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	local_irq_restore(flags);
	local_irq_restore(flags);
	wake_up_interruptible(&tty->write_wait);
	tty_wakeup(tty);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
/*
/*
 Lines 1232-1242    Link Here 
	shutdown(info);
	shutdown(info);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
	
	tty->closing = 0;
	tty->closing = 0;
	info->event = 0;
	info->event = 0;
	info->tty = 0;
	info->tty = 0;
#if 0	
	if (tty->ldisc.num != ldiscs[N_TTY].num) {
	if (tty->ldisc.num != ldiscs[N_TTY].num) {
		if (tty->ldisc.close)
		if (tty->ldisc.close)
			(tty->ldisc.close)(tty);
			(tty->ldisc.close)(tty);
 Lines 1245-1250    Link Here 
		if (tty->ldisc.open)
		if (tty->ldisc.open)
			(tty->ldisc.open)(tty);
			(tty->ldisc.open)(tty);
	}
	}
#endif	
	if (info->blocked_open) {
	if (info->blocked_open) {
		if (info->close_delay) {
		if (info->close_delay) {
			current->state = TASK_INTERRUPTIBLE;
			current->state = TASK_INTERRUPTIBLE;
(-) linux-2.6.7/drivers/serial/serial_core.c (-18 / +8 lines)
 Lines 107-121    Link Here 
static void uart_tasklet_action(unsigned long data)
static void uart_tasklet_action(unsigned long data)
{
{
	struct uart_state *state = (struct uart_state *)data;
	struct uart_state *state = (struct uart_state *)data;
	struct tty_struct *tty;
	tty_wakeup(state->info->tty);
	tty = state->info->tty;
	if (tty) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		    tty->ldisc.write_wakeup)
			tty->ldisc.write_wakeup(tty);
		wake_up_interruptible(&tty->write_wait);
	}
}
}
static inline void
static inline void
 Lines 581-590    Link Here 
	spin_lock_irqsave(&port->lock, flags);
	spin_lock_irqsave(&port->lock, flags);
	uart_circ_clear(&state->info->xmit);
	uart_circ_clear(&state->info->xmit);
	spin_unlock_irqrestore(&port->lock, flags);
	spin_unlock_irqrestore(&port->lock, flags);
	wake_up_interruptible(&tty->write_wait);
	tty_wakeup(tty);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
/*
/*
 Lines 1216-1222    Link Here 
{
{
	struct uart_state *state = tty->driver_data;
	struct uart_state *state = tty->driver_data;
	struct uart_port *port;
	struct uart_port *port;
	
	BUG_ON(!kernel_locked());
	BUG_ON(!kernel_locked());
	if (!state || !state->port)
	if (!state || !state->port)
 Lines 1239-1250    Link Here 
		 * one, we've got real problems, since it means the
		 * one, we've got real problems, since it means the
		 * serial port won't be shutdown.
		 * serial port won't be shutdown.
		 */
		 */
		printk("uart_close: bad serial port count; tty->count is 1, "
		printk(KERN_ERR "uart_close: bad serial port count; tty->count is 1, "
		       "state->count is %d\n", state->count);
		       "state->count is %d\n", state->count);
		state->count = 1;
		state->count = 1;
	}
	}
	if (--state->count < 0) {
	if (--state->count < 0) {
		printk("rs_close: bad serial port count for %s: %d\n",
		printk(KERN_ERR "uart_close: bad serial port count for %s: %d\n",
		       tty->name, state->count);
		       tty->name, state->count);
		state->count = 0;
		state->count = 0;
	}
	}
 Lines 1280-1287    Link Here 
	uart_shutdown(state);
	uart_shutdown(state);
	uart_flush_buffer(tty);
	uart_flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
		tty->ldisc.flush_buffer(tty);
	tty_ldisc_flush(tty);	
	
	tty->closing = 0;
	tty->closing = 0;
	state->info->tty = NULL;
	state->info->tty = NULL;
(-) linux-2.6.7/drivers/tc/zs.c (-10 / +3 lines)
 Lines 683-692    Link Here 
		return;
		return;
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
	}
	}
}
}
 Lines 1010-1019    Link Here 
	cli();
	cli();
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
	sti();
	sti();
	wake_up_interruptible(&tty->write_wait);
	tty_wakeup(tty);
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
	    tty->ldisc.write_wakeup)
		(tty->ldisc.write_wakeup)(tty);
}
}
/*
/*
 Lines 1407-1414    Link Here 
	shutdown(info);
	shutdown(info);
	if (tty->driver->flush_buffer)
	if (tty->driver->flush_buffer)
		tty->driver->flush_buffer(tty);
		tty->driver->flush_buffer(tty);
	if (tty->ldisc.flush_buffer)
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer(tty);
	tty->closing = 0;
	tty->closing = 0;
	info->event = 0;
	info->event = 0;
	info->tty = 0;
	info->tty = 0;
(-) linux-2.6.7/drivers/usb/class/bluetty.c (-9 / +2 lines)
 Lines 992-1008    Link Here 
	dbg("%s", __FUNCTION__);
	dbg("%s", __FUNCTION__);
	if (!bluetooth) {
	if (!bluetooth)
		return;
		return;
	}
	tty = bluetooth->tty;
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
		dbg("%s - write wakeup call.", __FUNCTION__);
		(tty->ldisc.write_wakeup)(tty);
	}
	wake_up_interruptible(&tty->write_wait);
	tty_wakeup(&bluetooth->tty);
}
}
(-) linux-2.6.7/drivers/usb/class/cdc-acm.c (-5 / +1 lines)
 Lines 321-335    Link Here 
static void acm_softint(void *private)
static void acm_softint(void *private)
{
{
	struct acm *acm = private;
	struct acm *acm = private;
	struct tty_struct *tty = acm->tty;
	if (!ACM_READY(acm))
	if (!ACM_READY(acm))
		return;
		return;
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
	tty_wakeup(acm->tty);
		(tty->ldisc.write_wakeup)(tty);
	wake_up_interruptible(&tty->write_wait);
}
}
/*
/*
(-) linux-2.6.7/drivers/usb/serial/digi_acceleport.c (-10 / +2 lines)
 Lines 630-643    Link Here 
	wake_up_interruptible( &port->write_wait );
	wake_up_interruptible( &port->write_wait );
	/* wake up line discipline */
	/* wake up line discipline */
	if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
	tty_wakeup(tty);
	&& tty->ldisc.write_wakeup )
		(tty->ldisc.write_wakeup)(tty);
	/* wake up other tty processes */
	wake_up_interruptible( &tty->write_wait );
	/* For 2.2.16 backport -- wake_up_interruptible( &tty->poll_wait ); */
}
}
 Lines 1575-1582    Link Here 
	/* flush driver and line discipline buffers */
	/* flush driver and line discipline buffers */
	if( tty->driver->flush_buffer )
	if( tty->driver->flush_buffer )
		tty->driver->flush_buffer( tty );
		tty->driver->flush_buffer( tty );
	if( tty->ldisc.flush_buffer )
	tty_ldisc_flush(tty);
		tty->ldisc.flush_buffer( tty );
	if (port->serial->dev) {
	if (port->serial->dev) {
		/* wait for transmit idle */
		/* wait for transmit idle */
(-) linux-2.6.7/drivers/usb/serial/empeg.c (-1 / +3 lines)
 Lines 521-527    Link Here 
	 */
	 */
	port->tty->low_latency = 1;
	port->tty->low_latency = 1;
	/* Notify the tty driver that the termios have changed. */
	/* Notify the tty driver that the termios have changed.
	   FIXME: Why - the ldisc will do this anyway and NULL is not
	   a valid previous state */
	port->tty->ldisc.set_termios(port->tty, NULL);
	port->tty->ldisc.set_termios(port->tty, NULL);
	return;
	return;
(-) linux-2.6.7/drivers/usb/serial/io_edgeport.c (-6 / +1 lines)
 Lines 914-925    Link Here 
	if (tty && edge_port->open) {
	if (tty && edge_port->open) {
		/* let the tty driver wakeup if it has a special write_wakeup function */
		/* let the tty driver wakeup if it has a special write_wakeup function */
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
		tty_wakeup(tty);
			(tty->ldisc.write_wakeup)(tty);
		}
		/* tell the tty driver that something has changed */
		wake_up_interruptible(&tty->write_wait);
	}
	}
	// Release the Write URB
	// Release the Write URB
(-) linux-2.6.7/drivers/usb/serial/io_ti.c (-6 / +1 lines)
 Lines 1810-1821    Link Here 
	tty = port->tty;
	tty = port->tty;
	if (tty) {
	if (tty) {
		/* let the tty driver wakeup if it has a special write_wakeup function */
		/* let the tty driver wakeup if it has a special write_wakeup function */
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
		tty_wakeup(tty);
			(tty->ldisc.write_wakeup)(tty);
		}
		/* tell the tty driver that something has changed */
		wake_up_interruptible(&tty->write_wait);
	}
	}
}
}
(-) linux-2.6.7/drivers/usb/serial/ir-usb.c (+4 lines)
 Lines 452-457    Link Here 
			 */
			 */
			tty = port->tty;
			tty = port->tty;
			/*
			 *	FIXME: must not do this in IRQ context,
			 *	must honour TTY_DONT_FLIP
			 */
			tty->ldisc.receive_buf(
			tty->ldisc.receive_buf(
				tty,
				tty,
				data+1,
				data+1,
(-) linux-2.6.7/drivers/usb/serial/keyspan_pda.c (-7 / +1 lines)
 Lines 191-203    Link Here 
	wake_up_interruptible( &port->write_wait );
	wake_up_interruptible( &port->write_wait );
	/* wake up line discipline */
	/* wake up line discipline */
	if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
	tty_wakeup(tty);
	&& tty->ldisc.write_wakeup )
		(tty->ldisc.write_wakeup)(tty);
	/* wake up other tty processes */
	wake_up_interruptible( &tty->write_wait );
	/* For 2.2.16 backport -- wake_up_interruptible( &tty->poll_wait ); */
}
}
static void keyspan_pda_request_unthrottle( struct usb_serial *serial )
static void keyspan_pda_request_unthrottle( struct usb_serial *serial )
(-) linux-2.6.7/drivers/usb/serial/mct_u232.c (-5 / +1 lines)
 Lines 585-595    Link Here 
	if (write_blocking) {
	if (write_blocking) {
		wake_up_interruptible(&port->write_wait);
		wake_up_interruptible(&port->write_wait);
		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
		tty_wakeup(tty);
		    tty->ldisc.write_wakeup)
			(tty->ldisc.write_wakeup)(tty);
		wake_up_interruptible(&tty->write_wait);
		
	} else {
	} else {
		/* from generic_write_bulk_callback */
		/* from generic_write_bulk_callback */
		schedule_work(&port->work);
		schedule_work(&port->work);
(-) linux-2.6.7/drivers/usb/serial/usb-serial.c (-6 / +1 lines)
 Lines 777-788    Link Here 
	if (!tty)
	if (!tty)
		return;
		return;
	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
	tty_wakeup(tty);
		dbg("%s - write wakeup call.", __FUNCTION__);
		(tty->ldisc.write_wakeup)(tty);
	}
	wake_up_interruptible(&tty->write_wait);
}
}
static void destroy_serial(struct kref *kref)
static void destroy_serial(struct kref *kref)
(-) linux-2.6.7/drivers/usb/serial/whiteheat.c (-2 / +1 lines)
 Lines 673-680    Link Here 
	if (port->tty->driver->flush_buffer)
	if (port->tty->driver->flush_buffer)
		port->tty->driver->flush_buffer(port->tty);
		port->tty->driver->flush_buffer(port->tty);
	if (port->tty->ldisc.flush_buffer)
	tty_ldisc_flush(port->tty);
		port->tty->ldisc.flush_buffer(port->tty);
	firm_report_tx_done(port);
	firm_report_tx_done(port);
(-) linux-2.6.7/fs/proc/proc_tty.c (-6 / +6 lines)
 Lines 15-23    Link Here 
#include <linux/seq_file.h>
#include <linux/seq_file.h>
#include <asm/bitops.h>
#include <asm/bitops.h>
extern struct tty_ldisc ldiscs[];
static int tty_ldiscs_read_proc(char *page, char **start, off_t off,
static int tty_ldiscs_read_proc(char *page, char **start, off_t off,
				int count, int *eof, void *data);
				int count, int *eof, void *data);
 Lines 159-170    Link Here 
	int	i;
	int	i;
	int	len = 0;
	int	len = 0;
	off_t	begin = 0;
	off_t	begin = 0;
	struct tty_ldisc *ld;
	
	for (i=0; i < NR_LDISCS; i++) {
	for (i=0; i < NR_LDISCS; i++) {
		if (!(ldiscs[i].flags & LDISC_FLAG_DEFINED))
		ld = tty_ldisc_get(i);
		if (ld == NULL)
			continue;
			continue;
		len += sprintf(page+len, "%-10s %2d\n",
		len += sprintf(page+len, "%-10s %2d\n",
			       ldiscs[i].name ? ldiscs[i].name : "???", i);
			       ld->name ? ld->name : "???", i);
		tty_ldisc_put(i);
		if (len+begin > off+count)
		if (len+begin > off+count)
			break;
			break;
		if (len+begin < off) {
		if (len+begin < off) {
(-) linux-2.6.7/include/linux/tty.h (-14 / +25 lines)
 Lines 306-331    Link Here 
 * tty->write.  Thus, you must use the inline functions set_bit() and
 * tty->write.  Thus, you must use the inline functions set_bit() and
 * clear_bit() to make things atomic.
 * clear_bit() to make things atomic.
 */
 */
#define TTY_THROTTLED 0
#define TTY_THROTTLED 		0	/* Call unthrottle() at threshold min */
#define TTY_IO_ERROR 1
#define TTY_IO_ERROR 		1	/* Canse an I/O error (may be no ldisc too) */
#define TTY_OTHER_CLOSED 2
#define TTY_OTHER_CLOSED 	2	/* Other side (if any) has closed */
#define TTY_EXCLUSIVE 3
#define TTY_EXCLUSIVE 		3	/* Exclusive open mode */
#define TTY_DEBUG 4
#define TTY_DEBUG 		4	/* Debugging */
#define TTY_DO_WRITE_WAKEUP 5
#define TTY_DO_WRITE_WAKEUP 	5	/* Call write_wakeup after queuing new */
#define TTY_PUSH 6
#define TTY_PUSH 		6	/* n_tty private */
#define TTY_CLOSING 7
#define TTY_CLOSING 		7	/* ->close() in progress */
#define TTY_DONT_FLIP 8
#define TTY_DONT_FLIP 		8	/* Defer buffer flip */
#define TTY_HW_COOK_OUT 14
#define TTY_LDISC 		9	/* Line discipline attached */
#define TTY_HW_COOK_IN 15
#define TTY_HW_COOK_OUT 	14	/* Hardware can do output cooking */
#define TTY_PTY_LOCK 16
#define TTY_HW_COOK_IN 		15	/* Hardware can do input cooking */
#define TTY_NO_WRITE_SPLIT 17
#define TTY_PTY_LOCK 		16	/* pty private */
#define TTY_NO_WRITE_SPLIT 	17	/* Preserve write boundaries to driver */
#define TTY_HUPPED 		18	/* Post driver->hangup() */
#define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
#define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))
extern void tty_write_flush(struct tty_struct *);
extern void tty_write_flush(struct tty_struct *);
extern struct termios tty_std_termios;
extern struct termios tty_std_termios;
extern struct tty_ldisc ldiscs[];
extern int fg_console, last_console, want_console;
extern int fg_console, last_console, want_console;
extern int kmsg_redirect;
extern int kmsg_redirect;
 Lines 365-370    Link Here 
struct semaphore;
struct semaphore;
extern struct semaphore tty_sem;
extern struct semaphore tty_sem;
extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
extern void tty_ldisc_deref(struct tty_ldisc *);
extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
extern struct tty_ldisc *tty_ldisc_get(int);
extern void tty_ldisc_put(int);
extern void tty_wakeup(struct tty_struct *tty);
extern void tty_ldisc_flush(struct tty_struct *tty);
/* n_tty.c */
/* n_tty.c */
extern struct tty_ldisc tty_ldisc_N_TTY;
extern struct tty_ldisc tty_ldisc_N_TTY;
(-) linux-2.6.7/include/linux/tty_ldisc.h (+10 lines)
 Lines 95-100    Link Here 
 * 	that line discpline should try to send more characters to the
 * 	that line discpline should try to send more characters to the
 * 	low-level driver for transmission.  If the line discpline does
 * 	low-level driver for transmission.  If the line discpline does
 * 	not have any more data to send, it can just return.
 * 	not have any more data to send, it can just return.
 *
 * int (*hangup)(struct tty_struct *)
 *
 *	Called on a hangup. Tells the discipline that it should
 *	cease I/O to the tty driver. Can sleep. The driver should
 *	seek to perform this action quickly but should wait until
 *	any pending driver I/O is completed.
 */
 */
#include <linux/fs.h>
#include <linux/fs.h>
 Lines 122-127    Link Here 
	void	(*set_termios)(struct tty_struct *tty, struct termios * old);
	void	(*set_termios)(struct tty_struct *tty, struct termios * old);
	unsigned int (*poll)(struct tty_struct *, struct file *,
	unsigned int (*poll)(struct tty_struct *, struct file *,
			     struct poll_table_struct *);
			     struct poll_table_struct *);
	int	(*hangup)(struct tty_struct *tty);
	
	
	/*
	/*
	 * The following routines are called from below.
	 * The following routines are called from below.
 Lines 132-137    Link Here 
	void	(*write_wakeup)(struct tty_struct *);
	void	(*write_wakeup)(struct tty_struct *);
	struct  module *owner;
	struct  module *owner;
	
	int refcount;
};
};
#define TTY_LDISC_MAGIC	0x5403
#define TTY_LDISC_MAGIC	0x5403