2008-10-13 13:36:58 +04:00
/*
* Tty buffer allocation management
*/
# include <linux/types.h>
# include <linux/errno.h>
# include <linux/tty.h>
# include <linux/tty_driver.h>
# include <linux/tty_flip.h>
# include <linux/timer.h>
# include <linux/string.h>
# include <linux/slab.h>
# include <linux/sched.h>
# include <linux/init.h>
# include <linux/wait.h>
# include <linux/bitops.h>
# include <linux/delay.h>
# include <linux/module.h>
2013-02-12 11:00:43 +04:00
# include <linux/ratelimit.h>
2008-10-13 13:36:58 +04:00
2013-06-15 17:36:02 +04:00
# define MIN_TTYB_SIZE 256
# define TTYB_ALIGN_MASK 255
2013-06-15 17:36:03 +04:00
static void tty_buffer_reset ( struct tty_buffer * p , size_t size )
{
p - > used = 0 ;
p - > size = size ;
p - > next = NULL ;
p - > commit = 0 ;
p - > read = 0 ;
}
2008-10-13 13:36:58 +04:00
/**
* tty_buffer_free_all - free buffers used by a tty
* @ tty : tty to free from
*
* Remove all the buffers pending on a tty whether queued with data
* or in the free ring . Must be called when the tty is no longer in use
*
* Locking : none
*/
2012-10-19 00:26:47 +04:00
void tty_buffer_free_all ( struct tty_port * port )
2008-10-13 13:36:58 +04:00
{
2012-10-19 00:26:47 +04:00
struct tty_bufhead * buf = & port - > buf ;
2013-06-15 17:36:06 +04:00
struct tty_buffer * p , * next ;
struct llist_node * llist ;
2012-10-19 00:26:45 +04:00
2013-06-15 17:36:05 +04:00
while ( ( p = buf - > head ) ! = NULL ) {
buf - > head = p - > next ;
2013-06-15 17:36:07 +04:00
if ( p - > size > 0 )
kfree ( p ) ;
2008-10-13 13:36:58 +04:00
}
2013-06-15 17:36:06 +04:00
llist = llist_del_all ( & buf - > free ) ;
llist_for_each_entry_safe ( p , next , llist , free )
2013-06-15 17:36:05 +04:00
kfree ( p ) ;
2013-06-15 17:36:06 +04:00
2013-06-15 17:36:07 +04:00
tty_buffer_reset ( & buf - > sentinel , 0 ) ;
buf - > head = & buf - > sentinel ;
buf - > tail = & buf - > sentinel ;
2012-10-19 00:26:45 +04:00
buf - > memory_used = 0 ;
2008-10-13 13:36:58 +04:00
}
/**
* tty_buffer_alloc - allocate a tty buffer
* @ tty : tty device
* @ size : desired size ( characters )
*
* Allocate a new tty buffer to hold the desired number of characters .
2013-06-15 17:36:04 +04:00
* We round our buffers off in 256 character chunks to get better
* allocation behaviour .
2008-10-13 13:36:58 +04:00
* Return NULL if out of memory or the allocation would exceed the
* per device queue
*/
2012-10-19 00:26:47 +04:00
static struct tty_buffer * tty_buffer_alloc ( struct tty_port * port , size_t size )
2008-10-13 13:36:58 +04:00
{
2013-06-15 17:36:06 +04:00
struct llist_node * free ;
2008-10-13 13:36:58 +04:00
struct tty_buffer * p ;
2013-06-15 17:36:04 +04:00
/* Round the buffer size out */
size = __ALIGN_MASK ( size , TTYB_ALIGN_MASK ) ;
if ( size < = MIN_TTYB_SIZE ) {
2013-06-15 17:36:06 +04:00
free = llist_del_first ( & port - > buf . free ) ;
if ( free ) {
p = llist_entry ( free , struct tty_buffer , free ) ;
2013-06-15 17:36:04 +04:00
goto found ;
}
}
/* Should possibly check if this fails for the largest buffer we
have queued and recycle that ? */
2012-10-19 00:26:47 +04:00
if ( port - > buf . memory_used + size > 65536 )
2008-10-13 13:36:58 +04:00
return NULL ;
p = kmalloc ( sizeof ( struct tty_buffer ) + 2 * size , GFP_ATOMIC ) ;
if ( p = = NULL )
return NULL ;
2013-06-15 17:36:03 +04:00
2013-06-15 17:36:04 +04:00
found :
2013-06-15 17:36:03 +04:00
tty_buffer_reset ( p , size ) ;
2012-10-19 00:26:47 +04:00
port - > buf . memory_used + = size ;
2008-10-13 13:36:58 +04:00
return p ;
}
/**
* tty_buffer_free - free a tty buffer
* @ tty : tty owning the buffer
* @ b : the buffer to free
*
* Free a tty buffer , or add it to the free list according to our
* internal strategy
*/
2012-10-19 00:26:47 +04:00
static void tty_buffer_free ( struct tty_port * port , struct tty_buffer * b )
2008-10-13 13:36:58 +04:00
{
2012-10-19 00:26:47 +04:00
struct tty_bufhead * buf = & port - > buf ;
2012-10-19 00:26:45 +04:00
2008-10-13 13:36:58 +04:00
/* Dumb strategy for now - should keep some stats */
2012-10-19 00:26:45 +04:00
buf - > memory_used - = b - > size ;
WARN_ON ( buf - > memory_used < 0 ) ;
2008-10-13 13:36:58 +04:00
2013-06-15 17:36:02 +04:00
if ( b - > size > MIN_TTYB_SIZE )
2008-10-13 13:36:58 +04:00
kfree ( b ) ;
2013-06-15 17:36:07 +04:00
else if ( b - > size > 0 )
2013-06-15 17:36:06 +04:00
llist_add ( & b - > free , & buf - > free ) ;
2008-10-13 13:36:58 +04:00
}
/**
* __tty_buffer_flush - flush full tty buffers
* @ tty : tty to flush
*
* flush all the buffers containing receive data . Caller must
* hold the buffer lock and must have ensured no parallel flush to
* ldisc is running .
*
* Locking : Caller must hold tty - > buf . lock
*/
2012-10-19 00:26:47 +04:00
static void __tty_buffer_flush ( struct tty_port * port )
2008-10-13 13:36:58 +04:00
{
2012-10-19 00:26:47 +04:00
struct tty_bufhead * buf = & port - > buf ;
2013-06-15 17:36:05 +04:00
struct tty_buffer * next ;
2008-10-13 13:36:58 +04:00
2013-06-15 17:36:05 +04:00
while ( ( next = buf - > head - > next ) ! = NULL ) {
2013-01-19 18:16:20 +04:00
tty_buffer_free ( port , buf - > head ) ;
2013-06-15 17:36:05 +04:00
buf - > head = next ;
2008-10-13 13:36:58 +04:00
}
2013-01-19 18:16:20 +04:00
WARN_ON ( buf - > head ! = buf - > tail ) ;
buf - > head - > read = buf - > head - > commit ;
2008-10-13 13:36:58 +04:00
}
/**
* tty_buffer_flush - flush full tty buffers
* @ tty : tty to flush
*
* flush all the buffers containing receive data . If the buffer is
* being processed by flush_to_ldisc then we defer the processing
* to that function
*
* Locking : none
*/
void tty_buffer_flush ( struct tty_struct * tty )
{
2012-10-19 00:26:44 +04:00
struct tty_port * port = tty - > port ;
2012-10-19 00:26:47 +04:00
struct tty_bufhead * buf = & port - > buf ;
2008-10-13 13:36:58 +04:00
unsigned long flags ;
2012-10-19 00:26:45 +04:00
spin_lock_irqsave ( & buf - > lock , flags ) ;
2008-10-13 13:36:58 +04:00
/* If the data is being pushed to the tty layer then we can't
process it here . Instead set a flag and the flush_to_ldisc
path will process the flush request before it exits */
2012-10-19 00:26:44 +04:00
if ( test_bit ( TTYP_FLUSHING , & port - > iflags ) ) {
set_bit ( TTYP_FLUSHPENDING , & port - > iflags ) ;
2012-10-19 00:26:45 +04:00
spin_unlock_irqrestore ( & buf - > lock , flags ) ;
2008-10-13 13:36:58 +04:00
wait_event ( tty - > read_wait ,
2012-10-19 00:26:44 +04:00
test_bit ( TTYP_FLUSHPENDING , & port - > iflags ) = = 0 ) ;
2008-10-13 13:36:58 +04:00
return ;
} else
2012-10-19 00:26:47 +04:00
__tty_buffer_flush ( port ) ;
2012-10-19 00:26:45 +04:00
spin_unlock_irqrestore ( & buf - > lock , flags ) ;
2008-10-13 13:36:58 +04:00
}
/**
2013-01-19 18:16:20 +04:00
* tty_buffer_request_room - grow tty buffer if needed
2008-10-13 13:36:58 +04:00
* @ tty : tty structure
* @ size : size desired
*
* Make at least size bytes of linear space available for the tty
* buffer . If we fail return the size we managed to find .
2013-01-19 18:16:20 +04:00
*
* Locking : Takes port - > buf . lock
2008-10-13 13:36:58 +04:00
*/
2013-01-19 18:16:20 +04:00
int tty_buffer_request_room ( struct tty_port * port , size_t size )
2008-10-13 13:36:58 +04:00
{
2012-10-19 00:26:47 +04:00
struct tty_bufhead * buf = & port - > buf ;
2008-10-13 13:36:58 +04:00
struct tty_buffer * b , * n ;
int left ;
2013-01-19 18:16:20 +04:00
unsigned long flags ;
spin_lock_irqsave ( & buf - > lock , flags ) ;
2012-10-19 00:26:45 +04:00
b = buf - > tail ;
2013-06-15 17:36:07 +04:00
left = b - > size - b - > used ;
2008-10-13 13:36:58 +04:00
if ( left < size ) {
/* This is the slow path - looking for new buffers to use */
2013-06-15 17:36:04 +04:00
if ( ( n = tty_buffer_alloc ( port , size ) ) ! = NULL ) {
2013-06-15 17:36:07 +04:00
b - > next = n ;
b - > commit = b - > used ;
2012-10-19 00:26:45 +04:00
buf - > tail = n ;
2008-10-13 13:36:58 +04:00
} else
size = left ;
}
2013-01-19 18:16:20 +04:00
spin_unlock_irqrestore ( & buf - > lock , flags ) ;
2008-10-13 13:36:58 +04:00
return size ;
}
EXPORT_SYMBOL_GPL ( tty_buffer_request_room ) ;
/**
2010-02-18 19:43:54 +03:00
* tty_insert_flip_string_fixed_flag - Add characters to the tty buffer
2013-01-03 18:53:02 +04:00
* @ port : tty port
2008-10-13 13:36:58 +04:00
* @ chars : characters
2010-02-18 19:43:54 +03:00
* @ flag : flag value for each character
2008-10-13 13:36:58 +04:00
* @ size : size
*
* Queue a series of bytes to the tty buffering . All the characters
2010-05-07 21:58:32 +04:00
* passed are marked with the supplied flag . Returns the number added .
2008-10-13 13:36:58 +04:00
*
2012-10-19 00:26:47 +04:00
* Locking : Called functions may take port - > buf . lock
2008-10-13 13:36:58 +04:00
*/
2013-01-03 18:53:02 +04:00
int tty_insert_flip_string_fixed_flag ( struct tty_port * port ,
2010-02-18 19:43:54 +03:00
const unsigned char * chars , char flag , size_t size )
2008-10-13 13:36:58 +04:00
{
int copied = 0 ;
do {
2010-03-09 13:54:28 +03:00
int goal = min_t ( size_t , size - copied , TTY_BUFFER_PAGE ) ;
2013-01-19 18:16:20 +04:00
int space = tty_buffer_request_room ( port , goal ) ;
struct tty_buffer * tb = port - > buf . tail ;
2013-06-15 17:36:07 +04:00
if ( unlikely ( space = = 0 ) )
2008-10-13 13:36:58 +04:00
break ;
2013-06-15 17:36:01 +04:00
memcpy ( char_buf_ptr ( tb , tb - > used ) , chars , space ) ;
memset ( flag_buf_ptr ( tb , tb - > used ) , flag , space ) ;
2008-10-13 13:36:58 +04:00
tb - > used + = space ;
copied + = space ;
chars + = space ;
/* There is a small chance that we need to split the data over
several buffers . If this is the case we must loop */
} while ( unlikely ( size > copied ) ) ;
return copied ;
}
2010-02-18 19:43:54 +03:00
EXPORT_SYMBOL ( tty_insert_flip_string_fixed_flag ) ;
2008-10-13 13:36:58 +04:00
/**
* tty_insert_flip_string_flags - Add characters to the tty buffer
2013-01-03 18:53:02 +04:00
* @ port : tty port
2008-10-13 13:36:58 +04:00
* @ chars : characters
* @ flags : flag bytes
* @ size : size
*
* Queue a series of bytes to the tty buffering . For each character
* the flags array indicates the status of the character . Returns the
* number added .
*
2012-10-19 00:26:47 +04:00
* Locking : Called functions may take port - > buf . lock
2008-10-13 13:36:58 +04:00
*/
2013-01-03 18:53:02 +04:00
int tty_insert_flip_string_flags ( struct tty_port * port ,
2008-10-13 13:36:58 +04:00
const unsigned char * chars , const char * flags , size_t size )
{
int copied = 0 ;
do {
2010-03-09 13:54:28 +03:00
int goal = min_t ( size_t , size - copied , TTY_BUFFER_PAGE ) ;
2013-01-19 18:16:20 +04:00
int space = tty_buffer_request_room ( port , goal ) ;
struct tty_buffer * tb = port - > buf . tail ;
2013-06-15 17:36:07 +04:00
if ( unlikely ( space = = 0 ) )
2008-10-13 13:36:58 +04:00
break ;
2013-06-15 17:36:01 +04:00
memcpy ( char_buf_ptr ( tb , tb - > used ) , chars , space ) ;
memcpy ( flag_buf_ptr ( tb , tb - > used ) , flags , space ) ;
2008-10-13 13:36:58 +04:00
tb - > used + = space ;
copied + = space ;
chars + = space ;
flags + = space ;
/* There is a small chance that we need to split the data over
several buffers . If this is the case we must loop */
} while ( unlikely ( size > copied ) ) ;
return copied ;
}
EXPORT_SYMBOL ( tty_insert_flip_string_flags ) ;
/**
* tty_schedule_flip - push characters to ldisc
2013-01-03 18:53:07 +04:00
* @ port : tty port to push from
2008-10-13 13:36:58 +04:00
*
* Takes any pending buffers and transfers their ownership to the
* ldisc side of the queue . It then schedules those characters for
* processing by the line discipline .
2012-09-27 16:02:05 +04:00
* Note that this function can only be used when the low_latency flag
* is unset . Otherwise the workqueue won ' t be flushed .
2008-10-13 13:36:58 +04:00
*
2012-10-19 00:26:47 +04:00
* Locking : Takes port - > buf . lock
2008-10-13 13:36:58 +04:00
*/
2013-01-03 18:53:07 +04:00
void tty_schedule_flip ( struct tty_port * port )
2008-10-13 13:36:58 +04:00
{
2013-01-03 18:53:07 +04:00
struct tty_bufhead * buf = & port - > buf ;
2008-10-13 13:36:58 +04:00
unsigned long flags ;
2013-01-03 18:53:07 +04:00
WARN_ON ( port - > low_latency ) ;
2012-10-19 00:26:45 +04:00
spin_lock_irqsave ( & buf - > lock , flags ) ;
2013-06-15 17:36:07 +04:00
buf - > tail - > commit = buf - > tail - > used ;
2012-10-19 00:26:45 +04:00
spin_unlock_irqrestore ( & buf - > lock , flags ) ;
schedule_work ( & buf - > work ) ;
2008-10-13 13:36:58 +04:00
}
EXPORT_SYMBOL ( tty_schedule_flip ) ;
/**
* tty_prepare_flip_string - make room for characters
2013-01-03 18:53:02 +04:00
* @ port : tty port
2008-10-13 13:36:58 +04:00
* @ chars : return pointer for character write area
* @ size : desired size
*
* Prepare a block of space in the buffer for data . Returns the length
* available and buffer pointer to the space which is now allocated and
* accounted for as ready for normal characters . This is used for drivers
* that need their own block copy routines into the buffer . There is no
* guarantee the buffer is a DMA target !
*
2012-10-19 00:26:47 +04:00
* Locking : May call functions taking port - > buf . lock
2008-10-13 13:36:58 +04:00
*/
2013-01-03 18:53:02 +04:00
int tty_prepare_flip_string ( struct tty_port * port , unsigned char * * chars ,
2012-10-19 00:26:47 +04:00
size_t size )
2008-10-13 13:36:58 +04:00
{
2013-01-19 18:16:20 +04:00
int space = tty_buffer_request_room ( port , size ) ;
2008-10-13 13:36:58 +04:00
if ( likely ( space ) ) {
2013-01-19 18:16:20 +04:00
struct tty_buffer * tb = port - > buf . tail ;
2013-06-15 17:36:01 +04:00
* chars = char_buf_ptr ( tb , tb - > used ) ;
memset ( flag_buf_ptr ( tb , tb - > used ) , TTY_NORMAL , space ) ;
2008-10-13 13:36:58 +04:00
tb - > used + = space ;
}
return space ;
}
EXPORT_SYMBOL_GPL ( tty_prepare_flip_string ) ;
/**
* tty_prepare_flip_string_flags - make room for characters
2013-01-03 18:53:02 +04:00
* @ port : tty port
2008-10-13 13:36:58 +04:00
* @ chars : return pointer for character write area
* @ flags : return pointer for status flag write area
* @ size : desired size
*
* Prepare a block of space in the buffer for data . Returns the length
* available and buffer pointer to the space which is now allocated and
* accounted for as ready for characters . This is used for drivers
* that need their own block copy routines into the buffer . There is no
* guarantee the buffer is a DMA target !
*
2012-10-19 00:26:47 +04:00
* Locking : May call functions taking port - > buf . lock
2008-10-13 13:36:58 +04:00
*/
2013-01-03 18:53:02 +04:00
int tty_prepare_flip_string_flags ( struct tty_port * port ,
2008-10-13 13:36:58 +04:00
unsigned char * * chars , char * * flags , size_t size )
{
2013-01-19 18:16:20 +04:00
int space = tty_buffer_request_room ( port , size ) ;
2008-10-13 13:36:58 +04:00
if ( likely ( space ) ) {
2013-01-19 18:16:20 +04:00
struct tty_buffer * tb = port - > buf . tail ;
2013-06-15 17:36:01 +04:00
* chars = char_buf_ptr ( tb , tb - > used ) ;
* flags = flag_buf_ptr ( tb , tb - > used ) ;
2008-10-13 13:36:58 +04:00
tb - > used + = space ;
}
return space ;
}
EXPORT_SYMBOL_GPL ( tty_prepare_flip_string_flags ) ;
2013-06-15 17:14:14 +04:00
static int
receive_buf ( struct tty_struct * tty , struct tty_buffer * head , int count )
{
struct tty_ldisc * disc = tty - > ldisc ;
2013-06-15 17:36:01 +04:00
unsigned char * p = char_buf_ptr ( head , head - > read ) ;
char * f = flag_buf_ptr ( head , head - > read ) ;
2013-06-15 17:14:14 +04:00
2013-06-15 17:14:15 +04:00
if ( disc - > ops - > receive_buf2 )
count = disc - > ops - > receive_buf2 ( tty , p , f , count ) ;
else {
count = min_t ( int , count , tty - > receive_room ) ;
if ( count )
disc - > ops - > receive_buf ( tty , p , f , count ) ;
}
2013-06-15 17:14:14 +04:00
head - > read + = count ;
return count ;
}
2008-10-13 13:36:58 +04:00
/**
* flush_to_ldisc
* @ work : tty structure passed from work queue .
*
* This routine is called out of the software interrupt to flush data
* from the buffer chain to the line discipline .
*
* Locking : holds tty - > buf . lock to guard buffer list . Drops the lock
* while invoking the line discipline receive_buf method . The
* receive_buf method is single threaded for each tty instance .
*/
static void flush_to_ldisc ( struct work_struct * work )
{
2012-10-19 00:26:47 +04:00
struct tty_port * port = container_of ( work , struct tty_port , buf . work ) ;
struct tty_bufhead * buf = & port - > buf ;
struct tty_struct * tty ;
2008-10-13 13:36:58 +04:00
unsigned long flags ;
struct tty_ldisc * disc ;
2012-10-19 00:26:47 +04:00
tty = port - > itty ;
2013-02-28 01:30:24 +04:00
if ( tty = = NULL )
2012-10-19 00:26:47 +04:00
return ;
2008-10-13 13:36:58 +04:00
disc = tty_ldisc_ref ( tty ) ;
2013-06-15 15:04:48 +04:00
if ( disc = = NULL )
2008-10-13 13:36:58 +04:00
return ;
2012-10-19 00:26:45 +04:00
spin_lock_irqsave ( & buf - > lock , flags ) ;
2009-10-14 19:59:49 +04:00
2012-10-19 00:26:44 +04:00
if ( ! test_and_set_bit ( TTYP_FLUSHING , & port - > iflags ) ) {
2013-06-15 17:36:07 +04:00
while ( 1 ) {
struct tty_buffer * head = buf - > head ;
2009-10-14 19:59:49 +04:00
int count ;
count = head - > commit - head - > read ;
2008-10-13 13:36:58 +04:00
if ( ! count ) {
if ( head - > next = = NULL )
break ;
2012-10-19 00:26:45 +04:00
buf - > head = head - > next ;
2012-10-19 00:26:47 +04:00
tty_buffer_free ( port , head ) ;
2008-10-13 13:36:58 +04:00
continue ;
}
2012-10-19 00:26:45 +04:00
spin_unlock_irqrestore ( & buf - > lock , flags ) ;
2013-06-15 17:14:14 +04:00
count = receive_buf ( tty , head , count ) ;
2012-10-19 00:26:45 +04:00
spin_lock_irqsave ( & buf - > lock , flags ) ;
2013-03-20 21:20:43 +04:00
/* Ldisc or user is trying to flush the buffers.
We may have a deferred request to flush the
input buffer , if so pull the chain under the lock
and empty the queue */
if ( test_bit ( TTYP_FLUSHPENDING , & port - > iflags ) ) {
__tty_buffer_flush ( port ) ;
clear_bit ( TTYP_FLUSHPENDING , & port - > iflags ) ;
wake_up ( & tty - > read_wait ) ;
break ;
2013-06-15 17:14:14 +04:00
} else if ( ! count )
break ;
2008-10-13 13:36:58 +04:00
}
2012-10-19 00:26:44 +04:00
clear_bit ( TTYP_FLUSHING , & port - > iflags ) ;
2008-10-13 13:36:58 +04:00
}
2009-10-14 19:59:49 +04:00
2012-10-19 00:26:45 +04:00
spin_unlock_irqrestore ( & buf - > lock , flags ) ;
2008-10-13 13:36:58 +04:00
tty_ldisc_deref ( disc ) ;
}
2009-07-29 23:15:56 +04:00
/**
* tty_flush_to_ldisc
* @ tty : tty to push
*
* Push the terminal flip buffers to the line discipline .
*
* Must not be called from IRQ context .
*/
void tty_flush_to_ldisc ( struct tty_struct * tty )
{
2013-01-03 18:53:05 +04:00
if ( ! tty - > port - > low_latency )
2012-10-19 00:26:47 +04:00
flush_work ( & tty - > port - > buf . work ) ;
2009-07-29 23:15:56 +04:00
}
2008-10-13 13:36:58 +04:00
/**
* tty_flip_buffer_push - terminal
2013-01-03 18:53:06 +04:00
* @ port : tty port to push
2008-10-13 13:36:58 +04:00
*
* Queue a push of the terminal flip buffers to the line discipline . This
2013-01-03 18:53:05 +04:00
* function must not be called from IRQ context if port - > low_latency is
* set .
2008-10-13 13:36:58 +04:00
*
* In the event of the queue being busy for flipping the work will be
* held off and retried later .
*
* Locking : tty buffer lock . Driver locks in low latency mode .
*/
2013-01-03 18:53:06 +04:00
void tty_flip_buffer_push ( struct tty_port * port )
2008-10-13 13:36:58 +04:00
{
2013-01-03 18:53:06 +04:00
struct tty_bufhead * buf = & port - > buf ;
2008-10-13 13:36:58 +04:00
unsigned long flags ;
2012-10-19 00:26:45 +04:00
spin_lock_irqsave ( & buf - > lock , flags ) ;
2013-06-15 17:36:07 +04:00
buf - > tail - > commit = buf - > tail - > used ;
2012-10-19 00:26:45 +04:00
spin_unlock_irqrestore ( & buf - > lock , flags ) ;
2008-10-13 13:36:58 +04:00
2013-01-03 18:53:06 +04:00
if ( port - > low_latency )
2012-10-19 00:26:45 +04:00
flush_to_ldisc ( & buf - > work ) ;
2008-10-13 13:36:58 +04:00
else
2012-10-19 00:26:45 +04:00
schedule_work ( & buf - > work ) ;
2008-10-13 13:36:58 +04:00
}
EXPORT_SYMBOL ( tty_flip_buffer_push ) ;
/**
* tty_buffer_init - prepare a tty buffer structure
* @ tty : tty to initialise
*
* Set up the initial state of the buffer management for a tty device .
* Must be called before the other tty buffer functions are used .
*
* Locking : none
*/
2012-10-19 00:26:47 +04:00
void tty_buffer_init ( struct tty_port * port )
2008-10-13 13:36:58 +04:00
{
2012-10-19 00:26:47 +04:00
struct tty_bufhead * buf = & port - > buf ;
2012-10-19 00:26:45 +04:00
spin_lock_init ( & buf - > lock ) ;
2013-06-15 17:36:07 +04:00
tty_buffer_reset ( & buf - > sentinel , 0 ) ;
buf - > head = & buf - > sentinel ;
buf - > tail = & buf - > sentinel ;
2013-06-15 17:36:06 +04:00
init_llist_head ( & buf - > free ) ;
2012-10-19 00:26:45 +04:00
buf - > memory_used = 0 ;
INIT_WORK ( & buf - > work , flush_to_ldisc ) ;
2008-10-13 13:36:58 +04:00
}