android_kernel_lge_bullhead/include/linux/tty_ldisc.h

211 lines
7.0 KiB
C
Raw Permalink Normal View History

#ifndef _LINUX_TTY_LDISC_H
#define _LINUX_TTY_LDISC_H
/*
* This structure defines the interface between the tty line discipline
* implementation and the tty routines. The following routines can be
* defined; unless noted otherwise, they are optional, and can be
* filled in with a null pointer.
*
* int (*open)(struct tty_struct *);
*
* This function is called when the line discipline is associated
* with the tty. The line discipline can use this as an
* opportunity to initialize any state needed by the ldisc routines.
*
* void (*close)(struct tty_struct *);
*
* This function is called when the line discipline is being
* shutdown, either because the tty is being closed or because
* the tty is being changed to use a new line discipline
*
* void (*flush_buffer)(struct tty_struct *tty);
*
* This function instructs the line discipline to clear its
* buffers of any input characters it may have queued to be
* delivered to the user mode process.
*
* ssize_t (*chars_in_buffer)(struct tty_struct *tty);
*
* This function returns the number of input characters the line
* discipline may have queued up to be delivered to the user mode
* process.
*
* ssize_t (*read)(struct tty_struct * tty, struct file * file,
* unsigned char * buf, size_t nr);
*
* This function is called when the user requests to read from
* the tty. The line discipline will return whatever characters
* it has buffered up for the user. If this function is not
* defined, the user will receive an EIO error.
*
* ssize_t (*write)(struct tty_struct * tty, struct file * file,
* const unsigned char * buf, size_t nr);
*
* This function is called when the user requests to write to the
* tty. The line discipline will deliver the characters to the
* low-level tty device for transmission, optionally performing
* some processing on the characters first. If this function is
* not defined, the user will receive an EIO error.
*
* int (*ioctl)(struct tty_struct * tty, struct file * file,
* unsigned int cmd, unsigned long arg);
*
* This function is called when the user requests an ioctl which
* is not handled by the tty layer or the low-level tty driver.
* It is intended for ioctls which affect line discpline
* operation. Note that the search order for ioctls is (1) tty
* layer, (2) tty low-level driver, (3) line discpline. So a
* low-level driver can "grab" an ioctl request before the line
* discpline has a chance to see it.
*
* long (*compat_ioctl)(struct tty_struct * tty, struct file * file,
* unsigned int cmd, unsigned long arg);
*
* Process ioctl calls from 32-bit process on 64-bit system
*
* void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
*
* This function notifies the line discpline that a change has
* been made to the termios structure.
*
* int (*poll)(struct tty_struct * tty, struct file * file,
* poll_table *wait);
*
* This function is called when a user attempts to select/poll on a
* tty device. It is solely the responsibility of the line
* discipline to handle poll requests.
*
Revert "tty: make receive_buf() return the amout of bytes received" This reverts commit b1c43f82c5aa265442f82dba31ce985ebb7aa71c. It was broken in so many ways, and results in random odd pty issues. It re-introduced the buggy schedule_work() in flush_to_ldisc() that can cause endless work-loops (see commit a5660b41af6a: "tty: fix endless work loop when the buffer fills up"). It also used an "unsigned int" return value fo the ->receive_buf() function, but then made multiple functions return a negative error code, and didn't actually check for the error in the caller. And it didn't actually work at all. BenH bisected down odd tty behavior to it: "It looks like the patch is causing some major malfunctions of the X server for me, possibly related to PTYs. For example, cat'ing a large file in a gnome terminal hangs the kernel for -minutes- in a loop of what looks like flush_to_ldisc/workqueue code, (some ftrace data in the quoted bits further down). ... Some more data: It -looks- like what happens is that the flush_to_ldisc work queue entry constantly re-queues itself (because the PTY is full ?) and the workqueue thread will basically loop forver calling it without ever scheduling, thus starving the consumer process that could have emptied the PTY." which is pretty much exactly the problem we fixed in a5660b41af6a. Milton Miller pointed out the 'unsigned int' issue. Reported-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Reported-by: Milton Miller <miltonm@bga.com> Cc: Stefan Bigler <stefan.bigler@keymile.com> Cc: Toby Gray <toby.gray@realvnc.com> Cc: Felipe Balbi <balbi@ti.com> Cc: Greg Kroah-Hartman <gregkh@suse.de> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-06-03 23:33:24 +02:00
* void (*receive_buf)(struct tty_struct *, const unsigned char *cp,
* char *fp, int count);
*
* This function is called by the low-level tty driver to send
* characters received by the hardware to the line discpline for
* processing. <cp> is a pointer to the buffer of input
* character received by the device. <fp> is a pointer to a
* pointer of flag bytes which indicate whether a character was
* received with a parity error, etc.
*
* void (*write_wakeup)(struct tty_struct *);
*
* This function is called by the low-level tty driver to signal
* that line discpline should try to send more characters to the
* low-level driver for transmission. If the line discpline does
* 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.
*
* void (*dcd_change)(struct tty_struct *tty, unsigned int status)
*
* Tells the discipline that the DCD pin has changed its status.
* Used exclusively by the N_PPS (Pulse-Per-Second) line discipline.
*/
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/wait.h>
tty: Add timed, writer-prioritized rw semaphore The semantics of a rw semaphore are almost ideally suited for tty line discipline lifetime management; multiple active threads obtain "references" (read locks) while performing i/o to prevent the loss or change of the current line discipline (write lock). Unfortunately, the existing rw_semaphore is ill-suited in other ways; 1) TIOCSETD ioctl (change line discipline) expects to return an error if the line discipline cannot be exclusively locked within 5 secs. Lock wait timeouts are not supported by rwsem. 2) A tty hangup is expected to halt and scrap pending i/o, so exclusive locking must be prioritized. Writer priority is not supported by rwsem. Add ld_semaphore which implements these requirements in a semantically similar way to rw_semaphore. Writer priority is handled by separate wait lists for readers and writers. Pending write waits are priortized before existing read waits and prevent further read locks. Wait timeouts are trivially added, but obviously change the lock semantics as lock attempts can fail (but only due to timeout). This implementation incorporates the write-lock stealing work of Michel Lespinasse <walken@google.com>. Cc: Michel Lespinasse <walken@google.com> Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Git-commit: 4898e640caf03fdbaf2122d5a33949bf3e4a5b34 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Osvaldo Banuelos <osvaldob@codeaurora.org>
2013-04-16 12:15:50 +02:00
/*
* the semaphore definition
*/
struct ld_semaphore {
long count;
raw_spinlock_t wait_lock;
unsigned int wait_readers;
struct list_head read_wait;
struct list_head write_wait;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
};
extern void __init_ldsem(struct ld_semaphore *sem, const char *name,
struct lock_class_key *key);
#define init_ldsem(sem) \
do { \
static struct lock_class_key __key; \
\
__init_ldsem((sem), #sem, &__key); \
} while (0)
extern int ldsem_down_read(struct ld_semaphore *sem, long timeout);
extern int ldsem_down_read_trylock(struct ld_semaphore *sem);
extern int ldsem_down_write(struct ld_semaphore *sem, long timeout);
extern int ldsem_down_write_trylock(struct ld_semaphore *sem);
extern void ldsem_up_read(struct ld_semaphore *sem);
extern void ldsem_up_write(struct ld_semaphore *sem);
#ifdef CONFIG_DEBUG_LOCK_ALLOC
extern int ldsem_down_read_nested(struct ld_semaphore *sem, int subclass,
long timeout);
extern int ldsem_down_write_nested(struct ld_semaphore *sem, int subclass,
long timeout);
#else
# define ldsem_down_read_nested(sem, subclass, timeout) \
ldsem_down_read(sem, timeout)
# define ldsem_down_write_nested(sem, subclass, timeout) \
ldsem_down_write(sem, timeout)
#endif
struct tty_ldisc_ops {
int magic;
char *name;
int num;
int flags;
/*
* The following routines are called from above.
*/
int (*open)(struct tty_struct *);
void (*close)(struct tty_struct *);
void (*flush_buffer)(struct tty_struct *tty);
ssize_t (*chars_in_buffer)(struct tty_struct *tty);
ssize_t (*read)(struct tty_struct *tty, struct file *file,
unsigned char __user *buf, size_t nr);
ssize_t (*write)(struct tty_struct *tty, struct file *file,
const unsigned char *buf, size_t nr);
int (*ioctl)(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
long (*compat_ioctl)(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg);
void (*set_termios)(struct tty_struct *tty, struct ktermios *old);
unsigned int (*poll)(struct tty_struct *, struct file *,
struct poll_table_struct *);
int (*hangup)(struct tty_struct *tty);
/*
* The following routines are called from below.
*/
Revert "tty: make receive_buf() return the amout of bytes received" This reverts commit b1c43f82c5aa265442f82dba31ce985ebb7aa71c. It was broken in so many ways, and results in random odd pty issues. It re-introduced the buggy schedule_work() in flush_to_ldisc() that can cause endless work-loops (see commit a5660b41af6a: "tty: fix endless work loop when the buffer fills up"). It also used an "unsigned int" return value fo the ->receive_buf() function, but then made multiple functions return a negative error code, and didn't actually check for the error in the caller. And it didn't actually work at all. BenH bisected down odd tty behavior to it: "It looks like the patch is causing some major malfunctions of the X server for me, possibly related to PTYs. For example, cat'ing a large file in a gnome terminal hangs the kernel for -minutes- in a loop of what looks like flush_to_ldisc/workqueue code, (some ftrace data in the quoted bits further down). ... Some more data: It -looks- like what happens is that the flush_to_ldisc work queue entry constantly re-queues itself (because the PTY is full ?) and the workqueue thread will basically loop forver calling it without ever scheduling, thus starving the consumer process that could have emptied the PTY." which is pretty much exactly the problem we fixed in a5660b41af6a. Milton Miller pointed out the 'unsigned int' issue. Reported-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Reported-by: Milton Miller <miltonm@bga.com> Cc: Stefan Bigler <stefan.bigler@keymile.com> Cc: Toby Gray <toby.gray@realvnc.com> Cc: Felipe Balbi <balbi@ti.com> Cc: Greg Kroah-Hartman <gregkh@suse.de> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2011-06-03 23:33:24 +02:00
void (*receive_buf)(struct tty_struct *, const unsigned char *cp,
char *fp, int count);
void (*write_wakeup)(struct tty_struct *);
void (*dcd_change)(struct tty_struct *, unsigned int);
struct module *owner;
int refcount;
};
struct tty_ldisc {
struct tty_ldisc_ops *ops;
struct tty_struct *tty;
};
#define TTY_LDISC_MAGIC 0x5403
#define LDISC_FLAG_DEFINED 0x00000001
#define MODULE_ALIAS_LDISC(ldisc) \
MODULE_ALIAS("tty-ldisc-" __stringify(ldisc))
#endif /* _LINUX_TTY_LDISC_H */