Source
static void tty_ldisc_lock_pair(struct tty_struct *tty, struct tty_struct *tty2)
// SPDX-License-Identifier: GPL-2.0
/* lockdep nested classes for tty->ldisc_sem */
enum {
LDISC_SEM_NORMAL,
LDISC_SEM_OTHER,
};
/*
* 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 DEFINE_RAW_SPINLOCK(tty_ldiscs_lock);
/* Line disc dispatch table */
static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
/**
* tty_register_ldisc - install a line discipline
* @disc: ldisc number
* @new_ldisc: pointer to the ldisc object
*
* Installs a new line discipline into the kernel. The discipline
* is set up as unreferenced and then made available to the kernel
* from this point onwards.
*
* Locking:
* takes tty_ldiscs_lock to guard against ldisc races
*/
int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
{
unsigned long flags;
int ret = 0;
if (disc < N_TTY || disc >= NR_LDISCS)
return -EINVAL;
raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
tty_ldiscs[disc] = new_ldisc;
new_ldisc->num = disc;
new_ldisc->refcount = 0;
raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
return ret;
}
EXPORT_SYMBOL(tty_register_ldisc);
/**
* tty_unregister_ldisc - unload a line discipline
* @disc: ldisc number
* @new_ldisc: pointer to the ldisc object
*
* Remove a line discipline from the kernel providing it is not
* currently in use.
*
* Locking:
* takes tty_ldiscs_lock to guard against ldisc races
*/
int tty_unregister_ldisc(int disc)
{