Merge branch 'for-next' of git://github.com/rydberg/linux into next

Pull in changes from Henrik: "a trivial MT documentation fix".
This commit is contained in:
Dmitry Torokhov 2013-06-27 23:00:25 -07:00
commit 31881d74b6
10393 changed files with 590297 additions and 325040 deletions

View file

@ -1798,19 +1798,7 @@ static struct platform_driver amiga_serial_driver = {
},
};
static int __init amiga_serial_init(void)
{
return platform_driver_probe(&amiga_serial_driver, amiga_serial_probe);
}
module_init(amiga_serial_init);
static void __exit amiga_serial_exit(void)
{
platform_driver_unregister(&amiga_serial_driver);
}
module_exit(amiga_serial_exit);
module_platform_driver_probe(amiga_serial_driver, amiga_serial_probe);
#if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE)

View file

@ -1124,14 +1124,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
readl(&info->u.cyz.ch_ctrl->rs_status);
if (dcd & C_RS_DCD)
wake_up_interruptible(&info->port.open_wait);
else {
struct tty_struct *tty;
tty = tty_port_tty_get(&info->port);
if (tty) {
tty_hangup(tty);
tty_kref_put(tty);
}
}
else
tty_port_tty_hangup(&info->port, false);
}
break;
case C_CM_MCTS:

View file

@ -472,13 +472,9 @@ static void ehv_bc_tx_dequeue(struct ehv_bc_data *bc)
static irqreturn_t ehv_bc_tty_tx_isr(int irq, void *data)
{
struct ehv_bc_data *bc = data;
struct tty_struct *ttys = tty_port_tty_get(&bc->port);
ehv_bc_tx_dequeue(bc);
if (ttys) {
tty_wakeup(ttys);
tty_kref_put(ttys);
}
tty_port_tty_wakeup(&bc->port);
return IRQ_HANDLED;
}
@ -863,6 +859,7 @@ error:
*/
static void __exit ehv_bc_exit(void)
{
platform_driver_unregister(&ehv_bc_tty_driver);
tty_unregister_driver(ehv_bc_driver);
put_tty_driver(ehv_bc_driver);
kfree(bcs);

View file

@ -861,7 +861,6 @@ static void hvsi_write_worker(struct work_struct *work)
{
struct hvsi_struct *hp =
container_of(work, struct hvsi_struct, writer.work);
struct tty_struct *tty;
unsigned long flags;
#ifdef DEBUG
static long start_j = 0;
@ -895,11 +894,7 @@ static void hvsi_write_worker(struct work_struct *work)
start_j = 0;
#endif /* DEBUG */
wake_up_all(&hp->emptyq);
tty = tty_port_tty_get(&hp->port);
if (tty) {
tty_wakeup(tty);
tty_kref_put(tty);
}
tty_port_tty_wakeup(&hp->port);
}
out:

View file

@ -1732,8 +1732,7 @@ void ipwireless_hardware_free(struct ipw_hardware *hw)
flush_work(&hw->work_rx);
for (i = 0; i < NL_NUM_OF_ADDRESSES; i++)
if (hw->packet_assembler[i] != NULL)
kfree(hw->packet_assembler[i]);
kfree(hw->packet_assembler[i]);
for (i = 0; i < NL_NUM_OF_PRIORITIES; i++)
list_for_each_entry_safe(tp, tq, &hw->tx_queue[i], queue) {

View file

@ -913,16 +913,12 @@ static void moxa_board_deinit(struct moxa_board_conf *brd)
/* pci hot-un-plug support */
for (a = 0; a < brd->numPorts; a++)
if (brd->ports[a].port.flags & ASYNC_INITIALIZED) {
struct tty_struct *tty = tty_port_tty_get(
&brd->ports[a].port);
if (tty) {
tty_hangup(tty);
tty_kref_put(tty);
}
}
if (brd->ports[a].port.flags & ASYNC_INITIALIZED)
tty_port_tty_hangup(&brd->ports[a].port, false);
for (a = 0; a < MAX_PORTS_PER_BOARD; a++)
tty_port_destroy(&brd->ports[a].port);
while (1) {
opened = 0;
for (a = 0; a < brd->numPorts; a++)
@ -1365,7 +1361,6 @@ static void moxa_hangup(struct tty_struct *tty)
static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
{
struct tty_struct *tty;
unsigned long flags;
dcd = !!dcd;
@ -1373,10 +1368,8 @@ static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
if (dcd != p->DCDState) {
p->DCDState = dcd;
spin_unlock_irqrestore(&p->port.lock, flags);
tty = tty_port_tty_get(&p->port);
if (tty && !C_CLOCAL(tty) && !dcd)
tty_hangup(tty);
tty_kref_put(tty);
if (!dcd)
tty_port_tty_hangup(&p->port, true);
}
else
spin_unlock_irqrestore(&p->port.lock, flags);

View file

@ -1084,6 +1084,10 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
mutex_lock(&port->mutex);
mxser_close_port(port);
mxser_flush_buffer(tty);
if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
if (C_HUPCL(tty))
tty_port_lower_dtr_rts(port);
}
mxser_shutdown_port(port);
clear_bit(ASYNCB_INITIALIZED, &port->flags);
mutex_unlock(&port->mutex);
@ -1614,8 +1618,12 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
if (ip->type == PORT_16550A)
me->fifo[p] = 1;
opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2);
opmode &= OP_MODE_MASK;
if (ip->board->chip_flag == MOXA_MUST_MU860_HWID) {
opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2);
opmode &= OP_MODE_MASK;
} else {
opmode = RS232_MODE;
}
me->iftype[p] = opmode;
mutex_unlock(&port->mutex);
}
@ -1672,6 +1680,9 @@ static int mxser_ioctl(struct tty_struct *tty,
int shiftbit;
unsigned char val, mask;
if (info->board->chip_flag != MOXA_MUST_MU860_HWID)
return -EFAULT;
p = tty->index % 4;
if (cmd == MOXA_SET_OP_MODE) {
if (get_user(opmode, (int __user *) argp))
@ -2643,9 +2654,9 @@ static int mxser_probe(struct pci_dev *pdev,
mxvar_sdriver, brd->idx + i, &pdev->dev);
if (IS_ERR(tty_dev)) {
retval = PTR_ERR(tty_dev);
for (i--; i >= 0; i--)
for (; i > 0; i--)
tty_unregister_device(mxvar_sdriver,
brd->idx + i);
brd->idx + i - 1);
goto err_relbrd;
}
}
@ -2751,9 +2762,9 @@ static int __init mxser_module_init(void)
tty_dev = tty_port_register_device(&brd->ports[i].port,
mxvar_sdriver, brd->idx + i, NULL);
if (IS_ERR(tty_dev)) {
for (i--; i >= 0; i--)
for (; i > 0; i--)
tty_unregister_device(mxvar_sdriver,
brd->idx + i);
brd->idx + i - 1);
for (i = 0; i < brd->info->nports; i++)
tty_port_destroy(&brd->ports[i].port);
free_irq(brd->irq, brd);

View file

@ -1418,11 +1418,7 @@ static void gsm_dlci_close(struct gsm_dlci *dlci)
pr_debug("DLCI %d goes closed.\n", dlci->addr);
dlci->state = DLCI_CLOSED;
if (dlci->addr != 0) {
struct tty_struct *tty = tty_port_tty_get(&dlci->port);
if (tty) {
tty_hangup(tty);
tty_kref_put(tty);
}
tty_port_tty_hangup(&dlci->port, false);
kfifo_reset(dlci->fifo);
} else
dlci->gsm->dead = 1;
@ -2968,6 +2964,10 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp)
if (tty_port_close_start(&dlci->port, tty, filp) == 0)
goto out;
gsm_dlci_begin_close(dlci);
if (test_bit(ASYNCB_INITIALIZED, &dlci->port.flags)) {
if (C_HUPCL(tty))
tty_port_lower_dtr_rts(&dlci->port);
}
tty_port_close_end(&dlci->port, tty);
tty_port_tty_set(&dlci->port, NULL);
out:

View file

@ -153,6 +153,12 @@ static void n_tty_set_room(struct tty_struct *tty)
if (left && !old_left) {
WARN_RATELIMIT(tty->port->itty == NULL,
"scheduling with invalid itty\n");
/* see if ldisc has been killed - if so, this means that
* even though the ldisc has been halted and ->buf.work
* cancelled, ->buf.work is about to be rescheduled
*/
WARN_RATELIMIT(test_bit(TTY_LDISC_HALTED, &tty->flags),
"scheduling buffer work for halted ldisc\n");
schedule_work(&tty->port->buf.work);
}
}
@ -188,35 +194,18 @@ static void put_tty_queue(unsigned char c, struct n_tty_data *ldata)
raw_spin_unlock_irqrestore(&ldata->read_lock, flags);
}
/**
* check_unthrottle - allow new receive data
* @tty; tty device
*
* Check whether to call the driver unthrottle functions
*
* Can sleep, may be called under the atomic_read_lock mutex but
* this is not guaranteed.
*/
static void check_unthrottle(struct tty_struct *tty)
{
if (tty->count)
tty_unthrottle(tty);
}
/**
* reset_buffer_flags - reset buffer state
* @tty: terminal to reset
*
* 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().
* Reset the read buffer counters and clear the flags.
* Called from n_tty_open() and n_tty_flush_buffer().
*
* Locking: tty_read_lock for read fields.
*/
static void reset_buffer_flags(struct tty_struct *tty)
static void reset_buffer_flags(struct n_tty_data *ldata)
{
struct n_tty_data *ldata = tty->disc_data;
unsigned long flags;
raw_spin_lock_irqsave(&ldata->read_lock, flags);
@ -229,29 +218,11 @@ static void reset_buffer_flags(struct tty_struct *tty)
ldata->canon_head = ldata->canon_data = ldata->erasing = 0;
bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
n_tty_set_room(tty);
}
/**
* 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).
*
* Locking: ctrl_lock, read_lock.
*/
static void n_tty_flush_buffer(struct tty_struct *tty)
static void n_tty_packet_mode_flush(struct tty_struct *tty)
{
unsigned long flags;
/* clear everything and unthrottle the driver */
reset_buffer_flags(tty);
if (!tty->link)
return;
spin_lock_irqsave(&tty->ctrl_lock, flags);
if (tty->link->packet) {
@ -261,6 +232,26 @@ static void n_tty_flush_buffer(struct tty_struct *tty)
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
}
/**
* n_tty_flush_buffer - clean input queue
* @tty: terminal device
*
* Flush the input buffer. Called 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).
*
* Locking: ctrl_lock, read_lock.
*/
static void n_tty_flush_buffer(struct tty_struct *tty)
{
reset_buffer_flags(tty->disc_data);
n_tty_set_room(tty);
if (tty->link)
n_tty_packet_mode_flush(tty);
}
/**
* n_tty_chars_in_buffer - report available bytes
* @tty: tty device
@ -1032,23 +1023,19 @@ static void eraser(unsigned char c, struct tty_struct *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.
* Called when a signal is being sent due to terminal input.
* Called from the driver receive_buf path so serialized.
*
* Locking: ctrl_lock, read_lock (both via flush buffer)
* Locking: ctrl_lock
*/
static inline void isig(int sig, struct tty_struct *tty, int flush)
static inline void isig(int sig, struct tty_struct *tty)
{
if (tty->pgrp)
kill_pgrp(tty->pgrp, sig, 1);
if (flush || !L_NOFLSH(tty)) {
n_tty_flush_buffer(tty);
tty_driver_flush_buffer(tty);
struct pid *tty_pgrp = tty_get_pgrp(tty);
if (tty_pgrp) {
kill_pgrp(tty_pgrp, sig, 1);
put_pid(tty_pgrp);
}
}
@ -1069,7 +1056,11 @@ static inline void n_tty_receive_break(struct tty_struct *tty)
if (I_IGNBRK(tty))
return;
if (I_BRKINT(tty)) {
isig(SIGINT, tty, 1);
isig(SIGINT, tty);
if (!L_NOFLSH(tty)) {
n_tty_flush_buffer(tty);
tty_driver_flush_buffer(tty);
}
return;
}
if (I_PARMRK(tty)) {
@ -1236,11 +1227,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
signal = SIGTSTP;
if (c == SUSP_CHAR(tty)) {
send_signal:
/*
* Note that we do not use isig() here because we want
* the order to be:
* 1) flush, 2) echo, 3) signal
*/
if (!L_NOFLSH(tty)) {
n_tty_flush_buffer(tty);
tty_driver_flush_buffer(tty);
@ -1251,8 +1237,7 @@ send_signal:
echo_char(c, tty);
process_echoes(tty);
}
if (tty->pgrp)
kill_pgrp(tty->pgrp, signal, 1);
isig(signal, tty);
return;
}
}
@ -1483,14 +1468,14 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
* mode. We don't want to throttle the driver if we're in
* canonical mode and don't have a newline yet!
*/
if (tty->receive_room < TTY_THRESHOLD_THROTTLE)
tty_throttle(tty);
/* FIXME: there is a tiny race here if the receive room check runs
before the other work executes and empties the buffer (upping
the receiving room and unthrottling. We then throttle and get
stuck. This has been observed and traced down by Vincent Pillet/
We need to address this when we sort out out the rx path locking */
while (1) {
tty_set_flow_change(tty, TTY_THROTTLE_SAFE);
if (tty->receive_room >= TTY_THRESHOLD_THROTTLE)
break;
if (!tty_throttle_safe(tty))
break;
}
__tty_set_flow_change(tty, 0);
}
int is_ignored(int sig)
@ -1588,6 +1573,14 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
ldata->real_raw = 0;
}
n_tty_set_room(tty);
/*
* Fix tty hang when I_IXON(tty) is cleared, but the tty
* been stopped by STOP_CHAR(tty) before it.
*/
if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) {
start_tty(tty);
}
/* The termios change make the tty ready for I/O */
wake_up_interruptible(&tty->write_wait);
wake_up_interruptible(&tty->read_wait);
@ -1607,7 +1600,9 @@ static void n_tty_close(struct tty_struct *tty)
{
struct n_tty_data *ldata = tty->disc_data;
n_tty_flush_buffer(tty);
if (tty->link)
n_tty_packet_mode_flush(tty);
kfree(ldata->read_buf);
kfree(ldata->echo_buf);
kfree(ldata);
@ -1645,12 +1640,14 @@ static int n_tty_open(struct tty_struct *tty)
goto err_free_bufs;
tty->disc_data = ldata;
reset_buffer_flags(tty);
tty_unthrottle(tty);
reset_buffer_flags(tty->disc_data);
ldata->column = 0;
n_tty_set_termios(tty, NULL);
tty->minimum_to_wake = 1;
tty->closing = 0;
/* indicate buffer work may resume */
clear_bit(TTY_LDISC_HALTED, &tty->flags);
n_tty_set_termios(tty, NULL);
tty_unthrottle(tty);
return 0;
err_free_bufs:
@ -1740,10 +1737,9 @@ extern ssize_t redirected_tty_write(struct file *, const char __user *,
* and if appropriate send any needed signals and return a negative
* error code if action should be taken.
*
* FIXME:
* Locking: None - redirected write test is safe, testing
* current->signal should possibly lock current->sighand
* pgrp locking ?
* Locking: redirected write test is safe
* current->signal->tty check is safe
* ctrl_lock to safely reference tty->pgrp
*/
static int job_control(struct tty_struct *tty, struct file *file)
@ -1753,19 +1749,22 @@ static int job_control(struct tty_struct *tty, struct file *file)
/* NOTE: not yet done after every sleep pending a thorough
check of the logic of this change. -- jlc */
/* don't stop on /dev/console */
if (file->f_op->write != redirected_tty_write &&
current->signal->tty == tty) {
if (!tty->pgrp)
printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
else if (task_pgrp(current) != tty->pgrp) {
if (is_ignored(SIGTTIN) ||
is_current_pgrp_orphaned())
return -EIO;
kill_pgrp(task_pgrp(current), SIGTTIN, 1);
set_thread_flag(TIF_SIGPENDING);
return -ERESTARTSYS;
}
if (file->f_op->write == redirected_tty_write ||
current->signal->tty != tty)
return 0;
spin_lock_irq(&tty->ctrl_lock);
if (!tty->pgrp)
printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
else if (task_pgrp(current) != tty->pgrp) {
spin_unlock_irq(&tty->ctrl_lock);
if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned())
return -EIO;
kill_pgrp(task_pgrp(current), SIGTTIN, 1);
set_thread_flag(TIF_SIGPENDING);
return -ERESTARTSYS;
}
spin_unlock_irq(&tty->ctrl_lock);
return 0;
}
@ -1959,10 +1958,17 @@ do_it_again:
* longer than TTY_THRESHOLD_UNTHROTTLE in canonical mode,
* we won't get any more characters.
*/
if (n_tty_chars_in_buffer(tty) <= TTY_THRESHOLD_UNTHROTTLE) {
while (1) {
tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE);
if (n_tty_chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE)
break;
if (!tty->count)
break;
n_tty_set_room(tty);
check_unthrottle(tty);
if (!tty_unthrottle_safe(tty))
break;
}
__tty_set_flow_change(tty, 0);
if (b - buf >= minimum)
break;

View file

@ -791,7 +791,6 @@ static int send_data(enum port_type index, struct nozomi *dc)
const u8 toggle = port->toggle_ul;
void __iomem *addr = port->ul_addr[toggle];
const u32 ul_size = port->ul_size[toggle];
struct tty_struct *tty = tty_port_tty_get(&port->port);
/* Get data from tty and place in buf for now */
size = kfifo_out(&port->fifo_ul, dc->send_buf,
@ -799,7 +798,6 @@ static int send_data(enum port_type index, struct nozomi *dc)
if (size == 0) {
DBG4("No more data to send, disable link:");
tty_kref_put(tty);
return 0;
}
@ -809,10 +807,8 @@ static int send_data(enum port_type index, struct nozomi *dc)
write_mem32(addr, (u32 *) &size, 4);
write_mem32(addr + 4, (u32 *) dc->send_buf, size);
if (tty)
tty_wakeup(tty);
tty_port_tty_wakeup(&port->port);
tty_kref_put(tty);
return 1;
}
@ -1505,12 +1501,9 @@ static void tty_exit(struct nozomi *dc)
DBG1(" ");
for (i = 0; i < MAX_PORT; ++i) {
struct tty_struct *tty = tty_port_tty_get(&dc->port[i].port);
if (tty && list_empty(&tty->hangup_work.entry))
tty_hangup(tty);
tty_kref_put(tty);
}
for (i = 0; i < MAX_PORT; ++i)
tty_port_tty_hangup(&dc->port[i].port, false);
/* Racy below - surely should wait for scheduled work to be done or
complete off a hangup method ? */
while (dc->open_ttys)

View file

@ -405,15 +405,8 @@ err:
return retval;
}
/* this is called once with whichever end is closed last */
static void pty_unix98_shutdown(struct tty_struct *tty)
{
devpts_kill_index(tty->driver_data, tty->index);
}
static void pty_cleanup(struct tty_struct *tty)
{
tty->port->itty = NULL;
tty_port_put(tty->port);
}
@ -627,6 +620,12 @@ static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
{
}
/* this is called once with whichever end is closed last */
static void pty_unix98_shutdown(struct tty_struct *tty)
{
devpts_kill_index(tty->driver_data, tty->index);
}
static const struct tty_operations ptm_unix98_ops = {
.lookup = ptm_unix98_lookup,
.install = pty_unix98_install,
@ -682,6 +681,9 @@ static int ptmx_open(struct inode *inode, struct file *filp)
nonseekable_open(inode, filp);
/* We refuse fsnotify events on ptmx, since it's a shared resource */
filp->f_mode |= FMODE_NONOTIFY;
retval = tty_alloc_file(filp);
if (retval)
return retval;

View file

@ -150,12 +150,14 @@ static Word_t aiop_intr_bits[AIOP_CTL_SIZE] = {
AIOP_INTR_BIT_3
};
#ifdef CONFIG_PCI
static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = {
UPCI_AIOP_INTR_BIT_0,
UPCI_AIOP_INTR_BIT_1,
UPCI_AIOP_INTR_BIT_2,
UPCI_AIOP_INTR_BIT_3
};
#endif
static Byte_t RData[RDATASIZE] = {
0x00, 0x09, 0xf6, 0x82,
@ -227,7 +229,6 @@ static unsigned long nextLineNumber;
static int __init init_ISA(int i);
static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
static void rp_flush_buffer(struct tty_struct *tty);
static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model);
static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
static void rp_start(struct tty_struct *tty);
@ -241,11 +242,6 @@ static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
static void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
ByteIO_t * AiopIOList, int AiopIOListSize,
WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
int PeriodicOnly, int altChanRingIndicator,
int UPCIRingInd);
static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
ByteIO_t * AiopIOList, int AiopIOListSize,
int IRQNum, Byte_t Frequency, int PeriodicOnly);
@ -449,7 +445,7 @@ static void rp_do_transmit(struct r_port *info)
/* Loop sending data to FIFO until done or FIFO full */
while (1) {
if (tty->stopped || tty->hw_stopped)
if (tty->stopped)
break;
c = min(info->xmit_fifo_room, info->xmit_cnt);
c = min(c, XMIT_BUF_SIZE - info->xmit_tail);
@ -521,15 +517,10 @@ static void rp_handle_port(struct r_port *info)
(ChanStatus & CD_ACT) ? "on" : "off");
#endif
if (!(ChanStatus & CD_ACT) && info->cd_status) {
struct tty_struct *tty;
#ifdef ROCKET_DEBUG_HANGUP
printk(KERN_INFO "CD drop, calling hangup.\n");
#endif
tty = tty_port_tty_get(&info->port);
if (tty) {
tty_hangup(tty);
tty_kref_put(tty);
}
tty_port_tty_hangup(&info->port, false);
}
info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0;
wake_up_interruptible(&info->port.open_wait);
@ -1111,15 +1102,12 @@ static void rp_set_termios(struct tty_struct *tty,
/* Handle transition away from B0 status */
if (!(old_termios->c_cflag & CBAUD) && (tty->termios.c_cflag & CBAUD)) {
if (!tty->hw_stopped || !(tty->termios.c_cflag & CRTSCTS))
sSetRTS(cp);
sSetRTS(cp);
sSetDTR(cp);
}
if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios.c_cflag & CRTSCTS))
rp_start(tty);
}
}
static int rp_break(struct tty_struct *tty, int break_state)
@ -1575,10 +1563,10 @@ static int rp_put_char(struct tty_struct *tty, unsigned char ch)
spin_lock_irqsave(&info->slock, flags);
cp = &info->channel;
if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
if (!tty->stopped && info->xmit_fifo_room == 0)
info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
if (tty->stopped || tty->hw_stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
if (tty->stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
info->xmit_buf[info->xmit_head++] = ch;
info->xmit_head &= XMIT_BUF_SIZE - 1;
info->xmit_cnt++;
@ -1619,14 +1607,14 @@ static int rp_write(struct tty_struct *tty,
#endif
cp = &info->channel;
if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room < count)
if (!tty->stopped && info->xmit_fifo_room < count)
info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
/*
* If the write queue for the port is empty, and there is FIFO space, stuff bytes
* into FIFO. Use the write queue for temp storage.
*/
if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
if (!tty->stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
c = min(count, info->xmit_fifo_room);
b = buf;
@ -1674,7 +1662,7 @@ static int rp_write(struct tty_struct *tty,
retval += c;
}
if ((retval > 0) && !tty->stopped && !tty->hw_stopped)
if ((retval > 0) && !tty->stopped)
set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
end:
@ -1783,6 +1771,145 @@ static DEFINE_PCI_DEVICE_TABLE(rocket_pci_ids) = {
};
MODULE_DEVICE_TABLE(pci, rocket_pci_ids);
/* Resets the speaker controller on RocketModem II and III devices */
static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
{
ByteIO_t addr;
/* RocketModem II speaker control is at the 8th port location of offset 0x40 */
if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
addr = CtlP->AiopIO[0] + 0x4F;
sOutB(addr, 0);
}
/* RocketModem III speaker control is at the 1st port location of offset 0x80 */
if ((model == MODEL_UPCI_RM3_8PORT)
|| (model == MODEL_UPCI_RM3_4PORT)) {
addr = CtlP->AiopIO[0] + 0x88;
sOutB(addr, 0);
}
}
/***************************************************************************
Function: sPCIInitController
Purpose: Initialization of controller global registers and controller
structure.
Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
IRQNum,Frequency,PeriodicOnly)
CONTROLLER_T *CtlP; Ptr to controller structure
int CtlNum; Controller number
ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
This list must be in the order the AIOPs will be found on the
controller. Once an AIOP in the list is not found, it is
assumed that there are no more AIOPs on the controller.
int AiopIOListSize; Number of addresses in AiopIOList
int IRQNum; Interrupt Request number. Can be any of the following:
0: Disable global interrupts
3: IRQ 3
4: IRQ 4
5: IRQ 5
9: IRQ 9
10: IRQ 10
11: IRQ 11
12: IRQ 12
15: IRQ 15
Byte_t Frequency: A flag identifying the frequency
of the periodic interrupt, can be any one of the following:
FREQ_DIS - periodic interrupt disabled
FREQ_137HZ - 137 Hertz
FREQ_69HZ - 69 Hertz
FREQ_34HZ - 34 Hertz
FREQ_17HZ - 17 Hertz
FREQ_9HZ - 9 Hertz
FREQ_4HZ - 4 Hertz
If IRQNum is set to 0 the Frequency parameter is
overidden, it is forced to a value of FREQ_DIS.
int PeriodicOnly: 1 if all interrupts except the periodic
interrupt are to be blocked.
0 is both the periodic interrupt and
other channel interrupts are allowed.
If IRQNum is set to 0 the PeriodicOnly parameter is
overidden, it is forced to a value of 0.
Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
initialization failed.
Comments:
If periodic interrupts are to be disabled but AIOP interrupts
are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
If interrupts are to be completely disabled set IRQNum to 0.
Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
invalid combination.
This function performs initialization of global interrupt modes,
but it does not actually enable global interrupts. To enable
and disable global interrupts use functions sEnGlobalInt() and
sDisGlobalInt(). Enabling of global interrupts is normally not
done until all other initializations are complete.
Even if interrupts are globally enabled, they must also be
individually enabled for each channel that is to generate
interrupts.
Warnings: No range checking on any of the parameters is done.
No context switches are allowed while executing this function.
After this function all AIOPs on the controller are disabled,
they can be enabled with sEnAiop().
*/
static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
ByteIO_t * AiopIOList, int AiopIOListSize,
WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
int PeriodicOnly, int altChanRingIndicator,
int UPCIRingInd)
{
int i;
ByteIO_t io;
CtlP->AltChanRingIndicator = altChanRingIndicator;
CtlP->UPCIRingInd = UPCIRingInd;
CtlP->CtlNum = CtlNum;
CtlP->CtlID = CTLID_0001; /* controller release 1 */
CtlP->BusType = isPCI; /* controller release 1 */
if (ConfigIO) {
CtlP->isUPCI = 1;
CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
CtlP->AiopIntrBits = upci_aiop_intr_bits;
} else {
CtlP->isUPCI = 0;
CtlP->PCIIO =
(WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
CtlP->AiopIntrBits = aiop_intr_bits;
}
sPCIControllerEOI(CtlP); /* clear EOI if warm init */
/* Init AIOPs */
CtlP->NumAiop = 0;
for (i = 0; i < AiopIOListSize; i++) {
io = AiopIOList[i];
CtlP->AiopIO[i] = (WordIO_t) io;
CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
break; /* done looking for AIOPs */
CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
sOutB(io + _INDX_DATA, sClockPrescale);
CtlP->NumAiop++; /* bump count of AIOPs */
}
if (CtlP->NumAiop == 0)
return (-1);
else
return (CtlP->NumAiop);
}
/*
* Called when a PCI card is found. Retrieves and stores model information,
* init's aiopic and serial port hardware.
@ -2527,126 +2654,6 @@ static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
return (CtlP->NumAiop);
}
/***************************************************************************
Function: sPCIInitController
Purpose: Initialization of controller global registers and controller
structure.
Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
IRQNum,Frequency,PeriodicOnly)
CONTROLLER_T *CtlP; Ptr to controller structure
int CtlNum; Controller number
ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
This list must be in the order the AIOPs will be found on the
controller. Once an AIOP in the list is not found, it is
assumed that there are no more AIOPs on the controller.
int AiopIOListSize; Number of addresses in AiopIOList
int IRQNum; Interrupt Request number. Can be any of the following:
0: Disable global interrupts
3: IRQ 3
4: IRQ 4
5: IRQ 5
9: IRQ 9
10: IRQ 10
11: IRQ 11
12: IRQ 12
15: IRQ 15
Byte_t Frequency: A flag identifying the frequency
of the periodic interrupt, can be any one of the following:
FREQ_DIS - periodic interrupt disabled
FREQ_137HZ - 137 Hertz
FREQ_69HZ - 69 Hertz
FREQ_34HZ - 34 Hertz
FREQ_17HZ - 17 Hertz
FREQ_9HZ - 9 Hertz
FREQ_4HZ - 4 Hertz
If IRQNum is set to 0 the Frequency parameter is
overidden, it is forced to a value of FREQ_DIS.
int PeriodicOnly: 1 if all interrupts except the periodic
interrupt are to be blocked.
0 is both the periodic interrupt and
other channel interrupts are allowed.
If IRQNum is set to 0 the PeriodicOnly parameter is
overidden, it is forced to a value of 0.
Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
initialization failed.
Comments:
If periodic interrupts are to be disabled but AIOP interrupts
are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
If interrupts are to be completely disabled set IRQNum to 0.
Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
invalid combination.
This function performs initialization of global interrupt modes,
but it does not actually enable global interrupts. To enable
and disable global interrupts use functions sEnGlobalInt() and
sDisGlobalInt(). Enabling of global interrupts is normally not
done until all other initializations are complete.
Even if interrupts are globally enabled, they must also be
individually enabled for each channel that is to generate
interrupts.
Warnings: No range checking on any of the parameters is done.
No context switches are allowed while executing this function.
After this function all AIOPs on the controller are disabled,
they can be enabled with sEnAiop().
*/
static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
ByteIO_t * AiopIOList, int AiopIOListSize,
WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
int PeriodicOnly, int altChanRingIndicator,
int UPCIRingInd)
{
int i;
ByteIO_t io;
CtlP->AltChanRingIndicator = altChanRingIndicator;
CtlP->UPCIRingInd = UPCIRingInd;
CtlP->CtlNum = CtlNum;
CtlP->CtlID = CTLID_0001; /* controller release 1 */
CtlP->BusType = isPCI; /* controller release 1 */
if (ConfigIO) {
CtlP->isUPCI = 1;
CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
CtlP->AiopIntrBits = upci_aiop_intr_bits;
} else {
CtlP->isUPCI = 0;
CtlP->PCIIO =
(WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
CtlP->AiopIntrBits = aiop_intr_bits;
}
sPCIControllerEOI(CtlP); /* clear EOI if warm init */
/* Init AIOPs */
CtlP->NumAiop = 0;
for (i = 0; i < AiopIOListSize; i++) {
io = AiopIOList[i];
CtlP->AiopIO[i] = (WordIO_t) io;
CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
CtlP->AiopID[i] = sReadAiopID(io); /* read AIOP ID */
if (CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */
break; /* done looking for AIOPs */
CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io); /* num channels in AIOP */
sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE); /* clock prescaler */
sOutB(io + _INDX_DATA, sClockPrescale);
CtlP->NumAiop++; /* bump count of AIOPs */
}
if (CtlP->NumAiop == 0)
return (-1);
else
return (CtlP->NumAiop);
}
/***************************************************************************
Function: sReadAiopID
Purpose: Read the AIOP idenfication number directly from an AIOP.
@ -3136,25 +3143,6 @@ static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
sOutB(addr + chan, 0); /* apply or remove reset */
}
/* Resets the speaker controller on RocketModem II and III devices */
static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
{
ByteIO_t addr;
/* RocketModem II speaker control is at the 8th port location of offset 0x40 */
if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
addr = CtlP->AiopIO[0] + 0x4F;
sOutB(addr, 0);
}
/* RocketModem III speaker control is at the 1st port location of offset 0x80 */
if ((model == MODEL_UPCI_RM3_8PORT)
|| (model == MODEL_UPCI_RM3_4PORT)) {
addr = CtlP->AiopIO[0] + 0x88;
sOutB(addr, 0);
}
}
/* Returns the line number given the controller (board), aiop and channel number */
static unsigned char GetLineNumber(int ctrl, int aiop, int ch)
{

View file

@ -14,7 +14,6 @@
* 2.4/2.5 port David McCullough
*/
#include <asm/dbg.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/serial.h>
@ -630,8 +629,7 @@ static void rs_flush_chars(struct tty_struct *tty)
/* Enable transmitter */
local_irq_save(flags);
if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
!info->xmit_buf) {
if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf) {
local_irq_restore(flags);
return;
}
@ -697,7 +695,7 @@ static int rs_write(struct tty_struct * tty,
total += c;
}
if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
if (info->xmit_cnt && !tty->stopped) {
/* Enable transmitter */
local_irq_disable();
#ifndef USE_INTS
@ -978,10 +976,8 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
change_speed(info, tty);
if ((old_termios->c_cflag & CRTSCTS) &&
!(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
!(tty->termios.c_cflag & CRTSCTS))
rs_start(tty);
}
}

View file

@ -117,13 +117,6 @@ static inline void serial_dl_write(struct uart_8250_port *up, int value)
* is cleared, the machine locks up with endless interrupts.
*/
#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2 | UART_MCR_OUT1)
#elif defined(CONFIG_SBC8560)
/*
* WindRiver did something similarly broken on their SBC8560 board. The
* UART tristates its IRQ output while OUT2 is clear, but they pulled
* the interrupt line _up_ instead of down, so if we register the IRQ
* while the UART is in that state, we die in an IRQ storm. */
#define ALPHA_KLUDGE_MCR (UART_MCR_OUT2)
#else
#define ALPHA_KLUDGE_MCR 0
#endif

View file

@ -3247,6 +3247,10 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
uart->tx_loadsz = up->tx_loadsz;
uart->capabilities = up->capabilities;
/* Take tx_loadsz from fifosize if it wasn't set separately */
if (uart->port.fifosize && !uart->tx_loadsz)
uart->tx_loadsz = uart->port.fifosize;
if (up->port.dev)
uart->port.dev = up->port.dev;
@ -3418,6 +3422,7 @@ MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
#endif
MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
#ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS
#ifndef MODULE
/* This module was renamed to 8250_core in 3.7. Keep the old "8250" name
* working as well for the module options so we don't break people. We
@ -3432,7 +3437,7 @@ MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
static void __used s8250_options(void)
{
#undef MODULE_PARAM_PREFIX
#define MODULE_PARAM_PREFIX "8250."
#define MODULE_PARAM_PREFIX "8250_core."
module_param_cb(share_irqs, &param_ops_uint, &share_irqs, 0644);
module_param_cb(nr_uarts, &param_ops_uint, &nr_uarts, 0644);
@ -3444,5 +3449,6 @@ static void __used s8250_options(void)
#endif
}
#else
MODULE_ALIAS("8250");
MODULE_ALIAS("8250_core");
#endif
#endif

View file

@ -33,10 +33,8 @@ static void __dma_tx_complete(void *param)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&p->port);
if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port)) {
if (!uart_circ_empty(xmit) && !uart_tx_stopped(&p->port))
serial8250_tx_dma(p);
uart_write_wakeup(&p->port);
}
}
static void __dma_rx_complete(void *param)
@ -67,12 +65,11 @@ int serial8250_tx_dma(struct uart_8250_port *p)
struct circ_buf *xmit = &p->port.state->xmit;
struct dma_async_tx_descriptor *desc;
if (dma->tx_running)
return -EBUSY;
if (uart_tx_stopped(&p->port) || dma->tx_running ||
uart_circ_empty(xmit))
return 0;
dma->tx_size = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
if (!dma->tx_size)
return -EINVAL;
desc = dmaengine_prep_slave_single(dma->txchan,
dma->tx_addr + xmit->tail,
@ -104,20 +101,29 @@ int serial8250_rx_dma(struct uart_8250_port *p, unsigned int iir)
struct dma_tx_state state;
int dma_status;
/*
* If RCVR FIFO trigger level was not reached, complete the transfer and
* let 8250.c copy the remaining data.
*/
if ((iir & 0x3f) == UART_IIR_RX_TIMEOUT) {
dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie,
&state);
dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
switch (iir & 0x3f) {
case UART_IIR_RLSI:
/* 8250_core handles errors and break interrupts */
return -EIO;
case UART_IIR_RX_TIMEOUT:
/*
* If RCVR FIFO trigger level was not reached, complete the
* transfer and let 8250_core copy the remaining data.
*/
if (dma_status == DMA_IN_PROGRESS) {
dmaengine_pause(dma->rxchan);
__dma_rx_complete(p);
}
return -ETIMEDOUT;
default:
break;
}
if (dma_status)
return 0;
desc = dmaengine_prep_slave_single(dma->rxchan, dma->rx_addr,
dma->rx_size, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
@ -143,21 +149,31 @@ int serial8250_request_dma(struct uart_8250_port *p)
struct uart_8250_dma *dma = p->dma;
dma_cap_mask_t mask;
dma->rxconf.src_addr = p->port.mapbase + UART_RX;
dma->txconf.dst_addr = p->port.mapbase + UART_TX;
/* Default slave configuration parameters */
dma->rxconf.direction = DMA_DEV_TO_MEM;
dma->rxconf.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma->rxconf.src_addr = p->port.mapbase + UART_RX;
dma->txconf.direction = DMA_MEM_TO_DEV;
dma->txconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
dma->txconf.dst_addr = p->port.mapbase + UART_TX;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
/* Get a channel for RX */
dma->rxchan = dma_request_channel(mask, dma->fn, dma->rx_param);
dma->rxchan = dma_request_slave_channel_compat(mask,
dma->fn, dma->rx_param,
p->port.dev, "rx");
if (!dma->rxchan)
return -ENODEV;
dmaengine_slave_config(dma->rxchan, &dma->rxconf);
/* Get a channel for TX */
dma->txchan = dma_request_channel(mask, dma->fn, dma->tx_param);
dma->txchan = dma_request_slave_channel_compat(mask,
dma->fn, dma->tx_param,
p->port.dev, "tx");
if (!dma->txchan) {
dma_release_channel(dma->rxchan);
return -ENODEV;

View file

@ -26,6 +26,8 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
#include "8250.h"
@ -34,9 +36,6 @@
#define DW_UART_CPR 0xf4 /* Component Parameter Register */
#define DW_UART_UCV 0xf8 /* UART Component Version */
/* Intel Low Power Subsystem specific */
#define LPSS_PRV_CLOCK_PARAMS 0x800
/* Component Parameter Register bits */
#define DW_UART_CPR_ABP_DATA_WIDTH (3 << 0)
#define DW_UART_CPR_AFCE_MODE (1 << 4)
@ -55,8 +54,9 @@
struct dw8250_data {
int last_lcr;
int line;
int last_lcr;
int line;
struct clk *clk;
};
static void dw8250_serial_out(struct uart_port *p, int offset, int value)
@ -113,6 +113,18 @@ static int dw8250_handle_irq(struct uart_port *p)
return 0;
}
static void
dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
{
if (!state)
pm_runtime_get_sync(port->dev);
serial8250_do_pm(port, state, old);
if (state)
pm_runtime_put_sync_suspend(port->dev);
}
static int dw8250_probe_of(struct uart_port *p)
{
struct device_node *np = p->dev->of_node;
@ -136,8 +148,13 @@ static int dw8250_probe_of(struct uart_port *p)
if (!of_property_read_u32(np, "reg-shift", &val))
p->regshift = val;
/* clock got configured through clk api, all done */
if (p->uartclk)
return 0;
/* try to find out clock frequency from DT as fallback */
if (of_property_read_u32(np, "clock-frequency", &val)) {
dev_err(p->dev, "no clock-frequency property set\n");
dev_err(p->dev, "clk or clock-frequency not defined\n");
return -EINVAL;
}
p->uartclk = val;
@ -146,67 +163,10 @@ static int dw8250_probe_of(struct uart_port *p)
}
#ifdef CONFIG_ACPI
static bool dw8250_acpi_dma_filter(struct dma_chan *chan, void *parm)
{
return chan->chan_id == *(int *)parm;
}
static acpi_status
dw8250_acpi_walk_resource(struct acpi_resource *res, void *data)
{
struct uart_port *p = data;
struct uart_8250_port *port;
struct uart_8250_dma *dma;
struct acpi_resource_fixed_dma *fixed_dma;
struct dma_slave_config *slave;
port = container_of(p, struct uart_8250_port, port);
switch (res->type) {
case ACPI_RESOURCE_TYPE_FIXED_DMA:
fixed_dma = &res->data.fixed_dma;
/* TX comes first */
if (!port->dma) {
dma = devm_kzalloc(p->dev, sizeof(*dma), GFP_KERNEL);
if (!dma)
return AE_NO_MEMORY;
port->dma = dma;
slave = &dma->txconf;
slave->direction = DMA_MEM_TO_DEV;
slave->dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
slave->slave_id = fixed_dma->request_lines;
slave->dst_maxburst = port->tx_loadsz / 4;
dma->tx_chan_id = fixed_dma->channels;
dma->tx_param = &dma->tx_chan_id;
dma->fn = dw8250_acpi_dma_filter;
} else {
dma = port->dma;
slave = &dma->rxconf;
slave->direction = DMA_DEV_TO_MEM;
slave->src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
slave->slave_id = fixed_dma->request_lines;
slave->src_maxburst = p->fifosize / 4;
dma->rx_chan_id = fixed_dma->channels;
dma->rx_param = &dma->rx_chan_id;
}
break;
}
return AE_OK;
}
static int dw8250_probe_acpi(struct uart_port *p)
static int dw8250_probe_acpi(struct uart_8250_port *up)
{
const struct acpi_device_id *id;
acpi_status status;
u32 reg;
struct uart_port *p = &up->port;
id = acpi_match_device(p->dev->driver->acpi_match_table, p->dev);
if (!id)
@ -216,26 +176,21 @@ static int dw8250_probe_acpi(struct uart_port *p)
p->serial_in = dw8250_serial_in32;
p->serial_out = dw8250_serial_out32;
p->regshift = 2;
p->uartclk = (unsigned int)id->driver_data;
status = acpi_walk_resources(ACPI_HANDLE(p->dev), METHOD_NAME__CRS,
dw8250_acpi_walk_resource, p);
if (ACPI_FAILURE(status)) {
dev_err_ratelimited(p->dev, "%s failed \"%s\"\n", __func__,
acpi_format_exception(status));
return -ENODEV;
}
if (!p->uartclk)
p->uartclk = (unsigned int)id->driver_data;
/* Fix Haswell issue where the clocks do not get enabled */
if (!strcmp(id->id, "INT33C4") || !strcmp(id->id, "INT33C5")) {
reg = readl(p->membase + LPSS_PRV_CLOCK_PARAMS);
writel(reg | 1, p->membase + LPSS_PRV_CLOCK_PARAMS);
}
up->dma = devm_kzalloc(p->dev, sizeof(*up->dma), GFP_KERNEL);
if (!up->dma)
return -ENOMEM;
up->dma->rxconf.src_maxburst = p->fifosize / 4;
up->dma->txconf.dst_maxburst = p->fifosize / 4;
return 0;
}
#else
static inline int dw8250_probe_acpi(struct uart_port *p)
static inline int dw8250_probe_acpi(struct uart_8250_port *up)
{
return -ENODEV;
}
@ -266,7 +221,11 @@ static void dw8250_setup_port(struct uart_8250_port *up)
p->flags |= UPF_FIXED_TYPE;
p->fifosize = DW_UART_CPR_FIFO_SIZE(reg);
up->tx_loadsz = p->fifosize;
up->capabilities = UART_CAP_FIFO;
}
if (reg & DW_UART_CPR_AFCE_MODE)
up->capabilities |= UART_CAP_AFE;
}
static int dw8250_probe(struct platform_device *pdev)
@ -286,17 +245,30 @@ static int dw8250_probe(struct platform_device *pdev)
uart.port.mapbase = regs->start;
uart.port.irq = irq->start;
uart.port.handle_irq = dw8250_handle_irq;
uart.port.pm = dw8250_do_pm;
uart.port.type = PORT_8250;
uart.port.flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
uart.port.dev = &pdev->dev;
uart.port.membase = ioremap(regs->start, resource_size(regs));
uart.port.membase = devm_ioremap(&pdev->dev, regs->start,
resource_size(regs));
if (!uart.port.membase)
return -ENOMEM;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->clk = devm_clk_get(&pdev->dev, NULL);
if (!IS_ERR(data->clk)) {
clk_prepare_enable(data->clk);
uart.port.uartclk = clk_get_rate(data->clk);
}
uart.port.iotype = UPIO_MEM;
uart.port.serial_in = dw8250_serial_in;
uart.port.serial_out = dw8250_serial_out;
uart.port.private_data = data;
dw8250_setup_port(&uart);
@ -305,25 +277,22 @@ static int dw8250_probe(struct platform_device *pdev)
if (err)
return err;
} else if (ACPI_HANDLE(&pdev->dev)) {
err = dw8250_probe_acpi(&uart.port);
err = dw8250_probe_acpi(&uart);
if (err)
return err;
} else {
return -ENODEV;
}
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
uart.port.private_data = data;
data->line = serial8250_register_8250_port(&uart);
if (data->line < 0)
return data->line;
platform_set_drvdata(pdev, data);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
return 0;
}
@ -331,34 +300,66 @@ static int dw8250_remove(struct platform_device *pdev)
{
struct dw8250_data *data = platform_get_drvdata(pdev);
pm_runtime_get_sync(&pdev->dev);
serial8250_unregister_port(data->line);
if (!IS_ERR(data->clk))
clk_disable_unprepare(data->clk);
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
return 0;
}
#ifdef CONFIG_PM
static int dw8250_suspend(struct platform_device *pdev, pm_message_t state)
static int dw8250_suspend(struct device *dev)
{
struct dw8250_data *data = platform_get_drvdata(pdev);
struct dw8250_data *data = dev_get_drvdata(dev);
serial8250_suspend_port(data->line);
return 0;
}
static int dw8250_resume(struct platform_device *pdev)
static int dw8250_resume(struct device *dev)
{
struct dw8250_data *data = platform_get_drvdata(pdev);
struct dw8250_data *data = dev_get_drvdata(dev);
serial8250_resume_port(data->line);
return 0;
}
#else
#define dw8250_suspend NULL
#define dw8250_resume NULL
#endif /* CONFIG_PM */
#ifdef CONFIG_PM_RUNTIME
static int dw8250_runtime_suspend(struct device *dev)
{
struct dw8250_data *data = dev_get_drvdata(dev);
if (!IS_ERR(data->clk))
clk_disable_unprepare(data->clk);
return 0;
}
static int dw8250_runtime_resume(struct device *dev)
{
struct dw8250_data *data = dev_get_drvdata(dev);
if (!IS_ERR(data->clk))
clk_prepare_enable(data->clk);
return 0;
}
#endif
static const struct dev_pm_ops dw8250_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(dw8250_suspend, dw8250_resume)
SET_RUNTIME_PM_OPS(dw8250_runtime_suspend, dw8250_runtime_resume, NULL)
};
static const struct of_device_id dw8250_of_match[] = {
{ .compatible = "snps,dw-apb-uart" },
{ /* Sentinel */ }
@ -366,8 +367,9 @@ static const struct of_device_id dw8250_of_match[] = {
MODULE_DEVICE_TABLE(of, dw8250_of_match);
static const struct acpi_device_id dw8250_acpi_match[] = {
{ "INT33C4", 100000000 },
{ "INT33C5", 100000000 },
{ "INT33C4", 0 },
{ "INT33C5", 0 },
{ "80860F0A", 0 },
{ },
};
MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
@ -376,13 +378,12 @@ static struct platform_driver dw8250_platform_driver = {
.driver = {
.name = "dw-apb-uart",
.owner = THIS_MODULE,
.pm = &dw8250_pm_ops,
.of_match_table = dw8250_of_match,
.acpi_match_table = ACPI_PTR(dw8250_acpi_match),
},
.probe = dw8250_probe,
.remove = dw8250_remove,
.suspend = dw8250_suspend,
.resume = dw8250_resume,
};
module_platform_driver(dw8250_platform_driver);

View file

@ -1554,6 +1554,7 @@ pci_wch_ch353_setup(struct serial_private *priv,
#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
#define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
#define PCI_VENDOR_ID_WCH 0x4348
#define PCI_DEVICE_ID_WCH_CH352_2S 0x3253
#define PCI_DEVICE_ID_WCH_CH353_4S 0x3453
#define PCI_DEVICE_ID_WCH_CH353_2S1PF 0x5046
#define PCI_DEVICE_ID_WCH_CH353_2S1P 0x7053
@ -2172,6 +2173,14 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.subdevice = PCI_ANY_ID,
.setup = pci_wch_ch353_setup,
},
/* WCH CH352 2S card (16550 clone) */
{
.vendor = PCI_VENDOR_ID_WCH,
.device = PCI_DEVICE_ID_WCH_CH352_2S,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.setup = pci_wch_ch353_setup,
},
/*
* ASIX devices with FIFO bug
*/
@ -4870,6 +4879,10 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID,
0, 0, pbn_b0_bt_2_115200 },
{ PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH352_2S,
PCI_ANY_ID, PCI_ANY_ID,
0, 0, pbn_b0_bt_2_115200 },
/*
* Commtech, Inc. Fastcom adapters
*/

View file

@ -429,7 +429,6 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
struct uart_8250_port uart;
int ret, line, flags = dev_id->driver_data;
struct resource *res = NULL;
if (flags & UNKNOWN_DEV) {
ret = serial_pnp_guess_board(dev);
@ -440,12 +439,11 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
memset(&uart, 0, sizeof(uart));
if (pnp_irq_valid(dev, 0))
uart.port.irq = pnp_irq(dev, 0);
if ((flags & CIR_PORT) && pnp_port_valid(dev, 2))
res = pnp_get_resource(dev, IORESOURCE_IO, 2);
else if (pnp_port_valid(dev, 0))
res = pnp_get_resource(dev, IORESOURCE_IO, 0);
if (pnp_resource_enabled(res)) {
uart.port.iobase = res->start;
if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) {
uart.port.iobase = pnp_port_start(dev, 2);
uart.port.iotype = UPIO_PORT;
} else if (pnp_port_valid(dev, 0)) {
uart.port.iobase = pnp_port_start(dev, 0);
uart.port.iotype = UPIO_PORT;
} else if (pnp_mem_valid(dev, 0)) {
uart.port.mapbase = pnp_mem_start(dev, 0);

View file

@ -33,6 +33,23 @@ config SERIAL_8250
Most people will say Y or M here, so that they can use serial mice,
modems and similar devices connecting to the standard serial ports.
config SERIAL_8250_DEPRECATED_OPTIONS
bool "Support 8250_core.* kernel options (DEPRECATED)"
depends on SERIAL_8250
default y
---help---
In 3.7 we renamed 8250 to 8250_core by mistake, so now we have to
accept kernel parameters in both forms like 8250_core.nr_uarts=4 and
8250.nr_uarts=4. We now renamed the module back to 8250, but if
anybody noticed in 3.7 and changed their userspace we still have to
keep the 8350_core.* options around until they revert the changes
they already did.
If 8250 is built as a module, this adds 8250_core alias instead.
If you did not notice yet and/or you have userspace from pre-3.7, it
is safe (and recommended) to say N here.
config SERIAL_8250_PNP
bool "8250/16550 PNP device support" if EXPERT
depends on SERIAL_8250 && PNP

View file

@ -2,10 +2,10 @@
# Makefile for the 8250 serial device drivers.
#
obj-$(CONFIG_SERIAL_8250) += 8250_core.o
8250_core-y := 8250.o
8250_core-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
8250_core-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o
obj-$(CONFIG_SERIAL_8250) += 8250.o
8250-y := 8250_core.o
8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
8250-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o
obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o

View file

@ -852,18 +852,6 @@ static struct pcmcia_driver serial_cs_driver = {
.suspend = serial_suspend,
.resume = serial_resume,
};
static int __init init_serial_cs(void)
{
return pcmcia_register_driver(&serial_cs_driver);
}
static void __exit exit_serial_cs(void)
{
pcmcia_unregister_driver(&serial_cs_driver);
}
module_init(init_serial_cs);
module_exit(exit_serial_cs);
module_pcmcia_driver(serial_cs_driver);
MODULE_LICENSE("GPL");

View file

@ -29,6 +29,7 @@
* and hooked into this driver.
*/
#if defined(CONFIG_SERIAL_AMBA_PL011_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
@ -72,32 +73,44 @@
/* There is by now at least one vendor with differing details, so handle it */
struct vendor_data {
unsigned int ifls;
unsigned int fifosize;
unsigned int lcrh_tx;
unsigned int lcrh_rx;
bool oversampling;
bool dma_threshold;
bool cts_event_workaround;
unsigned int (*get_fifosize)(unsigned int periphid);
};
static unsigned int get_fifosize_arm(unsigned int periphid)
{
unsigned int rev = (periphid >> 20) & 0xf;
return rev < 3 ? 16 : 32;
}
static struct vendor_data vendor_arm = {
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
.fifosize = 16,
.lcrh_tx = UART011_LCRH,
.lcrh_rx = UART011_LCRH,
.oversampling = false,
.dma_threshold = false,
.cts_event_workaround = false,
.get_fifosize = get_fifosize_arm,
};
static unsigned int get_fifosize_st(unsigned int periphid)
{
return 64;
}
static struct vendor_data vendor_st = {
.ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
.fifosize = 64,
.lcrh_tx = ST_UART011_LCRH_TX,
.lcrh_rx = ST_UART011_LCRH_RX,
.oversampling = true,
.dma_threshold = true,
.cts_event_workaround = true,
.get_fifosize = get_fifosize_st,
};
static struct uart_amba_port *amba_ports[UART_NR];
@ -117,6 +130,12 @@ struct pl011_dmarx_data {
struct pl011_sgbuf sgbuf_b;
dma_cookie_t cookie;
bool running;
struct timer_list timer;
unsigned int last_residue;
unsigned long last_jiffies;
bool auto_poll_rate;
unsigned int poll_rate;
unsigned int poll_timeout;
};
struct pl011_dmatx_data {
@ -223,16 +242,18 @@ static int pl011_fifo_to_tty(struct uart_amba_port *uap)
static int pl011_sgbuf_init(struct dma_chan *chan, struct pl011_sgbuf *sg,
enum dma_data_direction dir)
{
sg->buf = kmalloc(PL011_DMA_BUFFER_SIZE, GFP_KERNEL);
dma_addr_t dma_addr;
sg->buf = dma_alloc_coherent(chan->device->dev,
PL011_DMA_BUFFER_SIZE, &dma_addr, GFP_KERNEL);
if (!sg->buf)
return -ENOMEM;
sg_init_one(&sg->sg, sg->buf, PL011_DMA_BUFFER_SIZE);
sg_init_table(&sg->sg, 1);
sg_set_page(&sg->sg, phys_to_page(dma_addr),
PL011_DMA_BUFFER_SIZE, offset_in_page(dma_addr));
sg_dma_address(&sg->sg) = dma_addr;
if (dma_map_sg(chan->device->dev, &sg->sg, 1, dir) != 1) {
kfree(sg->buf);
return -EINVAL;
}
return 0;
}
@ -240,12 +261,13 @@ static void pl011_sgbuf_free(struct dma_chan *chan, struct pl011_sgbuf *sg,
enum dma_data_direction dir)
{
if (sg->buf) {
dma_unmap_sg(chan->device->dev, &sg->sg, 1, dir);
kfree(sg->buf);
dma_free_coherent(chan->device->dev,
PL011_DMA_BUFFER_SIZE, sg->buf,
sg_dma_address(&sg->sg));
}
}
static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port *uap)
{
/* DMA is the sole user of the platform data right now */
struct amba_pl011_data *plat = uap->port.dev->platform_data;
@ -259,20 +281,25 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
struct dma_chan *chan;
dma_cap_mask_t mask;
/* We need platform data */
if (!plat || !plat->dma_filter) {
dev_info(uap->port.dev, "no DMA platform data\n");
return;
}
chan = dma_request_slave_channel(dev, "tx");
/* Try to acquire a generic DMA engine slave TX channel */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
chan = dma_request_channel(mask, plat->dma_filter, plat->dma_tx_param);
if (!chan) {
dev_err(uap->port.dev, "no TX DMA channel!\n");
return;
/* We need platform data */
if (!plat || !plat->dma_filter) {
dev_info(uap->port.dev, "no DMA platform data\n");
return;
}
/* Try to acquire a generic DMA engine slave TX channel */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
chan = dma_request_channel(mask, plat->dma_filter,
plat->dma_tx_param);
if (!chan) {
dev_err(uap->port.dev, "no TX DMA channel!\n");
return;
}
}
dmaengine_slave_config(chan, &tx_conf);
@ -282,7 +309,18 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
dma_chan_name(uap->dmatx.chan));
/* Optionally make use of an RX channel as well */
if (plat->dma_rx_param) {
chan = dma_request_slave_channel(dev, "rx");
if (!chan && plat->dma_rx_param) {
chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
if (!chan) {
dev_err(uap->port.dev, "no RX DMA channel!\n");
return;
}
}
if (chan) {
struct dma_slave_config rx_conf = {
.src_addr = uap->port.mapbase + UART01x_DR,
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
@ -291,15 +329,32 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
.device_fc = false,
};
chan = dma_request_channel(mask, plat->dma_filter, plat->dma_rx_param);
if (!chan) {
dev_err(uap->port.dev, "no RX DMA channel!\n");
return;
}
dmaengine_slave_config(chan, &rx_conf);
uap->dmarx.chan = chan;
if (plat && plat->dma_rx_poll_enable) {
/* Set poll rate if specified. */
if (plat->dma_rx_poll_rate) {
uap->dmarx.auto_poll_rate = false;
uap->dmarx.poll_rate = plat->dma_rx_poll_rate;
} else {
/*
* 100 ms defaults to poll rate if not
* specified. This will be adjusted with
* the baud rate at set_termios.
*/
uap->dmarx.auto_poll_rate = true;
uap->dmarx.poll_rate = 100;
}
/* 3 secs defaults poll_timeout if not specified. */
if (plat->dma_rx_poll_timeout)
uap->dmarx.poll_timeout =
plat->dma_rx_poll_timeout;
else
uap->dmarx.poll_timeout = 3000;
} else
uap->dmarx.auto_poll_rate = false;
dev_info(uap->port.dev, "DMA channel RX %s\n",
dma_chan_name(uap->dmarx.chan));
}
@ -315,6 +370,7 @@ static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
struct dma_uap {
struct list_head node;
struct uart_amba_port *uap;
struct device *dev;
};
static LIST_HEAD(pl011_dma_uarts);
@ -325,7 +381,7 @@ static int __init pl011_dma_initcall(void)
list_for_each_safe(node, tmp, &pl011_dma_uarts) {
struct dma_uap *dmau = list_entry(node, struct dma_uap, node);
pl011_dma_probe_initcall(dmau->uap);
pl011_dma_probe_initcall(dmau->dev, dmau->uap);
list_del(node);
kfree(dmau);
}
@ -334,18 +390,19 @@ static int __init pl011_dma_initcall(void)
device_initcall(pl011_dma_initcall);
static void pl011_dma_probe(struct uart_amba_port *uap)
static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
{
struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL);
if (dmau) {
dmau->uap = uap;
dmau->dev = dev;
list_add_tail(&dmau->node, &pl011_dma_uarts);
}
}
#else
static void pl011_dma_probe(struct uart_amba_port *uap)
static void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
{
pl011_dma_probe_initcall(uap);
pl011_dma_probe_initcall(dev, uap);
}
#endif
@ -701,24 +758,30 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
struct tty_port *port = &uap->port.state->port;
struct pl011_sgbuf *sgbuf = use_buf_b ?
&uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
struct device *dev = uap->dmarx.chan->device->dev;
int dma_count = 0;
u32 fifotaken = 0; /* only used for vdbg() */
/* Pick everything from the DMA first */
struct pl011_dmarx_data *dmarx = &uap->dmarx;
int dmataken = 0;
if (uap->dmarx.poll_rate) {
/* The data can be taken by polling */
dmataken = sgbuf->sg.length - dmarx->last_residue;
/* Recalculate the pending size */
if (pending >= dmataken)
pending -= dmataken;
}
/* Pick the remain data from the DMA */
if (pending) {
/* Sync in buffer */
dma_sync_sg_for_cpu(dev, &sgbuf->sg, 1, DMA_FROM_DEVICE);
/*
* First take all chars in the DMA pipe, then look in the FIFO.
* Note that tty_insert_flip_buf() tries to take as many chars
* as it can.
*/
dma_count = tty_insert_flip_string(port, sgbuf->buf, pending);
/* Return buffer to device */
dma_sync_sg_for_device(dev, &sgbuf->sg, 1, DMA_FROM_DEVICE);
dma_count = tty_insert_flip_string(port, sgbuf->buf + dmataken,
pending);
uap->port.icount.rx += dma_count;
if (dma_count < pending)
@ -726,6 +789,10 @@ static void pl011_dma_rx_chars(struct uart_amba_port *uap,
"couldn't insert all characters (TTY is full?)\n");
}
/* Reset the last_residue for Rx DMA poll */
if (uap->dmarx.poll_rate)
dmarx->last_residue = sgbuf->sg.length;
/*
* Only continue with trying to read the FIFO if all DMA chars have
* been taken first.
@ -865,6 +932,57 @@ static inline void pl011_dma_rx_stop(struct uart_amba_port *uap)
writew(uap->dmacr, uap->port.membase + UART011_DMACR);
}
/*
* Timer handler for Rx DMA polling.
* Every polling, It checks the residue in the dma buffer and transfer
* data to the tty. Also, last_residue is updated for the next polling.
*/
static void pl011_dma_rx_poll(unsigned long args)
{
struct uart_amba_port *uap = (struct uart_amba_port *)args;
struct tty_port *port = &uap->port.state->port;
struct pl011_dmarx_data *dmarx = &uap->dmarx;
struct dma_chan *rxchan = uap->dmarx.chan;
unsigned long flags = 0;
unsigned int dmataken = 0;
unsigned int size = 0;
struct pl011_sgbuf *sgbuf;
int dma_count;
struct dma_tx_state state;
sgbuf = dmarx->use_buf_b ? &uap->dmarx.sgbuf_b : &uap->dmarx.sgbuf_a;
rxchan->device->device_tx_status(rxchan, dmarx->cookie, &state);
if (likely(state.residue < dmarx->last_residue)) {
dmataken = sgbuf->sg.length - dmarx->last_residue;
size = dmarx->last_residue - state.residue;
dma_count = tty_insert_flip_string(port, sgbuf->buf + dmataken,
size);
if (dma_count == size)
dmarx->last_residue = state.residue;
dmarx->last_jiffies = jiffies;
}
tty_flip_buffer_push(port);
/*
* If no data is received in poll_timeout, the driver will fall back
* to interrupt mode. We will retrigger DMA at the first interrupt.
*/
if (jiffies_to_msecs(jiffies - dmarx->last_jiffies)
> uap->dmarx.poll_timeout) {
spin_lock_irqsave(&uap->port.lock, flags);
pl011_dma_rx_stop(uap);
spin_unlock_irqrestore(&uap->port.lock, flags);
uap->dmarx.running = false;
dmaengine_terminate_all(rxchan);
del_timer(&uap->dmarx.timer);
} else {
mod_timer(&uap->dmarx.timer,
jiffies + msecs_to_jiffies(uap->dmarx.poll_rate));
}
}
static void pl011_dma_startup(struct uart_amba_port *uap)
{
int ret;
@ -927,6 +1045,16 @@ skip_rx:
if (pl011_dma_rx_trigger_dma(uap))
dev_dbg(uap->port.dev, "could not trigger initial "
"RX DMA job, fall back to interrupt mode\n");
if (uap->dmarx.poll_rate) {
init_timer(&(uap->dmarx.timer));
uap->dmarx.timer.function = pl011_dma_rx_poll;
uap->dmarx.timer.data = (unsigned long)uap;
mod_timer(&uap->dmarx.timer,
jiffies +
msecs_to_jiffies(uap->dmarx.poll_rate));
uap->dmarx.last_residue = PL011_DMA_BUFFER_SIZE;
uap->dmarx.last_jiffies = jiffies;
}
}
}
@ -962,6 +1090,8 @@ static void pl011_dma_shutdown(struct uart_amba_port *uap)
/* Clean up the RX DMA */
pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_a, DMA_FROM_DEVICE);
pl011_sgbuf_free(uap->dmarx.chan, &uap->dmarx.sgbuf_b, DMA_FROM_DEVICE);
if (uap->dmarx.poll_rate)
del_timer_sync(&uap->dmarx.timer);
uap->using_rx_dma = false;
}
}
@ -976,10 +1106,9 @@ static inline bool pl011_dma_rx_running(struct uart_amba_port *uap)
return uap->using_rx_dma && uap->dmarx.running;
}
#else
/* Blank functions if the DMA engine is not available */
static inline void pl011_dma_probe(struct uart_amba_port *uap)
static inline void pl011_dma_probe(struct device *dev, struct uart_amba_port *uap)
{
}
@ -1088,8 +1217,20 @@ static void pl011_rx_chars(struct uart_amba_port *uap)
dev_dbg(uap->port.dev, "could not trigger RX DMA job "
"fall back to interrupt mode again\n");
uap->im |= UART011_RXIM;
} else
} else {
uap->im &= ~UART011_RXIM;
#ifdef CONFIG_DMA_ENGINE
/* Start Rx DMA poll */
if (uap->dmarx.poll_rate) {
uap->dmarx.last_jiffies = jiffies;
uap->dmarx.last_residue = PL011_DMA_BUFFER_SIZE;
mod_timer(&uap->dmarx.timer,
jiffies +
msecs_to_jiffies(uap->dmarx.poll_rate));
}
#endif
}
writew(uap->im, uap->port.membase + UART011_IMSC);
}
spin_lock(&uap->port.lock);
@ -1164,7 +1305,6 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
unsigned int dummy_read;
spin_lock_irqsave(&uap->port.lock, flags);
status = readw(uap->port.membase + UART011_MIS);
if (status) {
do {
@ -1551,6 +1691,13 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
*/
baud = uart_get_baud_rate(port, termios, old, 0,
port->uartclk / clkdiv);
#ifdef CONFIG_DMA_ENGINE
/*
* Adjust RX DMA polling rate with baud rate if not specified.
*/
if (uap->dmarx.auto_poll_rate)
uap->dmarx.poll_rate = DIV_ROUND_UP(10000000, baud);
#endif
if (baud > port->uartclk/16)
quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud);
@ -2010,7 +2157,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
uap->lcrh_rx = vendor->lcrh_rx;
uap->lcrh_tx = vendor->lcrh_tx;
uap->old_cr = 0;
uap->fifosize = vendor->fifosize;
uap->fifosize = vendor->get_fifosize(dev->periphid);
uap->port.dev = &dev->dev;
uap->port.mapbase = dev->res.start;
uap->port.membase = base;
@ -2020,7 +2167,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
uap->port.ops = &amba_pl011_pops;
uap->port.flags = UPF_BOOT_AUTOCONF;
uap->port.line = i;
pl011_dma_probe(uap);
pl011_dma_probe(&dev->dev, uap);
/* Ensure interrupts from this UART are masked and cleared */
writew(0, uap->port.membase + UART011_IMSC);

View file

@ -162,7 +162,7 @@ static unsigned int arc_serial_tx_empty(struct uart_port *port)
/*
* Driver internal routine, used by both tty(serial core) as well as tx-isr
* -Called under spinlock in either cases
* -also tty->stopped / tty->hw_stopped has already been checked
* -also tty->stopped has already been checked
* = by uart_start( ) before calling us
* = tx_ist checks that too before calling
*/

View file

@ -158,7 +158,7 @@ struct atmel_uart_port {
};
static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
static unsigned long atmel_ports_in_use;
static DECLARE_BITMAP(atmel_ports_in_use, ATMEL_MAX_UART);
#ifdef SUPPORT_SYSRQ
static struct console atmel_console;
@ -1769,15 +1769,14 @@ static int atmel_serial_probe(struct platform_device *pdev)
if (ret < 0)
/* port id not found in platform data nor device-tree aliases:
* auto-enumerate it */
ret = find_first_zero_bit(&atmel_ports_in_use,
sizeof(atmel_ports_in_use));
ret = find_first_zero_bit(atmel_ports_in_use, ATMEL_MAX_UART);
if (ret > ATMEL_MAX_UART) {
if (ret >= ATMEL_MAX_UART) {
ret = -ENODEV;
goto err;
}
if (test_and_set_bit(ret, &atmel_ports_in_use)) {
if (test_and_set_bit(ret, atmel_ports_in_use)) {
/* port already in use */
ret = -EBUSY;
goto err;
@ -1857,7 +1856,7 @@ static int atmel_serial_remove(struct platform_device *pdev)
/* "port" is allocated statically, so we shouldn't free it */
clear_bit(port->line, &atmel_ports_in_use);
clear_bit(port->line, atmel_ports_in_use);
clk_put(atmel_port->clk);

View file

@ -30,7 +30,6 @@
#include <linux/serial.h>
#include <linux/serial_core.h>
#include <bcm63xx_clk.h>
#include <bcm63xx_irq.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>

View file

@ -1011,24 +1011,6 @@ static int bfin_serial_poll_get_char(struct uart_port *port)
}
#endif
#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
static void bfin_kgdboc_port_shutdown(struct uart_port *port)
{
if (kgdboc_break_enabled) {
kgdboc_break_enabled = 0;
bfin_serial_shutdown(port);
}
}
static int bfin_kgdboc_port_startup(struct uart_port *port)
{
kgdboc_port_line = port->line;
kgdboc_break_enabled = !bfin_serial_startup(port);
return 0;
}
#endif
static struct uart_ops bfin_serial_pops = {
.tx_empty = bfin_serial_tx_empty,
.set_mctrl = bfin_serial_set_mctrl,
@ -1047,11 +1029,6 @@ static struct uart_ops bfin_serial_pops = {
.request_port = bfin_serial_request_port,
.config_port = bfin_serial_config_port,
.verify_port = bfin_serial_verify_port,
#if defined(CONFIG_KGDB_SERIAL_CONSOLE) || \
defined(CONFIG_KGDB_SERIAL_CONSOLE_MODULE)
.kgdboc_port_startup = bfin_kgdboc_port_startup,
.kgdboc_port_shutdown = bfin_kgdboc_port_shutdown,
#endif
#ifdef CONFIG_CONSOLE_POLL
.poll_put_char = bfin_serial_poll_put_char,
.poll_get_char = bfin_serial_poll_get_char,

View file

@ -169,7 +169,6 @@ static int get_lsr_info(struct e100_serial *info, unsigned int *value);
#define DEF_BAUD 115200 /* 115.2 kbit/s */
#define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
#define DEF_RX 0x20 /* or SERIAL_CTRL_W >> 8 */
/* Default value of tx_ctrl register: has txd(bit 7)=1 (idle) as default */
#define DEF_TX 0x80 /* or SERIAL_CTRL_B */
@ -246,7 +245,6 @@ static struct e100_serial rs_table[] = {
.ifirstadr = R_DMA_CH7_FIRST,
.icmdadr = R_DMA_CH7_CMD,
.idescradr = R_DMA_CH7_DESCR,
.flags = STD_FLAGS,
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 2,
@ -300,7 +298,6 @@ static struct e100_serial rs_table[] = {
.ifirstadr = R_DMA_CH9_FIRST,
.icmdadr = R_DMA_CH9_CMD,
.idescradr = R_DMA_CH9_DESCR,
.flags = STD_FLAGS,
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 3,
@ -356,7 +353,6 @@ static struct e100_serial rs_table[] = {
.ifirstadr = R_DMA_CH3_FIRST,
.icmdadr = R_DMA_CH3_CMD,
.idescradr = R_DMA_CH3_DESCR,
.flags = STD_FLAGS,
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 0,
@ -410,7 +406,6 @@ static struct e100_serial rs_table[] = {
.ifirstadr = R_DMA_CH5_FIRST,
.icmdadr = R_DMA_CH5_CMD,
.idescradr = R_DMA_CH5_DESCR,
.flags = STD_FLAGS,
.rx_ctrl = DEF_RX,
.tx_ctrl = DEF_TX,
.iseteop = 1,
@ -2263,8 +2258,7 @@ TODO: The break will be delayed until an F or V character is received.
*/
static
struct e100_serial * handle_ser_rx_interrupt_no_dma(struct e100_serial *info)
static void handle_ser_rx_interrupt_no_dma(struct e100_serial *info)
{
unsigned long data_read;
@ -2370,10 +2364,9 @@ more_data:
}
tty_flip_buffer_push(&info->port);
return info;
}
static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info)
static void handle_ser_rx_interrupt(struct e100_serial *info)
{
unsigned char rstat;
@ -2382,7 +2375,8 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info)
#endif
/* DEBUG_LOG(info->line, "ser_interrupt stat %03X\n", rstat | (i << 8)); */
if (!info->uses_dma_in) {
return handle_ser_rx_interrupt_no_dma(info);
handle_ser_rx_interrupt_no_dma(info);
return;
}
/* DMA is used */
rstat = info->ioport[REG_STATUS];
@ -2489,7 +2483,6 @@ static struct e100_serial* handle_ser_rx_interrupt(struct e100_serial *info)
/* Restarting the DMA never hurts */
*info->icmdadr = IO_STATE(R_DMA_CH6_CMD, cmd, restart);
START_FLUSH_FAST_TIMER(info, "ser_int");
return info;
} /* handle_ser_rx_interrupt */
static void handle_ser_tx_interrupt(struct e100_serial *info)
@ -2534,8 +2527,7 @@ static void handle_ser_tx_interrupt(struct e100_serial *info)
}
/* Normal char-by-char interrupt */
if (info->xmit.head == info->xmit.tail
|| info->port.tty->stopped
|| info->port.tty->hw_stopped) {
|| info->port.tty->stopped) {
DFLOW(DEBUG_LOG(info->line, "tx_int: stopped %i\n",
info->port.tty->stopped));
e100_disable_serial_tx_ready_irq(info);
@ -2722,7 +2714,7 @@ startup(struct e100_serial * info)
/* if it was already initialized, skip this */
if (info->flags & ASYNC_INITIALIZED) {
if (info->port.flags & ASYNC_INITIALIZED) {
local_irq_restore(flags);
free_page(xmit_page);
return 0;
@ -2847,7 +2839,7 @@ startup(struct e100_serial * info)
#endif /* CONFIG_SVINTO_SIM */
info->flags |= ASYNC_INITIALIZED;
info->port.flags |= ASYNC_INITIALIZED;
local_irq_restore(flags);
return 0;
@ -2892,7 +2884,7 @@ shutdown(struct e100_serial * info)
#endif /* CONFIG_SVINTO_SIM */
if (!(info->flags & ASYNC_INITIALIZED))
if (!(info->port.flags & ASYNC_INITIALIZED))
return;
#ifdef SERIAL_DEBUG_OPEN
@ -2923,7 +2915,7 @@ shutdown(struct e100_serial * info)
if (info->port.tty)
set_bit(TTY_IO_ERROR, &info->port.tty->flags);
info->flags &= ~ASYNC_INITIALIZED;
info->port.flags &= ~ASYNC_INITIALIZED;
local_irq_restore(flags);
}
@ -2948,7 +2940,7 @@ change_speed(struct e100_serial *info)
/* possibly, the tx/rx should be disabled first to do this safely */
/* change baud-rate and write it to the hardware */
if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) {
if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) {
/* Special baudrate */
u32 mask = 0xFF << (info->line*8); /* Each port has 8 bits */
unsigned long alt_source =
@ -3098,7 +3090,6 @@ rs_flush_chars(struct tty_struct *tty)
if (info->tr_running ||
info->xmit.head == info->xmit.tail ||
tty->stopped ||
tty->hw_stopped ||
!info->xmit.buf)
return;
@ -3176,7 +3167,6 @@ static int rs_raw_write(struct tty_struct *tty,
if (info->xmit.head != info->xmit.tail &&
!tty->stopped &&
!tty->hw_stopped &&
!info->tr_running) {
start_transmit(info);
}
@ -3400,10 +3390,10 @@ get_serial_info(struct e100_serial * info,
tmp.line = info->line;
tmp.port = (int)info->ioport;
tmp.irq = info->irq;
tmp.flags = info->flags;
tmp.flags = info->port.flags;
tmp.baud_base = info->baud_base;
tmp.close_delay = info->close_delay;
tmp.closing_wait = info->closing_wait;
tmp.close_delay = info->port.close_delay;
tmp.closing_wait = info->port.closing_wait;
tmp.custom_divisor = info->custom_divisor;
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
return -EFAULT;
@ -3425,16 +3415,16 @@ set_serial_info(struct e100_serial *info,
if (!capable(CAP_SYS_ADMIN)) {
if ((new_serial.type != info->type) ||
(new_serial.close_delay != info->close_delay) ||
(new_serial.close_delay != info->port.close_delay) ||
((new_serial.flags & ~ASYNC_USR_MASK) !=
(info->flags & ~ASYNC_USR_MASK)))
(info->port.flags & ~ASYNC_USR_MASK)))
return -EPERM;
info->flags = ((info->flags & ~ASYNC_USR_MASK) |
info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) |
(new_serial.flags & ASYNC_USR_MASK));
goto check_and_exit;
}
if (info->count > 1)
if (info->port.count > 1)
return -EBUSY;
/*
@ -3443,16 +3433,16 @@ set_serial_info(struct e100_serial *info,
*/
info->baud_base = new_serial.baud_base;
info->flags = ((info->flags & ~ASYNC_FLAGS) |
info->port.flags = ((info->port.flags & ~ASYNC_FLAGS) |
(new_serial.flags & ASYNC_FLAGS));
info->custom_divisor = new_serial.custom_divisor;
info->type = new_serial.type;
info->close_delay = new_serial.close_delay;
info->closing_wait = new_serial.closing_wait;
info->port.low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
info->port.close_delay = new_serial.close_delay;
info->port.closing_wait = new_serial.closing_wait;
info->port.low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
check_and_exit:
if (info->flags & ASYNC_INITIALIZED) {
if (info->port.flags & ASYNC_INITIALIZED) {
change_speed(info);
} else
retval = startup(info);
@ -3733,10 +3723,8 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
/* Handle turning off CRTSCTS */
if ((old_termios->c_cflag & CRTSCTS) &&
!(tty->termios.c_cflag & CRTSCTS)) {
tty->hw_stopped = 0;
!(tty->termios.c_cflag & CRTSCTS))
rs_start(tty);
}
}
@ -3772,7 +3760,7 @@ rs_close(struct tty_struct *tty, struct file * filp)
printk("[%d] rs_close ttyS%d, count = %d\n", current->pid,
info->line, info->count);
#endif
if ((tty->count == 1) && (info->count != 1)) {
if ((tty->count == 1) && (info->port.count != 1)) {
/*
* Uh, oh. tty->count is 1, which means that the tty
* structure will be freed. Info->count should always
@ -3782,32 +3770,32 @@ rs_close(struct tty_struct *tty, struct file * filp)
*/
printk(KERN_ERR
"rs_close: bad serial port count; tty->count is 1, "
"info->count is %d\n", info->count);
info->count = 1;
"info->count is %d\n", info->port.count);
info->port.count = 1;
}
if (--info->count < 0) {
if (--info->port.count < 0) {
printk(KERN_ERR "rs_close: bad serial port count for ttyS%d: %d\n",
info->line, info->count);
info->count = 0;
info->line, info->port.count);
info->port.count = 0;
}
if (info->count) {
if (info->port.count) {
local_irq_restore(flags);
return;
}
info->flags |= ASYNC_CLOSING;
info->port.flags |= ASYNC_CLOSING;
/*
* Save the termios structure, since this port may have
* separate termios for callout and dialin.
*/
if (info->flags & ASYNC_NORMAL_ACTIVE)
if (info->port.flags & ASYNC_NORMAL_ACTIVE)
info->normal_termios = tty->termios;
/*
* Now we wait for the transmit buffer to clear; and we notify
* the line discipline to only process XON/XOFF characters.
*/
tty->closing = 1;
if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, info->closing_wait);
if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, info->port.closing_wait);
/*
* At this point we stop accepting input. To do this, we
* disable the serial receiver and the DMA receive interrupt.
@ -3820,7 +3808,7 @@ rs_close(struct tty_struct *tty, struct file * filp)
e100_disable_rx(info);
e100_disable_rx_irq(info);
if (info->flags & ASYNC_INITIALIZED) {
if (info->port.flags & ASYNC_INITIALIZED) {
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
@ -3836,13 +3824,13 @@ rs_close(struct tty_struct *tty, struct file * filp)
tty->closing = 0;
info->event = 0;
info->port.tty = NULL;
if (info->blocked_open) {
if (info->close_delay)
schedule_timeout_interruptible(info->close_delay);
wake_up_interruptible(&info->open_wait);
if (info->port.blocked_open) {
if (info->port.close_delay)
schedule_timeout_interruptible(info->port.close_delay);
wake_up_interruptible(&info->port.open_wait);
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->port.close_wait);
local_irq_restore(flags);
/* port closed */
@ -3935,10 +3923,10 @@ rs_hangup(struct tty_struct *tty)
rs_flush_buffer(tty);
shutdown(info);
info->event = 0;
info->count = 0;
info->flags &= ~ASYNC_NORMAL_ACTIVE;
info->port.count = 0;
info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
info->port.tty = NULL;
wake_up_interruptible(&info->open_wait);
wake_up_interruptible(&info->port.open_wait);
}
/*
@ -3960,11 +3948,11 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
* until it's done, and then try again.
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
wait_event_interruptible_tty(tty, info->close_wait,
!(info->flags & ASYNC_CLOSING));
(info->port.flags & ASYNC_CLOSING)) {
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
if (info->flags & ASYNC_HUP_NOTIFY)
if (info->port.flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
else
return -ERESTARTSYS;
@ -3979,7 +3967,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
*/
if ((filp->f_flags & O_NONBLOCK) ||
(tty->flags & (1 << TTY_IO_ERROR))) {
info->flags |= ASYNC_NORMAL_ACTIVE;
info->port.flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
@ -3990,23 +3978,23 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
/*
* Block waiting for the carrier detect and the line to become
* free (i.e., not in use by the callout). While we are in
* this loop, info->count is dropped by one, so that
* this loop, info->port.count is dropped by one, so that
* rs_close() knows when to free things. We restore it upon
* exit, either normal or abnormal.
*/
retval = 0;
add_wait_queue(&info->open_wait, &wait);
add_wait_queue(&info->port.open_wait, &wait);
#ifdef SERIAL_DEBUG_OPEN
printk("block_til_ready before block: ttyS%d, count = %d\n",
info->line, info->count);
info->line, info->port.count);
#endif
local_irq_save(flags);
if (!tty_hung_up_p(filp)) {
extra_count++;
info->count--;
info->port.count--;
}
local_irq_restore(flags);
info->blocked_open++;
info->port.blocked_open++;
while (1) {
local_irq_save(flags);
/* assert RTS and DTR */
@ -4015,9 +4003,9 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
local_irq_restore(flags);
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) {
!(info->port.flags & ASYNC_INITIALIZED)) {
#ifdef SERIAL_DO_RESTART
if (info->flags & ASYNC_HUP_NOTIFY)
if (info->port.flags & ASYNC_HUP_NOTIFY)
retval = -EAGAIN;
else
retval = -ERESTARTSYS;
@ -4026,7 +4014,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
#endif
break;
}
if (!(info->flags & ASYNC_CLOSING) && do_clocal)
if (!(info->port.flags & ASYNC_CLOSING) && do_clocal)
/* && (do_clocal || DCD_IS_ASSERTED) */
break;
if (signal_pending(current)) {
@ -4035,24 +4023,24 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
}
#ifdef SERIAL_DEBUG_OPEN
printk("block_til_ready blocking: ttyS%d, count = %d\n",
info->line, info->count);
info->line, info->port.count);
#endif
tty_unlock(tty);
schedule();
tty_lock(tty);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&info->open_wait, &wait);
remove_wait_queue(&info->port.open_wait, &wait);
if (extra_count)
info->count++;
info->blocked_open--;
info->port.count++;
info->port.blocked_open--;
#ifdef SERIAL_DEBUG_OPEN
printk("block_til_ready after blocking: ttyS%d, count = %d\n",
info->line, info->count);
info->line, info->port.count);
#endif
if (retval)
return retval;
info->flags |= ASYNC_NORMAL_ACTIVE;
info->port.flags |= ASYNC_NORMAL_ACTIVE;
return 0;
}
@ -4086,24 +4074,24 @@ rs_open(struct tty_struct *tty, struct file * filp)
#ifdef SERIAL_DEBUG_OPEN
printk("[%d] rs_open %s, count = %d\n", current->pid, tty->name,
info->count);
info->port.count);
#endif
info->count++;
info->port.count++;
tty->driver_data = info;
info->port.tty = tty;
info->port.low_latency = !!(info->flags & ASYNC_LOW_LATENCY);
info->port.low_latency = !!(info->port.flags & ASYNC_LOW_LATENCY);
/*
* If the port is in the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
wait_event_interruptible_tty(tty, info->close_wait,
!(info->flags & ASYNC_CLOSING));
(info->port.flags & ASYNC_CLOSING)) {
wait_event_interruptible_tty(tty, info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
return ((info->flags & ASYNC_HUP_NOTIFY) ?
return ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS);
#else
return -EAGAIN;
@ -4113,7 +4101,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
/*
* If DMA is enabled try to allocate the irq's.
*/
if (info->count == 1) {
if (info->port.count == 1) {
allocated_resources = 1;
if (info->dma_in_enabled) {
if (request_irq(info->dma_in_irq_nbr,
@ -4186,7 +4174,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
if (allocated_resources)
deinit_port(info);
/* FIXME Decrease count info->count here too? */
/* FIXME Decrease count info->port.count here too? */
return retval;
}
@ -4203,7 +4191,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
return retval;
}
if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
if ((info->port.count == 1) && (info->port.flags & ASYNC_SPLIT_TERMIOS)) {
tty->termios = info->normal_termios;
change_speed(info);
}
@ -4256,9 +4244,6 @@ static void seq_line_info(struct seq_file *m, struct e100_serial *info)
if (info->port.tty->stopped)
seq_printf(m, " stopped:%i",
(int)info->port.tty->stopped);
if (info->port.tty->hw_stopped)
seq_printf(m, " hw_stopped:%i",
(int)info->port.tty->hw_stopped);
}
{
@ -4455,16 +4440,9 @@ static int __init rs_init(void)
info->forced_eop = 0;
info->baud_base = DEF_BAUD_BASE;
info->custom_divisor = 0;
info->flags = 0;
info->close_delay = 5*HZ/10;
info->closing_wait = 30*HZ;
info->x_char = 0;
info->event = 0;
info->count = 0;
info->blocked_open = 0;
info->normal_termios = driver->init_termios;
init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait);
info->xmit.buf = NULL;
info->xmit.tail = info->xmit.head = 0;
info->first_recv_buffer = info->last_recv_buffer = NULL;

View file

@ -53,8 +53,6 @@ struct e100_serial {
volatile u8 *icmdadr; /* adr to R_DMA_CHx_CMD */
volatile u32 *idescradr; /* adr to R_DMA_CHx_DESCR */
int flags; /* defined in tty.h */
u8 rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */
u8 tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */
u8 iseteop; /* bit number for R_SET_EOP for the input dma */
@ -88,19 +86,10 @@ struct e100_serial {
volatile int tr_running; /* 1 if output is running */
struct tty_struct *tty;
int read_status_mask;
int ignore_status_mask;
int x_char; /* xon/xoff character */
int close_delay;
unsigned short closing_wait;
unsigned short closing_wait2;
unsigned long event;
unsigned long last_active;
int line;
int type; /* PORT_ETRAX */
int count; /* # of fd on device */
int blocked_open; /* # of blocked opens */
struct circ_buf xmit;
struct etrax_recv_buffer *first_recv_buffer;
struct etrax_recv_buffer *last_recv_buffer;
@ -110,9 +99,6 @@ struct e100_serial {
struct work_struct work;
struct async_icount icount; /* error-statistics etc.*/
struct ktermios normal_termios;
struct ktermios callout_termios;
wait_queue_head_t open_wait;
wait_queue_head_t close_wait;
unsigned long char_time_usec; /* The time for 1 char, in usecs */
unsigned long flush_time_usec; /* How often we should flush */

View file

@ -1415,8 +1415,7 @@ static int icom_alloc_adapter(struct icom_adapter
struct icom_adapter *cur_adapter_entry;
struct list_head *tmp;
icom_adapter = (struct icom_adapter *)
kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
icom_adapter = kzalloc(sizeof(struct icom_adapter), GFP_KERNEL);
if (!icom_adapter) {
return -ENOMEM;

View file

@ -269,23 +269,6 @@ static void mrdy_assert(struct ifx_spi_device *ifx_dev)
mrdy_set_high(ifx_dev);
}
/**
* ifx_spi_hangup - hang up an IFX device
* @ifx_dev: our SPI device
*
* Hang up the tty attached to the IFX device if one is currently
* open. If not take no action
*/
static void ifx_spi_ttyhangup(struct ifx_spi_device *ifx_dev)
{
struct tty_port *pport = &ifx_dev->tty_port;
struct tty_struct *tty = tty_port_tty_get(pport);
if (tty) {
tty_hangup(tty);
tty_kref_put(tty);
}
}
/**
* ifx_spi_timeout - SPI timeout
* @arg: our SPI device
@ -298,7 +281,7 @@ static void ifx_spi_timeout(unsigned long arg)
struct ifx_spi_device *ifx_dev = (struct ifx_spi_device *)arg;
dev_warn(&ifx_dev->spi_dev->dev, "*** SPI Timeout ***");
ifx_spi_ttyhangup(ifx_dev);
tty_port_tty_hangup(&ifx_dev->tty_port, false);
mrdy_set_low(ifx_dev);
clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
}
@ -442,25 +425,6 @@ static void ifx_spi_setup_spi_header(unsigned char *txbuffer, int tx_count,
txbuffer[1] |= (more << IFX_SPI_MORE_BIT) & IFX_SPI_MORE_MASK;
}
/**
* ifx_spi_wakeup_serial - SPI space made
* @port_data: our SPI device
*
* We have emptied the FIFO enough that we want to get more data
* queued into it. Poke the line discipline via tty_wakeup so that
* it will feed us more bits
*/
static void ifx_spi_wakeup_serial(struct ifx_spi_device *ifx_dev)
{
struct tty_struct *tty;
tty = tty_port_tty_get(&ifx_dev->tty_port);
if (!tty)
return;
tty_wakeup(tty);
tty_kref_put(tty);
}
/**
* ifx_spi_prepare_tx_buffer - prepare transmit frame
* @ifx_dev: our SPI device
@ -506,7 +470,7 @@ static int ifx_spi_prepare_tx_buffer(struct ifx_spi_device *ifx_dev)
tx_count += temp_count;
if (temp_count == queue_length)
/* poke port to get more data */
ifx_spi_wakeup_serial(ifx_dev);
tty_port_tty_wakeup(&ifx_dev->tty_port);
else /* more data in port, use next SPI message */
ifx_dev->spi_more = 1;
}
@ -683,8 +647,6 @@ static void ifx_spi_insert_flip_string(struct ifx_spi_device *ifx_dev,
static void ifx_spi_complete(void *ctx)
{
struct ifx_spi_device *ifx_dev = ctx;
struct tty_struct *tty;
struct tty_ldisc *ldisc = NULL;
int length;
int actual_length;
unsigned char more;
@ -762,15 +724,7 @@ complete_exit:
*/
ifx_spi_power_state_clear(ifx_dev,
IFX_SPI_POWER_DATA_PENDING);
tty = tty_port_tty_get(&ifx_dev->tty_port);
if (tty) {
ldisc = tty_ldisc_ref(tty);
if (ldisc) {
ldisc->ops->write_wakeup(tty);
tty_ldisc_deref(ldisc);
}
tty_kref_put(tty);
}
tty_port_tty_wakeup(&ifx_dev->tty_port);
}
}
}
@ -962,7 +916,7 @@ static irqreturn_t ifx_spi_reset_interrupt(int irq, void *dev)
set_bit(MR_INPROGRESS, &ifx_dev->mdm_reset_state);
if (!solreset) {
/* unsolicited reset */
ifx_spi_ttyhangup(ifx_dev);
tty_port_tty_hangup(&ifx_dev->tty_port, false);
}
} else {
/* exited reset */
@ -1324,30 +1278,6 @@ static void ifx_spi_spi_shutdown(struct spi_device *spi)
* no hardware to save state for
*/
/**
* ifx_spi_spi_suspend - suspend SPI on system suspend
* @dev: device being suspended
*
* Suspend the SPI side. No action needed on Intel MID platforms, may
* need extending for other systems.
*/
static int ifx_spi_spi_suspend(struct spi_device *spi, pm_message_t msg)
{
return 0;
}
/**
* ifx_spi_spi_resume - resume SPI side on system resume
* @dev: device being suspended
*
* Suspend the SPI side. No action needed on Intel MID platforms, may
* need extending for other systems.
*/
static int ifx_spi_spi_resume(struct spi_device *spi)
{
return 0;
}
/**
* ifx_spi_pm_suspend - suspend modem on system suspend
* @dev: device being suspended
@ -1437,8 +1367,6 @@ static struct spi_driver ifx_spi_driver = {
.probe = ifx_spi_spi_probe,
.shutdown = ifx_spi_spi_shutdown,
.remove = ifx_spi_spi_remove,
.suspend = ifx_spi_spi_suspend,
.resume = ifx_spi_spi_resume,
.id_table = ifx_id_table
};

View file

@ -761,6 +761,8 @@ static int imx_startup(struct uart_port *port)
temp = readl(sport->port.membase + UCR2);
temp |= (UCR2_RXEN | UCR2_TXEN);
if (!sport->have_rtscts)
temp |= UCR2_IRTS;
writel(temp, sport->port.membase + UCR2);
if (USE_IRDA(sport)) {

View file

@ -596,12 +596,6 @@ void jsm_input(struct jsm_channel *ch)
jsm_dbg(READ, &ch->ch_bd->pci_dev, "start 2\n");
if (data_len <= 0) {
spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
jsm_dbg(READ, &ch->ch_bd->pci_dev, "jsm_input 1\n");
return;
}
len = tty_buffer_request_room(port, data_len);
n = len;

View file

@ -778,7 +778,7 @@ static int max3100_probe(struct spi_device *spi)
max3100s[i]->spi = spi;
max3100s[i]->irq = spi->irq;
spin_lock_init(&max3100s[i]->conf_lock);
dev_set_drvdata(&spi->dev, max3100s[i]);
spi_set_drvdata(spi, max3100s[i]);
pdata = spi->dev.platform_data;
max3100s[i]->crystal = pdata->crystal;
max3100s[i]->loopback = pdata->loopback;
@ -819,7 +819,7 @@ static int max3100_probe(struct spi_device *spi)
static int max3100_remove(struct spi_device *spi)
{
struct max3100_port *s = dev_get_drvdata(&spi->dev);
struct max3100_port *s = spi_get_drvdata(spi);
int i;
mutex_lock(&max3100s_lock);
@ -849,11 +849,11 @@ static int max3100_remove(struct spi_device *spi)
return 0;
}
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
static int max3100_suspend(struct spi_device *spi, pm_message_t state)
static int max3100_suspend(struct device *dev)
{
struct max3100_port *s = dev_get_drvdata(&spi->dev);
struct max3100_port *s = dev_get_drvdata(dev);
dev_dbg(&s->spi->dev, "%s\n", __func__);
@ -874,9 +874,9 @@ static int max3100_suspend(struct spi_device *spi, pm_message_t state)
return 0;
}
static int max3100_resume(struct spi_device *spi)
static int max3100_resume(struct device *dev)
{
struct max3100_port *s = dev_get_drvdata(&spi->dev);
struct max3100_port *s = dev_get_drvdata(dev);
dev_dbg(&s->spi->dev, "%s\n", __func__);
@ -894,21 +894,21 @@ static int max3100_resume(struct spi_device *spi)
return 0;
}
static SIMPLE_DEV_PM_OPS(max3100_pm_ops, max3100_suspend, max3100_resume);
#define MAX3100_PM_OPS (&max3100_pm_ops)
#else
#define max3100_suspend NULL
#define max3100_resume NULL
#define MAX3100_PM_OPS NULL
#endif
static struct spi_driver max3100_driver = {
.driver = {
.name = "max3100",
.owner = THIS_MODULE,
.pm = MAX3100_PM_OPS,
},
.probe = max3100_probe,
.remove = max3100_remove,
.suspend = max3100_suspend,
.resume = max3100_resume,
};
module_spi_driver(max3100_driver);

View file

@ -881,12 +881,14 @@ static struct uart_ops max310x_ops = {
.verify_port = max310x_verify_port,
};
static int max310x_suspend(struct spi_device *spi, pm_message_t state)
#ifdef CONFIG_PM_SLEEP
static int max310x_suspend(struct device *dev)
{
int ret;
struct max310x_port *s = dev_get_drvdata(&spi->dev);
struct max310x_port *s = dev_get_drvdata(dev);
dev_dbg(&spi->dev, "Suspend\n");
dev_dbg(dev, "Suspend\n");
ret = uart_suspend_port(&s->uart, &s->port);
@ -905,11 +907,11 @@ static int max310x_suspend(struct spi_device *spi, pm_message_t state)
return ret;
}
static int max310x_resume(struct spi_device *spi)
static int max310x_resume(struct device *dev)
{
struct max310x_port *s = dev_get_drvdata(&spi->dev);
struct max310x_port *s = dev_get_drvdata(dev);
dev_dbg(&spi->dev, "Resume\n");
dev_dbg(dev, "Resume\n");
if (s->pdata->suspend)
s->pdata->suspend(0);
@ -928,6 +930,13 @@ static int max310x_resume(struct spi_device *spi)
return uart_resume_port(&s->uart, &s->port);
}
static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume);
#define MAX310X_PM_OPS (&max310x_pm_ops)
#else
#define MAX310X_PM_OPS NULL
#endif
#ifdef CONFIG_GPIOLIB
static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
{
@ -1242,11 +1251,10 @@ static struct spi_driver max310x_driver = {
.driver = {
.name = "max310x",
.owner = THIS_MODULE,
.pm = MAX310X_PM_OPS,
},
.probe = max310x_probe,
.remove = max310x_remove,
.suspend = max310x_suspend,
.resume = max310x_resume,
.id_table = max310x_id_table,
};
module_spi_driver(max310x_driver);

View file

@ -707,8 +707,10 @@ static int __init mcf_init(void)
if (rc)
return rc;
rc = platform_driver_register(&mcf_platform_driver);
if (rc)
if (rc) {
uart_unregister_driver(&mcf_driver);
return rc;
}
return 0;
}

View file

@ -1497,18 +1497,23 @@ mpc52xx_uart_init(void)
if (psc_ops && psc_ops->fifoc_init) {
ret = psc_ops->fifoc_init();
if (ret)
return ret;
goto err_init;
}
ret = platform_driver_register(&mpc52xx_uart_of_driver);
if (ret) {
printk(KERN_ERR "%s: platform_driver_register failed (%i)\n",
__FILE__, ret);
uart_unregister_driver(&mpc52xx_uart_driver);
return ret;
goto err_reg;
}
return 0;
err_reg:
if (psc_ops && psc_ops->fifoc_uninit)
psc_ops->fifoc_uninit();
err_init:
uart_unregister_driver(&mpc52xx_uart_driver);
return ret;
}
static void __exit

View file

@ -743,9 +743,10 @@ static struct uart_driver serial_m3110_reg = {
.cons = &serial_m3110_console,
};
#ifdef CONFIG_PM
static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
#ifdef CONFIG_PM_SLEEP
static int serial_m3110_suspend(struct device *dev)
{
struct spi_device *spi = to_spi_device(dev);
struct uart_max3110 *max = spi_get_drvdata(spi);
disable_irq(max->irq);
@ -754,8 +755,9 @@ static int serial_m3110_suspend(struct spi_device *spi, pm_message_t state)
return 0;
}
static int serial_m3110_resume(struct spi_device *spi)
static int serial_m3110_resume(struct device *dev)
{
struct spi_device *spi = to_spi_device(dev);
struct uart_max3110 *max = spi_get_drvdata(spi);
max3110_out(max, max->cur_conf);
@ -763,9 +765,13 @@ static int serial_m3110_resume(struct spi_device *spi)
enable_irq(max->irq);
return 0;
}
static SIMPLE_DEV_PM_OPS(serial_m3110_pm_ops, serial_m3110_suspend,
serial_m3110_resume);
#define SERIAL_M3110_PM_OPS (&serial_m3110_pm_ops)
#else
#define serial_m3110_suspend NULL
#define serial_m3110_resume NULL
#define SERIAL_M3110_PM_OPS NULL
#endif
static int serial_m3110_probe(struct spi_device *spi)
@ -872,11 +878,10 @@ static struct spi_driver uart_max3110_driver = {
.driver = {
.name = "spi_max3111",
.owner = THIS_MODULE,
.pm = SERIAL_M3110_PM_OPS,
},
.probe = serial_m3110_probe,
.remove = serial_m3110_remove,
.suspend = serial_m3110_suspend,
.resume = serial_m3110_resume,
};
static int __init serial_m3110_init(void)

View file

@ -907,7 +907,6 @@ static void msm_hs_dmov_rx_callback(struct msm_dmov_cmd *cmd_ptr,
unsigned int error_f = 0;
unsigned long flags;
unsigned int flush;
struct tty_struct *tty;
struct tty_port *port;
struct uart_port *uport;
struct msm_hs_port *msm_uport;
@ -919,7 +918,6 @@ static void msm_hs_dmov_rx_callback(struct msm_dmov_cmd *cmd_ptr,
clk_enable(msm_uport->clk);
port = &uport->state->port;
tty = port->tty;
msm_hs_write(uport, UARTDM_CR_ADDR, STALE_EVENT_DISABLE);

View file

@ -90,13 +90,13 @@ static void smd_tty_notify(void *priv, unsigned event)
static int smd_tty_port_activate(struct tty_port *tport, struct tty_struct *tty)
{
struct smd_tty_info *info = container_of(tport, struct smd_tty_info,
port);
int i, res = 0;
int n = tty->index;
const char *name = NULL;
struct smd_tty_info *info = smd_tty + n;
for (i = 0; i < smd_tty_channels_len; i++) {
if (smd_tty_channels[i].id == n) {
if (smd_tty_channels[i].id == tty->index) {
name = smd_tty_channels[i].name;
break;
}
@ -117,17 +117,13 @@ static int smd_tty_port_activate(struct tty_port *tport, struct tty_struct *tty)
static void smd_tty_port_shutdown(struct tty_port *tport)
{
struct smd_tty_info *info;
struct tty_struct *tty = tty_port_tty_get(tport);
struct smd_tty_info *info = container_of(tport, struct smd_tty_info,
port);
info = tty->driver_data;
if (info->ch) {
smd_close(info->ch);
info->ch = 0;
}
tty->driver_data = 0;
tty_kref_put(tty);
}
static int smd_tty_open(struct tty_struct *tty, struct file *f)

View file

@ -35,7 +35,7 @@
#include <linux/pinctrl/consumer.h>
#include <linux/of_device.h>
#include <linux/dma-mapping.h>
#include <linux/fsl/mxs-dma.h>
#include <linux/dmaengine.h>
#include <asm/cacheflush.h>
@ -148,11 +148,6 @@ struct mxs_auart_port {
struct device *dev;
/* for DMA */
struct mxs_dma_data dma_data;
int dma_channel_rx, dma_channel_tx;
int dma_irq_rx, dma_irq_tx;
int dma_channel;
struct scatterlist tx_sgl;
struct dma_chan *tx_dma_chan;
void *tx_dma_buf;
@ -440,20 +435,6 @@ static u32 mxs_auart_get_mctrl(struct uart_port *u)
return mctrl;
}
static bool mxs_auart_dma_filter(struct dma_chan *chan, void *param)
{
struct mxs_auart_port *s = param;
if (!mxs_dma_is_apbx(chan))
return false;
if (s->dma_channel == chan->chan_id) {
chan->private = &s->dma_data;
return true;
}
return false;
}
static int mxs_auart_dma_prep_rx(struct mxs_auart_port *s);
static void dma_rx_callback(void *arg)
{
@ -545,21 +526,11 @@ static void mxs_auart_dma_exit(struct mxs_auart_port *s)
static int mxs_auart_dma_init(struct mxs_auart_port *s)
{
dma_cap_mask_t mask;
if (auart_dma_enabled(s))
return 0;
/* We do not get the right DMA channels. */
if (s->dma_channel_rx == -1 || s->dma_channel_tx == -1)
return -EINVAL;
/* init for RX */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
s->dma_channel = s->dma_channel_rx;
s->dma_data.chan_irq = s->dma_irq_rx;
s->rx_dma_chan = dma_request_channel(mask, mxs_auart_dma_filter, s);
s->rx_dma_chan = dma_request_slave_channel(s->dev, "rx");
if (!s->rx_dma_chan)
goto err_out;
s->rx_dma_buf = kzalloc(UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
@ -567,9 +538,7 @@ static int mxs_auart_dma_init(struct mxs_auart_port *s)
goto err_out;
/* init for TX */
s->dma_channel = s->dma_channel_tx;
s->dma_data.chan_irq = s->dma_irq_tx;
s->tx_dma_chan = dma_request_channel(mask, mxs_auart_dma_filter, s);
s->tx_dma_chan = dma_request_slave_channel(s->dev, "tx");
if (!s->tx_dma_chan)
goto err_out;
s->tx_dma_buf = kzalloc(UART_XMIT_SIZE, GFP_KERNEL | GFP_DMA);
@ -883,7 +852,7 @@ auart_console_write(struct console *co, const char *str, unsigned int count)
unsigned int old_ctrl0, old_ctrl2;
unsigned int to = 1000;
if (co->index > MXS_AUART_PORTS || co->index < 0)
if (co->index >= MXS_AUART_PORTS || co->index < 0)
return;
s = auart_port[co->index];
@ -1020,7 +989,6 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
u32 dma_channel[2];
int ret;
if (!np)
@ -1034,20 +1002,8 @@ static int serial_mxs_probe_dt(struct mxs_auart_port *s,
}
s->port.line = ret;
s->dma_irq_rx = platform_get_irq(pdev, 1);
s->dma_irq_tx = platform_get_irq(pdev, 2);
s->flags |= MXS_AUART_DMA_CONFIG;
ret = of_property_read_u32_array(np, "fsl,auart-dma-channel",
dma_channel, 2);
if (ret == 0) {
s->dma_channel_rx = dma_channel[0];
s->dma_channel_tx = dma_channel[1];
s->flags |= MXS_AUART_DMA_CONFIG;
} else {
s->dma_channel_rx = -1;
s->dma_channel_tx = -1;
}
return 0;
}
@ -1103,7 +1059,7 @@ static int mxs_auart_probe(struct platform_device *pdev)
s->port.fifosize = 16;
s->port.uartclk = clk_get_rate(s->clk);
s->port.type = PORT_IMX;
s->port.dev = s->dev = get_device(&pdev->dev);
s->port.dev = s->dev = &pdev->dev;
s->ctrl = 0;
@ -1134,7 +1090,6 @@ out_free_irq:
auart_port[pdev->id] = NULL;
free_irq(s->irq, s);
out_free_clk:
put_device(s->dev);
clk_put(s->clk);
out_free:
kfree(s);
@ -1150,7 +1105,6 @@ static int mxs_auart_remove(struct platform_device *pdev)
auart_port[pdev->id] = NULL;
put_device(s->dev);
clk_put(s->clk);
free_irq(s->irq, s);
kfree(s);

View file

@ -199,7 +199,7 @@ static void nwpserial_shutdown(struct uart_port *port)
dcr_write(up->dcr_host, UART_IER, up->ier);
/* free irq */
free_irq(up->port.irq, port);
free_irq(up->port.irq, up);
}
static int nwpserial_verify_port(struct uart_port *port,

View file

@ -14,7 +14,6 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
@ -22,6 +21,8 @@
#include <linux/nwpserial.h>
#include <linux/clk.h>
#include "8250/8250.h"
struct of_serial_info {
struct clk *clk;
int type;
@ -97,6 +98,10 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
if (of_property_read_u32(np, "reg-shift", &prop) == 0)
port->regshift = prop;
/* Check for fifo size */
if (of_property_read_u32(np, "fifo-size", &prop) == 0)
port->fifosize = prop;
port->irq = irq_of_parse_and_map(np, 0);
port->iotype = UPIO_MEM;
if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
@ -167,11 +172,17 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
#ifdef CONFIG_SERIAL_8250
case PORT_8250 ... PORT_MAX_8250:
{
/* For now the of bindings don't support the extra
8250 specific bits */
struct uart_8250_port port8250;
memset(&port8250, 0, sizeof(port8250));
port8250.port = port;
if (port.fifosize)
port8250.capabilities = UART_CAP_FIFO;
if (of_property_read_bool(ofdev->dev.of_node,
"auto-flow-control"))
port8250.capabilities |= UART_CAP_AFE;
ret = serial8250_register_8250_port(&port8250);
break;
}

View file

@ -202,26 +202,6 @@ static int serial_omap_get_context_loss_count(struct uart_omap_port *up)
return pdata->get_context_loss_count(up->dev);
}
static void serial_omap_set_forceidle(struct uart_omap_port *up)
{
struct omap_uart_port_info *pdata = up->dev->platform_data;
if (!pdata || !pdata->set_forceidle)
return;
pdata->set_forceidle(up->dev);
}
static void serial_omap_set_noidle(struct uart_omap_port *up)
{
struct omap_uart_port_info *pdata = up->dev->platform_data;
if (!pdata || !pdata->set_noidle)
return;
pdata->set_noidle(up->dev);
}
static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable)
{
struct omap_uart_port_info *pdata = up->dev->platform_data;
@ -298,8 +278,6 @@ static void serial_omap_stop_tx(struct uart_port *port)
serial_out(up, UART_IER, up->ier);
}
serial_omap_set_forceidle(up);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
@ -364,7 +342,6 @@ static void serial_omap_start_tx(struct uart_port *port)
pm_runtime_get_sync(up->dev);
serial_omap_enable_ier_thri(up);
serial_omap_set_noidle(up);
pm_runtime_mark_last_busy(up->dev);
pm_runtime_put_autosuspend(up->dev);
}
@ -886,6 +863,17 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
/* FIFO ENABLE, DMA MODE */
up->scr |= OMAP_UART_SCR_RX_TRIG_GRANU1_MASK;
/*
* NOTE: Setting OMAP_UART_SCR_RX_TRIG_GRANU1_MASK
* sets Enables the granularity of 1 for TRIGGER RX
* level. Along with setting RX FIFO trigger level
* to 1 (as noted below, 16 characters) and TLR[3:0]
* to zero this will result RX FIFO threshold level
* to 1 character, instead of 16 as noted in comment
* below.
*/
/* Set receive FIFO threshold to 16 characters and
* transmit FIFO threshold to 16 spaces
*/

View file

@ -1493,29 +1493,6 @@ static int pch_uart_verify_port(struct uart_port *port,
return 0;
}
static struct uart_ops pch_uart_ops = {
.tx_empty = pch_uart_tx_empty,
.set_mctrl = pch_uart_set_mctrl,
.get_mctrl = pch_uart_get_mctrl,
.stop_tx = pch_uart_stop_tx,
.start_tx = pch_uart_start_tx,
.stop_rx = pch_uart_stop_rx,
.enable_ms = pch_uart_enable_ms,
.break_ctl = pch_uart_break_ctl,
.startup = pch_uart_startup,
.shutdown = pch_uart_shutdown,
.set_termios = pch_uart_set_termios,
/* .pm = pch_uart_pm, Not supported yet */
/* .set_wake = pch_uart_set_wake, Not supported yet */
.type = pch_uart_type,
.release_port = pch_uart_release_port,
.request_port = pch_uart_request_port,
.config_port = pch_uart_config_port,
.verify_port = pch_uart_verify_port
};
#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE
/*
* Wait for transmitter & holding register to empty
*/
@ -1547,6 +1524,84 @@ static void wait_for_xmitr(struct eg20t_port *up, int bits)
}
}
#ifdef CONFIG_CONSOLE_POLL
/*
* Console polling routines for communicate via uart while
* in an interrupt or debug context.
*/
static int pch_uart_get_poll_char(struct uart_port *port)
{
struct eg20t_port *priv =
container_of(port, struct eg20t_port, port);
u8 lsr = ioread8(priv->membase + UART_LSR);
if (!(lsr & UART_LSR_DR))
return NO_POLL_CHAR;
return ioread8(priv->membase + PCH_UART_RBR);
}
static void pch_uart_put_poll_char(struct uart_port *port,
unsigned char c)
{
unsigned int ier;
struct eg20t_port *priv =
container_of(port, struct eg20t_port, port);
/*
* First save the IER then disable the interrupts
*/
ier = ioread8(priv->membase + UART_IER);
pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_ALL_INT);
wait_for_xmitr(priv, UART_LSR_THRE);
/*
* Send the character out.
* If a LF, also do CR...
*/
iowrite8(c, priv->membase + PCH_UART_THR);
if (c == 10) {
wait_for_xmitr(priv, UART_LSR_THRE);
iowrite8(13, priv->membase + PCH_UART_THR);
}
/*
* Finally, wait for transmitter to become empty
* and restore the IER
*/
wait_for_xmitr(priv, BOTH_EMPTY);
iowrite8(ier, priv->membase + UART_IER);
}
#endif /* CONFIG_CONSOLE_POLL */
static struct uart_ops pch_uart_ops = {
.tx_empty = pch_uart_tx_empty,
.set_mctrl = pch_uart_set_mctrl,
.get_mctrl = pch_uart_get_mctrl,
.stop_tx = pch_uart_stop_tx,
.start_tx = pch_uart_start_tx,
.stop_rx = pch_uart_stop_rx,
.enable_ms = pch_uart_enable_ms,
.break_ctl = pch_uart_break_ctl,
.startup = pch_uart_startup,
.shutdown = pch_uart_shutdown,
.set_termios = pch_uart_set_termios,
/* .pm = pch_uart_pm, Not supported yet */
/* .set_wake = pch_uart_set_wake, Not supported yet */
.type = pch_uart_type,
.release_port = pch_uart_release_port,
.request_port = pch_uart_request_port,
.config_port = pch_uart_config_port,
.verify_port = pch_uart_verify_port,
#ifdef CONFIG_CONSOLE_POLL
.poll_get_char = pch_uart_get_poll_char,
.poll_put_char = pch_uart_put_poll_char,
#endif
};
#ifdef CONFIG_SERIAL_PCH_UART_CONSOLE
static void pch_console_putchar(struct uart_port *port, int ch)
{
struct eg20t_port *priv =
@ -1655,7 +1710,7 @@ static struct console pch_console = {
#define PCH_CONSOLE (&pch_console)
#else
#define PCH_CONSOLE NULL
#endif
#endif /* CONFIG_SERIAL_PCH_UART_CONSOLE */
static struct uart_driver pch_uart_driver = {
.owner = THIS_MODULE,

View file

@ -39,6 +39,7 @@
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
#include <linux/serial.h>
#include <linux/serial_s3c.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
@ -46,10 +47,9 @@
#include <asm/irq.h>
#include <mach/hardware.h>
#include <plat/regs-serial.h>
#ifdef CONFIG_SAMSUNG_CLOCK
#include <plat/clock.h>
#endif
#include "samsung.h"
@ -446,6 +446,8 @@ static void s3c24xx_serial_shutdown(struct uart_port *port)
/* Clear pending interrupts and mask all interrupts */
if (s3c24xx_serial_has_interrupt_mask(port)) {
free_irq(port->irq, ourport);
wr_regl(port, S3C64XX_UINTP, 0xf);
wr_regl(port, S3C64XX_UINTM, 0xf);
}
@ -505,6 +507,8 @@ static int s3c64xx_serial_startup(struct uart_port *port)
dbg("s3c64xx_serial_startup: port=%p (%08lx,%p)\n",
port->mapbase, port->membase);
wr_regl(port, S3C64XX_UINTM, 0xf);
ret = request_irq(port->irq, s3c64xx_serial_handle_irq, IRQF_SHARED,
s3c24xx_serial_portname(port), ourport);
if (ret) {
@ -894,7 +898,7 @@ console_initcall(s3c24xx_serial_console_init);
#define S3C24XX_SERIAL_CONSOLE NULL
#endif
#ifdef CONFIG_CONSOLE_POLL
#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
static int s3c24xx_serial_get_poll_char(struct uart_port *port);
static void s3c24xx_serial_put_poll_char(struct uart_port *port,
unsigned char c);
@ -918,7 +922,7 @@ static struct uart_ops s3c24xx_serial_ops = {
.request_port = s3c24xx_serial_request_port,
.config_port = s3c24xx_serial_config_port,
.verify_port = s3c24xx_serial_verify_port,
#ifdef CONFIG_CONSOLE_POLL
#if defined(CONFIG_SERIAL_SAMSUNG_CONSOLE) && defined(CONFIG_CONSOLE_POLL)
.poll_get_char = s3c24xx_serial_get_poll_char,
.poll_put_char = s3c24xx_serial_put_poll_char,
#endif
@ -1162,6 +1166,18 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
ourport->tx_irq = ret;
ourport->clk = clk_get(&platdev->dev, "uart");
if (IS_ERR(ourport->clk)) {
pr_err("%s: Controller clock not found\n",
dev_name(&platdev->dev));
return PTR_ERR(ourport->clk);
}
ret = clk_prepare_enable(ourport->clk);
if (ret) {
pr_err("uart: clock failed to prepare+enable: %d\n", ret);
clk_put(ourport->clk);
return ret;
}
/* Keep all interrupts masked and cleared */
if (s3c24xx_serial_has_interrupt_mask(port)) {
@ -1176,9 +1192,11 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
/* reset the fifos (and setup the uart) */
s3c24xx_serial_resetport(port, cfg);
clk_disable_unprepare(ourport->clk);
return 0;
}
#ifdef CONFIG_SAMSUNG_CLOCK
static ssize_t s3c24xx_serial_show_clksrc(struct device *dev,
struct device_attribute *attr,
char *buf)
@ -1194,7 +1212,7 @@ static ssize_t s3c24xx_serial_show_clksrc(struct device *dev,
}
static DEVICE_ATTR(clock_source, S_IRUGO, s3c24xx_serial_show_clksrc, NULL);
#endif
/* Device driver serial port probe */
@ -1252,9 +1270,11 @@ static int s3c24xx_serial_probe(struct platform_device *pdev)
uart_add_one_port(&s3c24xx_uart_drv, &ourport->port);
platform_set_drvdata(pdev, &ourport->port);
#ifdef CONFIG_SAMSUNG_CLOCK
ret = device_create_file(&pdev->dev, &dev_attr_clock_source);
if (ret < 0)
dev_err(&pdev->dev, "failed to add clock source attr.\n");
#endif
ret = s3c24xx_serial_cpufreq_register(ourport);
if (ret < 0)
@ -1272,7 +1292,9 @@ static int s3c24xx_serial_remove(struct platform_device *dev)
if (port) {
s3c24xx_serial_cpufreq_deregister(to_ourport(port));
#ifdef CONFIG_SAMSUNG_CLOCK
device_remove_file(&dev->dev, &dev_attr_clock_source);
#endif
uart_remove_one_port(&s3c24xx_uart_drv, port);
}
@ -1307,9 +1329,29 @@ static int s3c24xx_serial_resume(struct device *dev)
return 0;
}
static int s3c24xx_serial_resume_noirq(struct device *dev)
{
struct uart_port *port = s3c24xx_dev_to_port(dev);
if (port) {
/* restore IRQ mask */
if (s3c24xx_serial_has_interrupt_mask(port)) {
unsigned int uintm = 0xf;
if (tx_enabled(port))
uintm &= ~S3C64XX_UINTM_TXD_MSK;
if (rx_enabled(port))
uintm &= ~S3C64XX_UINTM_RXD_MSK;
wr_regl(port, S3C64XX_UINTM, uintm);
}
}
return 0;
}
static const struct dev_pm_ops s3c24xx_serial_pm_ops = {
.suspend = s3c24xx_serial_suspend,
.resume = s3c24xx_serial_resume,
.resume_noirq = s3c24xx_serial_resume_noirq,
};
#define SERIAL_SAMSUNG_PM_OPS (&s3c24xx_serial_pm_ops)
@ -1343,6 +1385,13 @@ s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0;
}
static bool
s3c24xx_port_configured(unsigned int ucon)
{
/* consider the serial port configured if the tx/rx mode set */
return (ucon & 0xf) != 0;
}
#ifdef CONFIG_CONSOLE_POLL
/*
* Console polling routines for writing and reading from the uart while
@ -1365,6 +1414,11 @@ static void s3c24xx_serial_put_poll_char(struct uart_port *port,
unsigned char c)
{
unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
/* not possible to xmit on unconfigured port */
if (!s3c24xx_port_configured(ucon))
return;
while (!s3c24xx_serial_console_txrdy(port, ufcon))
cpu_relax();
@ -1377,6 +1431,12 @@ static void
s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
{
unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
unsigned int ucon = rd_regl(cons_uart, S3C2410_UCON);
/* not possible to xmit on unconfigured port */
if (!s3c24xx_port_configured(ucon))
return;
while (!s3c24xx_serial_console_txrdy(port, ufcon))
barrier();
wr_regb(cons_uart, S3C2410_UTXH, ch);
@ -1409,9 +1469,7 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud,
"registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n",
port, ulcon, ucon, ubrdiv);
if ((ucon & 0xf) != 0) {
/* consider the serial port configured if the tx/rx mode set */
if (s3c24xx_port_configured(ucon)) {
switch (ulcon & S3C2410_LCON_CSMASK) {
case S3C2410_LCON_CS5:
*bits = 5;
@ -1758,6 +1816,7 @@ static int __init s3c24xx_serial_modinit(void)
static void __exit s3c24xx_serial_modexit(void)
{
platform_driver_unregister(&samsung_serial_driver);
uart_unregister_driver(&s3c24xx_uart_drv);
}

View file

@ -76,7 +76,9 @@ struct s3c24xx_uart_port {
#define wr_regb(port, reg, val) __raw_writeb(val, portaddr(port, reg))
#define wr_regl(port, reg, val) __raw_writel(val, portaddr(port, reg))
#ifdef CONFIG_SERIAL_SAMSUNG_DEBUG
#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \
defined(CONFIG_DEBUG_LL) && \
!defined(MODULE)
extern void printascii(const char *);

View file

@ -27,6 +27,7 @@
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/platform_data/serial-sccnxp.h>
#include <linux/regulator/consumer.h>
#define SCCNXP_NAME "uart-sccnxp"
#define SCCNXP_MAJOR 204
@ -131,6 +132,8 @@ struct sccnxp_port {
struct timer_list timer;
struct sccnxp_pdata pdata;
struct regulator *regulator;
};
static inline u8 sccnxp_raw_read(void __iomem *base, u8 reg, u8 shift)
@ -789,8 +792,6 @@ static int sccnxp_probe(struct platform_device *pdev)
return -EADDRNOTAVAIL;
}
dev_set_name(&pdev->dev, SCCNXP_NAME);
s = devm_kzalloc(&pdev->dev, sizeof(struct sccnxp_port), GFP_KERNEL);
if (!s) {
dev_err(&pdev->dev, "Error allocating port structure\n");
@ -918,6 +919,16 @@ static int sccnxp_probe(struct platform_device *pdev)
goto err_out;
}
s->regulator = devm_regulator_get(&pdev->dev, "VCC");
if (!IS_ERR(s->regulator)) {
ret = regulator_enable(s->regulator);
if (ret) {
dev_err(&pdev->dev,
"Failed to enable regulator: %i\n", ret);
return ret;
}
}
membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(membase)) {
ret = PTR_ERR(membase);
@ -967,10 +978,6 @@ static int sccnxp_probe(struct platform_device *pdev)
s->imr = 0;
sccnxp_write(&s->port[0], SCCNXP_IMR_REG, 0);
/* Board specific configure */
if (s->pdata.init)
s->pdata.init();
if (!s->poll) {
ret = devm_request_threaded_irq(&pdev->dev, s->irq, NULL,
sccnxp_ist,
@ -1011,8 +1018,8 @@ static int sccnxp_remove(struct platform_device *pdev)
uart_unregister_driver(&s->uart);
platform_set_drvdata(pdev, NULL);
if (s->pdata.exit)
s->pdata.exit();
if (!IS_ERR(s->regulator))
return regulator_disable(s->regulator);
return 0;
}

View file

@ -26,6 +26,7 @@
#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/dmapool.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/module.h>
@ -1301,11 +1302,9 @@ static int tegra_uart_probe(struct platform_device *pdev)
}
u->mapbase = resource->start;
u->membase = devm_request_and_ioremap(&pdev->dev, resource);
if (!u->membase) {
dev_err(&pdev->dev, "memregion/iomap address req failed\n");
return -EADDRNOTAVAIL;
}
u->membase = devm_ioremap_resource(&pdev->dev, resource);
if (IS_ERR(u->membase))
return PTR_ERR(u->membase);
tup->uart_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(tup->uart_clk)) {

View file

@ -1711,7 +1711,7 @@ static int uart_proc_show(struct seq_file *m, void *v)
static int uart_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, uart_proc_show, PDE(inode)->data);
return single_open(file, uart_proc_show, PDE_DATA(inode));
}
static const struct file_operations uart_proc_fops = {
@ -1941,6 +1941,8 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
mutex_unlock(&port->mutex);
return 0;
}
put_device(tty_dev);
if (console_suspend_enabled || !uart_console(uport))
uport->suspended = 1;
@ -2006,9 +2008,11 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
disable_irq_wake(uport->irq);
uport->irq_wake = 0;
}
put_device(tty_dev);
mutex_unlock(&port->mutex);
return 0;
}
put_device(tty_dev);
uport->suspended = 0;
/*

View file

@ -15,8 +15,6 @@
defined(CONFIG_CPU_SUBTYPE_SH7720) || \
defined(CONFIG_CPU_SUBTYPE_SH7721) || \
defined(CONFIG_ARCH_SH73A0) || \
defined(CONFIG_ARCH_SH7367) || \
defined(CONFIG_ARCH_SH7377) || \
defined(CONFIG_ARCH_SH7372) || \
defined(CONFIG_ARCH_R8A7740)

View file

@ -758,7 +758,7 @@ static struct of_device_id sirfsoc_uart_ids[] = {
{ .compatible = "sirf,marco-uart", },
{}
};
MODULE_DEVICE_TABLE(of, sirfsoc_serial_of_match);
MODULE_DEVICE_TABLE(of, sirfsoc_uart_ids);
static struct platform_driver sirfsoc_uart_driver = {
.probe = sirfsoc_uart_probe,

View file

@ -203,7 +203,7 @@ receive_chars(struct uart_sunsab_port *up,
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch))
if (uart_handle_sysrq_char(&up->port, ch) || !port)
continue;
if ((stat->sreg.isr0 & (up->port.ignore_status_mask & 0xff)) == 0 &&

View file

@ -968,6 +968,7 @@ static struct uart_ops sunsu_pops = {
#define UART_NR 4
static struct uart_sunsu_port sunsu_ports[UART_NR];
static int nr_inst; /* Number of already registered ports */
#ifdef CONFIG_SERIO
@ -1337,13 +1338,8 @@ static int __init sunsu_console_setup(struct console *co, char *options)
printk("Console: ttyS%d (SU)\n",
(sunsu_reg.minor - 64) + co->index);
/*
* Check whether an invalid uart number has been specified, and
* if so, search for the first available port that does have
* console support.
*/
if (co->index >= UART_NR)
co->index = 0;
if (co->index > nr_inst)
return -ENODEV;
port = &sunsu_ports[co->index].port;
/*
@ -1408,7 +1404,6 @@ static enum su_type su_get_type(struct device_node *dp)
static int su_probe(struct platform_device *op)
{
static int inst;
struct device_node *dp = op->dev.of_node;
struct uart_sunsu_port *up;
struct resource *rp;
@ -1418,16 +1413,16 @@ static int su_probe(struct platform_device *op)
type = su_get_type(dp);
if (type == SU_PORT_PORT) {
if (inst >= UART_NR)
if (nr_inst >= UART_NR)
return -EINVAL;
up = &sunsu_ports[inst];
up = &sunsu_ports[nr_inst];
} else {
up = kzalloc(sizeof(*up), GFP_KERNEL);
if (!up)
return -ENOMEM;
}
up->port.line = inst;
up->port.line = nr_inst;
spin_lock_init(&up->port.lock);
@ -1461,6 +1456,8 @@ static int su_probe(struct platform_device *op)
}
dev_set_drvdata(&op->dev, up);
nr_inst++;
return 0;
}
@ -1488,7 +1485,7 @@ static int su_probe(struct platform_device *op)
dev_set_drvdata(&op->dev, up);
inst++;
nr_inst++;
return 0;
@ -1595,6 +1592,7 @@ static int __init sunsu_init(void)
static void __exit sunsu_exit(void)
{
platform_driver_unregister(&su_driver);
if (sunsu_reg.nr)
sunserial_unregister_minors(&sunsu_reg, sunsu_reg.nr);
}

View file

@ -388,7 +388,7 @@ sunzilog_receive_chars(struct uart_sunzilog_port *up,
else if (r1 & CRC_ERR)
flag = TTY_FRAME;
}
if (uart_handle_sysrq_char(&up->port, ch))
if (uart_handle_sysrq_char(&up->port, ch) || !port)
continue;
if (up->port.ignore_status_mask == 0xff ||

View file

@ -35,6 +35,7 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/err.h>
/*
* UART Register offsets
@ -585,9 +586,9 @@ static int vt8500_serial_probe(struct platform_device *pdev)
if (!vt8500_port)
return -ENOMEM;
vt8500_port->uart.membase = devm_request_and_ioremap(&pdev->dev, mmres);
if (!vt8500_port->uart.membase)
return -EADDRNOTAVAIL;
vt8500_port->uart.membase = devm_ioremap_resource(&pdev->dev, mmres);
if (IS_ERR(vt8500_port->uart.membase))
return PTR_ERR(vt8500_port->uart.membase);
vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0);
if (IS_ERR(vt8500_port->clk)) {

View file

@ -578,14 +578,13 @@ static int xuartps_startup(struct uart_port *port)
/* Receive Timeout register is enabled with value of 10 */
xuartps_writel(10, XUARTPS_RXTOUT_OFFSET);
/* Clear out any pending interrupts before enabling them */
xuartps_writel(xuartps_readl(XUARTPS_ISR_OFFSET), XUARTPS_ISR_OFFSET);
/* Set the Interrupt Registers with desired interrupts */
xuartps_writel(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY |
XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN |
XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT, XUARTPS_IER_OFFSET);
xuartps_writel(~(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY |
XUARTPS_IXR_FRAMING | XUARTPS_IXR_OVERRUN |
XUARTPS_IXR_RXTRIG | XUARTPS_IXR_TOUT), XUARTPS_IDR_OFFSET);
return retval;
}

View file

@ -1058,9 +1058,6 @@ static void mgsl_bh_handler(struct work_struct *work)
container_of(work, struct mgsl_struct, task);
int action;
if (!info)
return;
if ( debug_level >= DEBUG_LEVEL_BH )
printk( "%s(%d):mgsl_bh_handler(%s) entry\n",
__FILE__,__LINE__,info->device_name);
@ -3311,7 +3308,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
port->blocked_open++;
while (1) {
if (tty->termios.c_cflag & CBAUD)
if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))
tty_port_raise_dtr_rts(port);
set_current_state(TASK_INTERRUPTIBLE);

View file

@ -3308,7 +3308,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
port->blocked_open++;
while (1) {
if ((tty->termios.c_cflag & CBAUD))
if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))
tty_port_raise_dtr_rts(port);
set_current_state(TASK_INTERRUPTIBLE);

View file

@ -3329,7 +3329,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
port->blocked_open++;
while (1) {
if (tty->termios.c_cflag & CBAUD)
if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))
tty_port_raise_dtr_rts(port);
set_current_state(TASK_INTERRUPTIBLE);

View file

@ -106,7 +106,7 @@ static void sysrq_handle_SAK(int key)
}
static struct sysrq_key_op sysrq_SAK_op = {
.handler = sysrq_handle_SAK,
.help_msg = "saK",
.help_msg = "sak(k)",
.action_msg = "SAK",
.enable_mask = SYSRQ_ENABLE_KEYBOARD,
};
@ -122,7 +122,7 @@ static void sysrq_handle_unraw(int key)
static struct sysrq_key_op sysrq_unraw_op = {
.handler = sysrq_handle_unraw,
.help_msg = "unRaw",
.help_msg = "unraw(r)",
.action_msg = "Keyboard mode set to system default",
.enable_mask = SYSRQ_ENABLE_KEYBOARD,
};
@ -140,7 +140,7 @@ static void sysrq_handle_crash(int key)
}
static struct sysrq_key_op sysrq_crash_op = {
.handler = sysrq_handle_crash,
.help_msg = "Crash",
.help_msg = "crash(c)",
.action_msg = "Trigger a crash",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
@ -153,7 +153,7 @@ static void sysrq_handle_reboot(int key)
}
static struct sysrq_key_op sysrq_reboot_op = {
.handler = sysrq_handle_reboot,
.help_msg = "reBoot",
.help_msg = "reboot(b)",
.action_msg = "Resetting",
.enable_mask = SYSRQ_ENABLE_BOOT,
};
@ -164,7 +164,7 @@ static void sysrq_handle_sync(int key)
}
static struct sysrq_key_op sysrq_sync_op = {
.handler = sysrq_handle_sync,
.help_msg = "Sync",
.help_msg = "sync(s)",
.action_msg = "Emergency Sync",
.enable_mask = SYSRQ_ENABLE_SYNC,
};
@ -176,7 +176,7 @@ static void sysrq_handle_show_timers(int key)
static struct sysrq_key_op sysrq_show_timers_op = {
.handler = sysrq_handle_show_timers,
.help_msg = "show-all-timers(Q)",
.help_msg = "show-all-timers(q)",
.action_msg = "Show clockevent devices & pending hrtimers (no others)",
};
@ -186,7 +186,7 @@ static void sysrq_handle_mountro(int key)
}
static struct sysrq_key_op sysrq_mountro_op = {
.handler = sysrq_handle_mountro,
.help_msg = "Unmount",
.help_msg = "unmount(u)",
.action_msg = "Emergency Remount R/O",
.enable_mask = SYSRQ_ENABLE_REMOUNT,
};
@ -199,7 +199,7 @@ static void sysrq_handle_showlocks(int key)
static struct sysrq_key_op sysrq_showlocks_op = {
.handler = sysrq_handle_showlocks,
.help_msg = "show-all-locks(D)",
.help_msg = "show-all-locks(d)",
.action_msg = "Show Locks Held",
};
#else
@ -250,7 +250,7 @@ static void sysrq_handle_showallcpus(int key)
static struct sysrq_key_op sysrq_showallcpus_op = {
.handler = sysrq_handle_showallcpus,
.help_msg = "show-backtrace-all-active-cpus(L)",
.help_msg = "show-backtrace-all-active-cpus(l)",
.action_msg = "Show backtrace of all active CPUs",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
@ -265,7 +265,7 @@ static void sysrq_handle_showregs(int key)
}
static struct sysrq_key_op sysrq_showregs_op = {
.handler = sysrq_handle_showregs,
.help_msg = "show-registers(P)",
.help_msg = "show-registers(p)",
.action_msg = "Show Regs",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
@ -276,7 +276,7 @@ static void sysrq_handle_showstate(int key)
}
static struct sysrq_key_op sysrq_showstate_op = {
.handler = sysrq_handle_showstate,
.help_msg = "show-task-states(T)",
.help_msg = "show-task-states(t)",
.action_msg = "Show State",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
@ -287,7 +287,7 @@ static void sysrq_handle_showstate_blocked(int key)
}
static struct sysrq_key_op sysrq_showstate_blocked_op = {
.handler = sysrq_handle_showstate_blocked,
.help_msg = "show-blocked-tasks(W)",
.help_msg = "show-blocked-tasks(w)",
.action_msg = "Show Blocked State",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
@ -301,7 +301,7 @@ static void sysrq_ftrace_dump(int key)
}
static struct sysrq_key_op sysrq_ftrace_dump_op = {
.handler = sysrq_ftrace_dump,
.help_msg = "dump-ftrace-buffer(Z)",
.help_msg = "dump-ftrace-buffer(z)",
.action_msg = "Dump ftrace buffer",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
@ -315,7 +315,7 @@ static void sysrq_handle_showmem(int key)
}
static struct sysrq_key_op sysrq_showmem_op = {
.handler = sysrq_handle_showmem,
.help_msg = "show-memory-usage(M)",
.help_msg = "show-memory-usage(m)",
.action_msg = "Show Memory",
.enable_mask = SYSRQ_ENABLE_DUMP,
};
@ -346,7 +346,7 @@ static void sysrq_handle_term(int key)
}
static struct sysrq_key_op sysrq_term_op = {
.handler = sysrq_handle_term,
.help_msg = "terminate-all-tasks(E)",
.help_msg = "terminate-all-tasks(e)",
.action_msg = "Terminate All Tasks",
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
@ -365,7 +365,7 @@ static void sysrq_handle_moom(int key)
}
static struct sysrq_key_op sysrq_moom_op = {
.handler = sysrq_handle_moom,
.help_msg = "memory-full-oom-kill(F)",
.help_msg = "memory-full-oom-kill(f)",
.action_msg = "Manual OOM execution",
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
@ -377,7 +377,7 @@ static void sysrq_handle_thaw(int key)
}
static struct sysrq_key_op sysrq_thaw_op = {
.handler = sysrq_handle_thaw,
.help_msg = "thaw-filesystems(J)",
.help_msg = "thaw-filesystems(j)",
.action_msg = "Emergency Thaw of all frozen filesystems",
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
@ -390,7 +390,7 @@ static void sysrq_handle_kill(int key)
}
static struct sysrq_key_op sysrq_kill_op = {
.handler = sysrq_handle_kill,
.help_msg = "kill-all-tasks(I)",
.help_msg = "kill-all-tasks(i)",
.action_msg = "Kill All Tasks",
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
@ -401,7 +401,7 @@ static void sysrq_handle_unrt(int key)
}
static struct sysrq_key_op sysrq_unrt_op = {
.handler = sysrq_handle_unrt,
.help_msg = "nice-all-RT-tasks(N)",
.help_msg = "nice-all-RT-tasks(n)",
.action_msg = "Nice All RT Tasks",
.enable_mask = SYSRQ_ENABLE_RTNICE,
};

View file

@ -60,24 +60,22 @@ static void tty_audit_buf_put(struct tty_audit_buf *buf)
tty_audit_buf_free(buf);
}
static void tty_audit_log(const char *description, struct task_struct *tsk,
kuid_t loginuid, unsigned sessionid, int major,
int minor, unsigned char *data, size_t size)
static void tty_audit_log(const char *description, int major, int minor,
unsigned char *data, size_t size)
{
struct audit_buffer *ab;
struct task_struct *tsk = current;
uid_t uid = from_kuid(&init_user_ns, task_uid(tsk));
uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk));
u32 sessionid = audit_get_sessionid(tsk);
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY);
if (ab) {
char name[sizeof(tsk->comm)];
kuid_t uid = task_uid(tsk);
audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u "
"major=%d minor=%d comm=", description,
tsk->pid,
from_kuid(&init_user_ns, uid),
from_kuid(&init_user_ns, loginuid),
sessionid,
major, minor);
audit_log_format(ab, "%s pid=%u uid=%u auid=%u ses=%u major=%d"
" minor=%d comm=", description, tsk->pid, uid,
loginuid, sessionid, major, minor);
get_task_comm(name, tsk);
audit_log_untrustedstring(ab, name);
audit_log_format(ab, " data=");
@ -90,11 +88,9 @@ static void tty_audit_log(const char *description, struct task_struct *tsk,
* tty_audit_buf_push - Push buffered data out
*
* Generate an audit message from the contents of @buf, which is owned by
* @tsk with @loginuid. @buf->mutex must be locked.
* the current task. @buf->mutex must be locked.
*/
static void tty_audit_buf_push(struct task_struct *tsk, kuid_t loginuid,
unsigned int sessionid,
struct tty_audit_buf *buf)
static void tty_audit_buf_push(struct tty_audit_buf *buf)
{
if (buf->valid == 0)
return;
@ -102,24 +98,10 @@ static void tty_audit_buf_push(struct task_struct *tsk, kuid_t loginuid,
buf->valid = 0;
return;
}
tty_audit_log("tty", tsk, loginuid, sessionid, buf->major, buf->minor,
buf->data, buf->valid);
tty_audit_log("tty", buf->major, buf->minor, buf->data, buf->valid);
buf->valid = 0;
}
/**
* tty_audit_buf_push_current - Push buffered data out
*
* Generate an audit message from the contents of @buf, which is owned by
* the current task. @buf->mutex must be locked.
*/
static void tty_audit_buf_push_current(struct tty_audit_buf *buf)
{
kuid_t auid = audit_get_loginuid(current);
unsigned int sessionid = audit_get_sessionid(current);
tty_audit_buf_push(current, auid, sessionid, buf);
}
/**
* tty_audit_exit - Handle a task exit
*
@ -130,15 +112,13 @@ void tty_audit_exit(void)
{
struct tty_audit_buf *buf;
spin_lock_irq(&current->sighand->siglock);
buf = current->signal->tty_audit_buf;
current->signal->tty_audit_buf = NULL;
spin_unlock_irq(&current->sighand->siglock);
if (!buf)
return;
mutex_lock(&buf->mutex);
tty_audit_buf_push_current(buf);
tty_audit_buf_push(buf);
mutex_unlock(&buf->mutex);
tty_audit_buf_put(buf);
@ -151,9 +131,8 @@ void tty_audit_exit(void)
*/
void tty_audit_fork(struct signal_struct *sig)
{
spin_lock_irq(&current->sighand->siglock);
sig->audit_tty = current->signal->audit_tty;
spin_unlock_irq(&current->sighand->siglock);
sig->audit_tty_log_passwd = current->signal->audit_tty_log_passwd;
}
/**
@ -163,20 +142,21 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch)
{
struct tty_audit_buf *buf;
int major, minor, should_audit;
unsigned long flags;
spin_lock_irq(&current->sighand->siglock);
spin_lock_irqsave(&current->sighand->siglock, flags);
should_audit = current->signal->audit_tty;
buf = current->signal->tty_audit_buf;
if (buf)
atomic_inc(&buf->count);
spin_unlock_irq(&current->sighand->siglock);
spin_unlock_irqrestore(&current->sighand->siglock, flags);
major = tty->driver->major;
minor = tty->driver->minor_start + tty->index;
if (buf) {
mutex_lock(&buf->mutex);
if (buf->major == major && buf->minor == minor)
tty_audit_buf_push_current(buf);
tty_audit_buf_push(buf);
mutex_unlock(&buf->mutex);
tty_audit_buf_put(buf);
}
@ -187,24 +167,20 @@ void tty_audit_tiocsti(struct tty_struct *tty, char ch)
auid = audit_get_loginuid(current);
sessionid = audit_get_sessionid(current);
tty_audit_log("ioctl=TIOCSTI", current, auid, sessionid, major,
minor, &ch, 1);
tty_audit_log("ioctl=TIOCSTI", major, minor, &ch, 1);
}
}
/**
* tty_audit_push_task - Flush task's pending audit data
* @tsk: task pointer
* @loginuid: sender login uid
* @sessionid: sender session id
* tty_audit_push_current - Flush current's pending audit data
*
* Called with a ref on @tsk held. Try to lock sighand and get a
* reference to the tty audit buffer if available.
* Try to lock sighand and get a reference to the tty audit buffer if available.
* Flush the buffer or return an appropriate error code.
*/
int tty_audit_push_task(struct task_struct *tsk, kuid_t loginuid, u32 sessionid)
int tty_audit_push_current(void)
{
struct tty_audit_buf *buf = ERR_PTR(-EPERM);
struct task_struct *tsk = current;
unsigned long flags;
if (!lock_task_sighand(tsk, &flags))
@ -225,7 +201,7 @@ int tty_audit_push_task(struct task_struct *tsk, kuid_t loginuid, u32 sessionid)
return PTR_ERR(buf);
mutex_lock(&buf->mutex);
tty_audit_buf_push(tsk, loginuid, sessionid, buf);
tty_audit_buf_push(buf);
mutex_unlock(&buf->mutex);
tty_audit_buf_put(buf);
@ -243,10 +219,11 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
unsigned icanon)
{
struct tty_audit_buf *buf, *buf2;
unsigned long flags;
buf = NULL;
buf2 = NULL;
spin_lock_irq(&current->sighand->siglock);
spin_lock_irqsave(&current->sighand->siglock, flags);
if (likely(!current->signal->audit_tty))
goto out;
buf = current->signal->tty_audit_buf;
@ -254,7 +231,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
atomic_inc(&buf->count);
goto out;
}
spin_unlock_irq(&current->sighand->siglock);
spin_unlock_irqrestore(&current->sighand->siglock, flags);
buf2 = tty_audit_buf_alloc(tty->driver->major,
tty->driver->minor_start + tty->index,
@ -264,7 +241,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
return NULL;
}
spin_lock_irq(&current->sighand->siglock);
spin_lock_irqsave(&current->sighand->siglock, flags);
if (!current->signal->audit_tty)
goto out;
buf = current->signal->tty_audit_buf;
@ -276,7 +253,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
atomic_inc(&buf->count);
/* Fall through */
out:
spin_unlock_irq(&current->sighand->siglock);
spin_unlock_irqrestore(&current->sighand->siglock, flags);
if (buf2)
tty_audit_buf_free(buf2);
return buf;
@ -292,10 +269,18 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
{
struct tty_audit_buf *buf;
int major, minor;
int audit_log_tty_passwd;
unsigned long flags;
if (unlikely(size == 0))
return;
spin_lock_irqsave(&current->sighand->siglock, flags);
audit_log_tty_passwd = current->signal->audit_tty_log_passwd;
spin_unlock_irqrestore(&current->sighand->siglock, flags);
if (!audit_log_tty_passwd && icanon && !L_ECHO(tty))
return;
if (tty->driver->type == TTY_DRIVER_TYPE_PTY
&& tty->driver->subtype == PTY_TYPE_MASTER)
return;
@ -309,7 +294,7 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
minor = tty->driver->minor_start + tty->index;
if (buf->major != major || buf->minor != minor
|| buf->icanon != icanon) {
tty_audit_buf_push_current(buf);
tty_audit_buf_push(buf);
buf->major = major;
buf->minor = minor;
buf->icanon = icanon;
@ -325,7 +310,7 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
data += run;
size -= run;
if (buf->valid == N_TTY_BUF_SIZE)
tty_audit_buf_push_current(buf);
tty_audit_buf_push(buf);
} while (size != 0);
mutex_unlock(&buf->mutex);
tty_audit_buf_put(buf);
@ -339,16 +324,17 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
void tty_audit_push(struct tty_struct *tty)
{
struct tty_audit_buf *buf;
unsigned long flags;
spin_lock_irq(&current->sighand->siglock);
spin_lock_irqsave(&current->sighand->siglock, flags);
if (likely(!current->signal->audit_tty)) {
spin_unlock_irq(&current->sighand->siglock);
spin_unlock_irqrestore(&current->sighand->siglock, flags);
return;
}
buf = current->signal->tty_audit_buf;
if (buf)
atomic_inc(&buf->count);
spin_unlock_irq(&current->sighand->siglock);
spin_unlock_irqrestore(&current->sighand->siglock, flags);
if (buf) {
int major, minor;
@ -357,7 +343,7 @@ void tty_audit_push(struct tty_struct *tty)
minor = tty->driver->minor_start + tty->index;
mutex_lock(&buf->mutex);
if (buf->major == major && buf->minor == minor)
tty_audit_buf_push_current(buf);
tty_audit_buf_push(buf);
mutex_unlock(&buf->mutex);
tty_audit_buf_put(buf);
}

View file

@ -449,11 +449,6 @@ static void flush_to_ldisc(struct work_struct *work)
tty_buffer_free(port, head);
continue;
}
/* Ldisc or user is trying to flush the buffers
we are feeding to the ldisc, stop feeding the
line discipline as we want to empty the queue */
if (test_bit(TTYP_FLUSHPENDING, &port->iflags))
break;
if (!tty->receive_room)
break;
if (count > tty->receive_room)
@ -465,17 +460,20 @@ static void flush_to_ldisc(struct work_struct *work)
disc->ops->receive_buf(tty, char_buf,
flag_buf, count);
spin_lock_irqsave(&buf->lock, flags);
/* 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;
}
}
clear_bit(TTYP_FLUSHING, &port->iflags);
}
/* 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);
}
spin_unlock_irqrestore(&buf->lock, flags);
tty_ldisc_deref(disc);

View file

@ -532,6 +532,60 @@ void tty_wakeup(struct tty_struct *tty)
EXPORT_SYMBOL_GPL(tty_wakeup);
/**
* tty_signal_session_leader - sends SIGHUP to session leader
* @tty controlling tty
* @exit_session if non-zero, signal all foreground group processes
*
* Send SIGHUP and SIGCONT to the session leader and its process group.
* Optionally, signal all processes in the foreground process group.
*
* Returns the number of processes in the session with this tty
* as their controlling terminal. This value is used to drop
* tty references for those processes.
*/
static int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
{
struct task_struct *p;
int refs = 0;
struct pid *tty_pgrp = NULL;
read_lock(&tasklist_lock);
if (tty->session) {
do_each_pid_task(tty->session, PIDTYPE_SID, p) {
spin_lock_irq(&p->sighand->siglock);
if (p->signal->tty == tty) {
p->signal->tty = NULL;
/* We defer the dereferences outside fo
the tasklist lock */
refs++;
}
if (!p->signal->leader) {
spin_unlock_irq(&p->sighand->siglock);
continue;
}
__group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
__group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
put_pid(p->signal->tty_old_pgrp); /* A noop */
spin_lock(&tty->ctrl_lock);
tty_pgrp = get_pid(tty->pgrp);
if (tty->pgrp)
p->signal->tty_old_pgrp = get_pid(tty->pgrp);
spin_unlock(&tty->ctrl_lock);
spin_unlock_irq(&p->sighand->siglock);
} while_each_pid_task(tty->session, PIDTYPE_SID, p);
}
read_unlock(&tasklist_lock);
if (tty_pgrp) {
if (exit_session)
kill_pgrp(tty_pgrp, SIGHUP, exit_session);
put_pid(tty_pgrp);
}
return refs;
}
/**
* __tty_hangup - actual handler for hangup events
* @work: tty device
@ -554,15 +608,13 @@ EXPORT_SYMBOL_GPL(tty_wakeup);
* tasklist_lock to walk task list for hangup event
* ->siglock to protect ->signal/->sighand
*/
static void __tty_hangup(struct tty_struct *tty)
static void __tty_hangup(struct tty_struct *tty, int exit_session)
{
struct file *cons_filp = NULL;
struct file *filp, *f = NULL;
struct task_struct *p;
struct tty_file_private *priv;
int closecount = 0, n;
unsigned long flags;
int refs = 0;
int refs;
if (!tty)
return;
@ -599,39 +651,18 @@ static void __tty_hangup(struct tty_struct *tty)
}
spin_unlock(&tty_files_lock);
refs = tty_signal_session_leader(tty, exit_session);
/* Account for the p->signal references we killed */
while (refs--)
tty_kref_put(tty);
/*
* it drops BTM and thus races with reopen
* we protect the race by TTY_HUPPING
*/
tty_ldisc_hangup(tty);
read_lock(&tasklist_lock);
if (tty->session) {
do_each_pid_task(tty->session, PIDTYPE_SID, p) {
spin_lock_irq(&p->sighand->siglock);
if (p->signal->tty == tty) {
p->signal->tty = NULL;
/* We defer the dereferences outside fo
the tasklist lock */
refs++;
}
if (!p->signal->leader) {
spin_unlock_irq(&p->sighand->siglock);
continue;
}
__group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
__group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
put_pid(p->signal->tty_old_pgrp); /* A noop */
spin_lock_irqsave(&tty->ctrl_lock, flags);
if (tty->pgrp)
p->signal->tty_old_pgrp = get_pid(tty->pgrp);
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
spin_unlock_irq(&p->sighand->siglock);
} while_each_pid_task(tty->session, PIDTYPE_SID, p);
}
read_unlock(&tasklist_lock);
spin_lock_irqsave(&tty->ctrl_lock, flags);
spin_lock_irq(&tty->ctrl_lock);
clear_bit(TTY_THROTTLED, &tty->flags);
clear_bit(TTY_PUSH, &tty->flags);
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
@ -640,11 +671,7 @@ static void __tty_hangup(struct tty_struct *tty)
tty->session = NULL;
tty->pgrp = NULL;
tty->ctrl_status = 0;
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
/* Account for the p->signal references we killed */
while (refs--)
tty_kref_put(tty);
spin_unlock_irq(&tty->ctrl_lock);
/*
* If one of the devices matches a console pointer, we
@ -666,7 +693,6 @@ static void __tty_hangup(struct tty_struct *tty)
*/
set_bit(TTY_HUPPED, &tty->flags);
clear_bit(TTY_HUPPING, &tty->flags);
tty_ldisc_enable(tty);
tty_unlock(tty);
@ -679,7 +705,7 @@ static void do_tty_hangup(struct work_struct *work)
struct tty_struct *tty =
container_of(work, struct tty_struct, hangup_work);
__tty_hangup(tty);
__tty_hangup(tty, 0);
}
/**
@ -717,7 +743,7 @@ void tty_vhangup(struct tty_struct *tty)
printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf));
#endif
__tty_hangup(tty);
__tty_hangup(tty, 0);
}
EXPORT_SYMBOL(tty_vhangup);
@ -740,6 +766,27 @@ void tty_vhangup_self(void)
}
}
/**
* tty_vhangup_session - hangup session leader exit
* @tty: tty to hangup
*
* The session leader is exiting and hanging up its controlling terminal.
* Every process in the foreground process group is signalled SIGHUP.
*
* We do this synchronously so that when the syscall returns the process
* is complete. That guarantee is necessary for security reasons.
*/
static void tty_vhangup_session(struct tty_struct *tty)
{
#ifdef TTY_DEBUG_HANGUP
char buf[64];
printk(KERN_DEBUG "%s vhangup session...\n", tty_name(tty, buf));
#endif
__tty_hangup(tty, 1);
}
/**
* tty_hung_up_p - was tty hung up
* @filp: file pointer of tty
@ -797,18 +844,18 @@ void disassociate_ctty(int on_exit)
tty = get_current_tty();
if (tty) {
struct pid *tty_pgrp = get_pid(tty->pgrp);
if (on_exit) {
if (tty->driver->type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty);
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) {
tty_vhangup_session(tty);
} else {
struct pid *tty_pgrp = tty_get_pgrp(tty);
if (tty_pgrp) {
kill_pgrp(tty_pgrp, SIGHUP, on_exit);
kill_pgrp(tty_pgrp, SIGCONT, on_exit);
put_pid(tty_pgrp);
}
}
tty_kref_put(tty);
if (tty_pgrp) {
kill_pgrp(tty_pgrp, SIGHUP, on_exit);
if (!on_exit)
kill_pgrp(tty_pgrp, SIGCONT, on_exit);
put_pid(tty_pgrp);
}
} else if (on_exit) {
struct pid *old_pgrp;
spin_lock_irq(&current->sighand->siglock);
@ -941,6 +988,14 @@ void start_tty(struct tty_struct *tty)
EXPORT_SYMBOL(start_tty);
/* We limit tty time update visibility to every 8 seconds or so. */
static void tty_update_time(struct timespec *time)
{
unsigned long sec = get_seconds() & ~7;
if ((long)(sec - time->tv_sec) > 0)
time->tv_sec = sec;
}
/**
* tty_read - read method for tty device files
* @file: pointer to tty file
@ -960,10 +1015,11 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
int i;
struct inode *inode = file_inode(file);
struct tty_struct *tty = file_tty(file);
struct tty_ldisc *ld;
if (tty_paranoia_check(tty, file_inode(file), "tty_read"))
if (tty_paranoia_check(tty, inode, "tty_read"))
return -EIO;
if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
return -EIO;
@ -977,6 +1033,9 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
i = -EIO;
tty_ldisc_deref(ld);
if (i > 0)
tty_update_time(&inode->i_atime);
return i;
}
@ -1077,8 +1136,10 @@ static inline ssize_t do_tty_write(
break;
cond_resched();
}
if (written)
if (written) {
tty_update_time(&file_inode(file)->i_mtime);
ret = written;
}
out:
tty_write_unlock(tty);
return ret;
@ -1344,9 +1405,7 @@ static int tty_reopen(struct tty_struct *tty)
}
tty->count++;
mutex_lock(&tty->ldisc_mutex);
WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
mutex_unlock(&tty->ldisc_mutex);
return 0;
}
@ -1463,6 +1522,17 @@ void tty_free_termios(struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_free_termios);
/**
* tty_flush_works - flush all works of a tty
* @tty: tty device to flush works for
*
* Sync flush all works belonging to @tty.
*/
static void tty_flush_works(struct tty_struct *tty)
{
flush_work(&tty->SAK_work);
flush_work(&tty->hangup_work);
}
/**
* release_one_tty - release tty structure memory
@ -1548,6 +1618,7 @@ static void release_tty(struct tty_struct *tty, int idx)
tty_free_termios(tty);
tty_driver_remove_tty(tty->driver, tty);
tty->port->itty = NULL;
cancel_work_sync(&tty->port->buf.work);
if (tty->link)
tty_kref_put(tty->link);
@ -1777,12 +1848,21 @@ int tty_release(struct inode *inode, struct file *filp)
return 0;
#ifdef TTY_DEBUG_HANGUP
printk(KERN_DEBUG "%s: freeing tty structure...\n", __func__);
printk(KERN_DEBUG "%s: %s: final close\n", __func__, tty_name(tty, buf));
#endif
/*
* Ask the line discipline code to release its structures
*/
tty_ldisc_release(tty, o_tty);
/* Wait for pending work before tty destruction commmences */
tty_flush_works(tty);
if (o_tty)
tty_flush_works(o_tty);
#ifdef TTY_DEBUG_HANGUP
printk(KERN_DEBUG "%s: %s: freeing structure...\n", __func__, tty_name(tty, buf));
#endif
/*
* The release_tty function takes care of the details of clearing
* the slots and preserving the termios structure. The tty_unlock_pair

View file

@ -106,6 +106,7 @@ void tty_throttle(struct tty_struct *tty)
if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
tty->ops->throttle)
tty->ops->throttle(tty);
tty->flow_change = 0;
mutex_unlock(&tty->termios_mutex);
}
EXPORT_SYMBOL(tty_throttle);
@ -129,10 +130,73 @@ void tty_unthrottle(struct tty_struct *tty)
if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
tty->ops->unthrottle)
tty->ops->unthrottle(tty);
tty->flow_change = 0;
mutex_unlock(&tty->termios_mutex);
}
EXPORT_SYMBOL(tty_unthrottle);
/**
* tty_throttle_safe - flow control
* @tty: terminal
*
* Similar to tty_throttle() but will only attempt throttle
* if tty->flow_change is TTY_THROTTLE_SAFE. Prevents an accidental
* throttle due to race conditions when throttling is conditional
* on factors evaluated prior to throttling.
*
* Returns 0 if tty is throttled (or was already throttled)
*/
int tty_throttle_safe(struct tty_struct *tty)
{
int ret = 0;
mutex_lock(&tty->termios_mutex);
if (!test_bit(TTY_THROTTLED, &tty->flags)) {
if (tty->flow_change != TTY_THROTTLE_SAFE)
ret = 1;
else {
set_bit(TTY_THROTTLED, &tty->flags);
if (tty->ops->throttle)
tty->ops->throttle(tty);
}
}
mutex_unlock(&tty->termios_mutex);
return ret;
}
/**
* tty_unthrottle_safe - flow control
* @tty: terminal
*
* Similar to tty_unthrottle() but will only attempt unthrottle
* if tty->flow_change is TTY_UNTHROTTLE_SAFE. Prevents an accidental
* unthrottle due to race conditions when unthrottling is conditional
* on factors evaluated prior to unthrottling.
*
* Returns 0 if tty is unthrottled (or was already unthrottled)
*/
int tty_unthrottle_safe(struct tty_struct *tty)
{
int ret = 0;
mutex_lock(&tty->termios_mutex);
if (test_bit(TTY_THROTTLED, &tty->flags)) {
if (tty->flow_change != TTY_UNTHROTTLE_SAFE)
ret = 1;
else {
clear_bit(TTY_THROTTLED, &tty->flags);
if (tty->ops->unthrottle)
tty->ops->unthrottle(tty);
}
}
mutex_unlock(&tty->termios_mutex);
return ret;
}
/**
* tty_wait_until_sent - wait for I/O to finish
* @tty: tty we are waiting for
@ -414,34 +478,6 @@ void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
}
EXPORT_SYMBOL_GPL(tty_encode_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.
*
* Locking: none
*/
speed_t tty_get_baud_rate(struct tty_struct *tty)
{
speed_t baud = tty_termios_baud_rate(&tty->termios);
if (baud == 38400 && tty->alt_speed) {
if (!tty->warned) {
printk(KERN_WARNING "Use of setserial/setrocket to "
"set SPD_* flags is deprecated\n");
tty->warned = 1;
}
baud = tty->alt_speed;
}
return baud;
}
EXPORT_SYMBOL(tty_get_baud_rate);
/**
* tty_termios_copy_hw - copy hardware settings
* @new: New termios
@ -1086,14 +1122,12 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
}
EXPORT_SYMBOL_GPL(tty_mode_ioctl);
int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
{
struct tty_ldisc *ld;
int retval = tty_check_change(tty);
if (retval)
return retval;
ld = tty_ldisc_ref_wait(tty);
/* Caller guarantees ldisc reference is held */
static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg)
{
struct tty_ldisc *ld = tty->ldisc;
switch (arg) {
case TCIFLUSH:
if (ld && ld->ops->flush_buffer) {
@ -1111,12 +1145,24 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
tty_driver_flush_buffer(tty);
break;
default:
tty_ldisc_deref(ld);
return -EINVAL;
}
tty_ldisc_deref(ld);
return 0;
}
int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
{
struct tty_ldisc *ld;
int retval = tty_check_change(tty);
if (retval)
return retval;
ld = tty_ldisc_ref_wait(tty);
retval = __tty_perform_flush(tty, arg);
if (ld)
tty_ldisc_deref(ld);
return retval;
}
EXPORT_SYMBOL_GPL(tty_perform_flush);
int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
@ -1155,7 +1201,7 @@ int n_tty_ioctl_helper(struct tty_struct *tty, struct file *file,
}
return 0;
case TCFLSH:
return tty_perform_flush(tty, arg);
return __tty_perform_flush(tty, arg);
default:
/* Try the mode commands */
return tty_mode_ioctl(tty, file, cmd, arg);

View file

@ -20,6 +20,17 @@
#include <linux/uaccess.h>
#include <linux/ratelimit.h>
#undef LDISC_DEBUG_HANGUP
#ifdef LDISC_DEBUG_HANGUP
#define tty_ldisc_debug(tty, f, args...) ({ \
char __b[64]; \
printk(KERN_DEBUG "%s: %s: " f, __func__, tty_name(tty, __b), ##args); \
})
#else
#define tty_ldisc_debug(tty, f, args...)
#endif
/*
* This guards the refcounted line discipline lists. The lock
* must be taken with irqs off because there are hangup path
@ -31,44 +42,6 @@ static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
/* Line disc dispatch table */
static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
static inline struct tty_ldisc *get_ldisc(struct tty_ldisc *ld)
{
if (ld)
atomic_inc(&ld->users);
return ld;
}
static void put_ldisc(struct tty_ldisc *ld)
{
unsigned long flags;
if (WARN_ON_ONCE(!ld))
return;
/*
* If this is the last user, free the ldisc, and
* release the ldisc ops.
*
* We really want an "atomic_dec_and_raw_lock_irqsave()",
* but we don't have it, so this does it by hand.
*/
raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
if (atomic_dec_and_test(&ld->users)) {
struct tty_ldisc_ops *ldo = ld->ops;
ldo->refcount--;
module_put(ldo->owner);
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
kfree(ld);
return;
}
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
if (waitqueue_active(&ld->wq_idle))
wake_up(&ld->wq_idle);
}
/**
* tty_register_ldisc - install a line discipline
* @disc: ldisc number
@ -206,6 +179,29 @@ static struct tty_ldisc *tty_ldisc_get(int disc)
return ld;
}
/**
* tty_ldisc_put - release the ldisc
*
* Complement of tty_ldisc_get().
*/
static inline void tty_ldisc_put(struct tty_ldisc *ld)
{
unsigned long flags;
if (WARN_ON_ONCE(!ld))
return;
raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
/* unreleased reader reference(s) will cause this WARN */
WARN_ON(!atomic_dec_and_test(&ld->users));
ld->ops->refcount--;
module_put(ld->ops->owner);
kfree(ld);
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
}
static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
{
return (*pos < NR_LDISCS) ? pos : NULL;
@ -254,24 +250,6 @@ const struct file_operations tty_ldiscs_proc_fops = {
.release = seq_release,
};
/**
* tty_ldisc_assign - set ldisc on a tty
* @tty: tty to assign
* @ld: line discipline
*
* Install an instance of a line discipline into a tty structure. The
* ldisc must have a reference count above zero to ensure it remains.
* The tty instance refcount starts at zero.
*
* Locking:
* Caller must hold references
*/
static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
{
tty->ldisc = ld;
}
/**
* tty_ldisc_try - internal helper
* @tty: the tty
@ -289,10 +267,13 @@ static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty)
unsigned long flags;
struct tty_ldisc *ld;
/* FIXME: this allows reference acquire after TTY_LDISC is cleared */
raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
ld = NULL;
if (test_bit(TTY_LDISC, &tty->flags))
ld = get_ldisc(tty->ldisc);
if (test_bit(TTY_LDISC, &tty->flags) && tty->ldisc) {
ld = tty->ldisc;
atomic_inc(&ld->users);
}
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
return ld;
}
@ -352,15 +333,24 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref);
void tty_ldisc_deref(struct tty_ldisc *ld)
{
put_ldisc(ld);
unsigned long flags;
if (WARN_ON_ONCE(!ld))
return;
raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
/*
* WARNs if one-too-many reader references were released
* - the last reference must be released with tty_ldisc_put
*/
WARN_ON(atomic_dec_and_test(&ld->users));
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
if (waitqueue_active(&ld->wq_idle))
wake_up(&ld->wq_idle);
}
EXPORT_SYMBOL_GPL(tty_ldisc_deref);
static inline void tty_ldisc_put(struct tty_ldisc *ld)
{
put_ldisc(ld);
}
/**
* tty_ldisc_enable - allow ldisc use
* @tty: terminal to activate ldisc on
@ -373,8 +363,9 @@ static inline void tty_ldisc_put(struct tty_ldisc *ld)
* Clearing directly is allowed.
*/
void tty_ldisc_enable(struct tty_struct *tty)
static void tty_ldisc_enable(struct tty_struct *tty)
{
clear_bit(TTY_LDISC_HALTED, &tty->flags);
set_bit(TTY_LDISC, &tty->flags);
clear_bit(TTY_LDISC_CHANGING, &tty->flags);
wake_up(&tty_ldisc_wait);
@ -479,7 +470,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
/* There is an outstanding reference here so this is safe */
old = tty_ldisc_get(old->ops->num);
WARN_ON(IS_ERR(old));
tty_ldisc_assign(tty, old);
tty->ldisc = old;
tty_set_termios_ldisc(tty, old->ops->num);
if (tty_ldisc_open(tty, old) < 0) {
tty_ldisc_put(old);
@ -487,7 +478,7 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
new_ldisc = tty_ldisc_get(N_TTY);
if (IS_ERR(new_ldisc))
panic("n_tty: get");
tty_ldisc_assign(tty, new_ldisc);
tty->ldisc = new_ldisc;
tty_set_termios_ldisc(tty, N_TTY);
r = tty_ldisc_open(tty, new_ldisc);
if (r < 0)
@ -497,39 +488,6 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
}
}
/**
* tty_ldisc_halt - shut down the line discipline
* @tty: tty device
*
* Shut down the line discipline and work queue for this tty device.
* The TTY_LDISC flag being cleared ensures no further references can
* be obtained while the delayed work queue halt ensures that no more
* data is fed to the ldisc.
*
* You need to do a 'flush_scheduled_work()' (outside the ldisc_mutex)
* in order to make sure any currently executing ldisc work is also
* flushed.
*/
static int tty_ldisc_halt(struct tty_struct *tty)
{
clear_bit(TTY_LDISC, &tty->flags);
return cancel_work_sync(&tty->port->buf.work);
}
/**
* tty_ldisc_flush_works - flush all works of a tty
* @tty: tty device to flush works for
*
* Sync flush all works belonging to @tty.
*/
static void tty_ldisc_flush_works(struct tty_struct *tty)
{
flush_work(&tty->hangup_work);
flush_work(&tty->SAK_work);
flush_work(&tty->port->buf.work);
}
/**
* tty_ldisc_wait_idle - wait for the ldisc to become idle
* @tty: tty to wait for
@ -546,6 +504,85 @@ static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
return ret > 0 ? 0 : -EBUSY;
}
/**
* tty_ldisc_halt - shut down the line discipline
* @tty: tty device
* @o_tty: paired pty device (can be NULL)
* @timeout: # of jiffies to wait for ldisc refs to be released
*
* Shut down the line discipline and work queue for this tty device and
* its paired pty (if exists). Clearing the TTY_LDISC flag ensures
* no further references can be obtained, while waiting for existing
* references to be released ensures no more data is fed to the ldisc.
*
* You need to do a 'flush_scheduled_work()' (outside the ldisc_mutex)
* in order to make sure any currently executing ldisc work is also
* flushed.
*/
static int tty_ldisc_halt(struct tty_struct *tty, struct tty_struct *o_tty,
long timeout)
{
int retval;
clear_bit(TTY_LDISC, &tty->flags);
if (o_tty)
clear_bit(TTY_LDISC, &o_tty->flags);
retval = tty_ldisc_wait_idle(tty, timeout);
if (!retval && o_tty)
retval = tty_ldisc_wait_idle(o_tty, timeout);
if (retval)
return retval;
set_bit(TTY_LDISC_HALTED, &tty->flags);
if (o_tty)
set_bit(TTY_LDISC_HALTED, &o_tty->flags);
return 0;
}
/**
* tty_ldisc_hangup_halt - halt the line discipline for hangup
* @tty: tty being hung up
*
* Shut down the line discipline and work queue for the tty device
* being hungup. Clear the TTY_LDISC flag to ensure no further
* references can be obtained and wait for remaining references to be
* released to ensure no more data is fed to this ldisc.
* Caller must hold legacy and ->ldisc_mutex.
*
* NB: tty_set_ldisc() is prevented from changing the ldisc concurrently
* with this function by checking the TTY_HUPPING flag.
*/
static bool tty_ldisc_hangup_halt(struct tty_struct *tty)
{
char cur_n[TASK_COMM_LEN], tty_n[64];
long timeout = 3 * HZ;
clear_bit(TTY_LDISC, &tty->flags);
if (tty->ldisc) { /* Not yet closed */
tty_unlock(tty);
while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
timeout = MAX_SCHEDULE_TIMEOUT;
printk_ratelimited(KERN_WARNING
"%s: waiting (%s) for %s took too long, but we keep waiting...\n",
__func__, get_task_comm(cur_n, current),
tty_name(tty, tty_n));
}
set_bit(TTY_LDISC_HALTED, &tty->flags);
/* must reacquire both locks and preserve lock order */
mutex_unlock(&tty->ldisc_mutex);
tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
}
return !!tty->ldisc;
}
/**
* tty_set_ldisc - set line discipline
* @tty: the terminal to set
@ -563,7 +600,6 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
{
int retval;
struct tty_ldisc *o_ldisc, *new_ldisc;
int work, o_work = 0;
struct tty_struct *o_tty;
new_ldisc = tty_ldisc_get(ldisc);
@ -589,15 +625,6 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
return 0;
}
tty_unlock(tty);
/*
* Problem: What do we do if this blocks ?
* We could deadlock here
*/
tty_wait_until_sent(tty, 0);
tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/*
@ -637,20 +664,16 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
* parallel to the change and re-referencing the tty.
*/
work = tty_ldisc_halt(tty);
if (o_tty)
o_work = tty_ldisc_halt(o_tty);
retval = tty_ldisc_halt(tty, o_tty, 5 * HZ);
/*
* Wait for ->hangup_work and ->buf.work handlers to terminate.
* Wait for hangup to complete, if pending.
* We must drop the mutex here in case a hangup is also in process.
*/
mutex_unlock(&tty->ldisc_mutex);
tty_ldisc_flush_works(tty);
retval = tty_ldisc_wait_idle(tty, 5 * HZ);
flush_work(&tty->hangup_work);
tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
@ -675,7 +698,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
tty_ldisc_close(tty, o_ldisc);
/* Now set up the new line discipline. */
tty_ldisc_assign(tty, new_ldisc);
tty->ldisc = new_ldisc;
tty_set_termios_ldisc(tty, ldisc);
retval = tty_ldisc_open(tty, new_ldisc);
@ -705,10 +728,10 @@ enable:
/* Restart the work queue in case no characters kick it off. Safe if
already running */
if (work)
schedule_work(&tty->port->buf.work);
if (o_work)
schedule_work(&tty->port->buf.work);
if (o_tty)
schedule_work(&o_tty->port->buf.work);
mutex_unlock(&tty->ldisc_mutex);
tty_unlock(tty);
return retval;
@ -749,11 +772,10 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
tty_ldisc_close(tty, tty->ldisc);
tty_ldisc_put(tty->ldisc);
tty->ldisc = NULL;
/*
* Switch the line discipline back
*/
tty_ldisc_assign(tty, ld);
tty->ldisc = ld;
tty_set_termios_ldisc(tty, ldisc);
return 0;
@ -780,6 +802,8 @@ void tty_ldisc_hangup(struct tty_struct *tty)
int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
int err = 0;
tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
/*
* FIXME! What are the locking issues here? This may me overdoing
* things... This question is especially important now that we've
@ -812,40 +836,12 @@ void tty_ldisc_hangup(struct tty_struct *tty)
*/
mutex_lock(&tty->ldisc_mutex);
/*
* this is like tty_ldisc_halt, but we need to give up
* the BTM before calling cancel_work_sync, which may
* need to wait for another function taking the BTM
*/
clear_bit(TTY_LDISC, &tty->flags);
tty_unlock(tty);
cancel_work_sync(&tty->port->buf.work);
mutex_unlock(&tty->ldisc_mutex);
retry:
tty_lock(tty);
mutex_lock(&tty->ldisc_mutex);
/* At this point we have a closed ldisc and we want to
reopen it. We could defer this to the next open but
it means auditing a lot of other paths so this is
a FIXME */
if (tty->ldisc) { /* Not yet closed */
if (atomic_read(&tty->ldisc->users) != 1) {
char cur_n[TASK_COMM_LEN], tty_n[64];
long timeout = 3 * HZ;
tty_unlock(tty);
while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
timeout = MAX_SCHEDULE_TIMEOUT;
printk_ratelimited(KERN_WARNING
"%s: waiting (%s) for %s took too long, but we keep waiting...\n",
__func__, get_task_comm(cur_n, current),
tty_name(tty, tty_n));
}
mutex_unlock(&tty->ldisc_mutex);
goto retry;
}
if (tty_ldisc_hangup_halt(tty)) {
/* At this point we have a halted ldisc; we want to close it and
reopen a new ldisc. We could defer the reopen to the next
open but it means auditing a lot of other paths so this is
a FIXME */
if (reset == 0) {
if (!tty_ldisc_reinit(tty, tty->termios.c_line))
@ -864,6 +860,8 @@ retry:
mutex_unlock(&tty->ldisc_mutex);
if (reset)
tty_reset_termios(tty);
tty_ldisc_debug(tty, "re-opened ldisc: %p\n", tty->ldisc);
}
/**
@ -899,11 +897,6 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
static void tty_ldisc_kill(struct tty_struct *tty)
{
/* There cannot be users from userspace now. But there still might be
* drivers holding a reference via tty_ldisc_ref. Do not steal them the
* ldisc until they are done. */
tty_ldisc_wait_idle(tty, MAX_SCHEDULE_TIMEOUT);
mutex_lock(&tty->ldisc_mutex);
/*
* Now kill off the ldisc
@ -931,18 +924,13 @@ static void tty_ldisc_kill(struct tty_struct *tty)
void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
{
/*
* Prevent flush_to_ldisc() from rescheduling the work for later. Then
* kill any delayed work. As this is the final close it does not
* race with the set_ldisc code path.
* Shutdown this line discipline. As this is the final close,
* it does not race with the set_ldisc code path.
*/
tty_ldisc_halt(tty);
if (o_tty)
tty_ldisc_halt(o_tty);
tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
tty_ldisc_flush_works(tty);
if (o_tty)
tty_ldisc_flush_works(o_tty);
tty_ldisc_halt(tty, o_tty, MAX_SCHEDULE_TIMEOUT);
tty_lock_pair(tty, o_tty);
/* This will need doing differently if we need to lock */
@ -953,6 +941,8 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
tty_unlock_pair(tty, o_tty);
/* And the memory resources remaining (buffers, termios) will be
disposed of when the kref hits zero */
tty_ldisc_debug(tty, "ldisc closed\n");
}
/**
@ -968,7 +958,7 @@ void tty_ldisc_init(struct tty_struct *tty)
struct tty_ldisc *ld = tty_ldisc_get(N_TTY);
if (IS_ERR(ld))
panic("n_tty: init_tty");
tty_ldisc_assign(tty, ld);
tty->ldisc = ld;
}
/**
@ -980,8 +970,8 @@ void tty_ldisc_init(struct tty_struct *tty)
*/
void tty_ldisc_deinit(struct tty_struct *tty)
{
put_ldisc(tty->ldisc);
tty_ldisc_assign(tty, NULL);
tty_ldisc_put(tty->ldisc);
tty->ldisc = NULL;
}
void tty_ldisc_begin(void)

View file

@ -132,6 +132,7 @@ EXPORT_SYMBOL(tty_port_free_xmit_buf);
*/
void tty_port_destroy(struct tty_port *port)
{
cancel_work_sync(&port->buf.work);
tty_buffer_free_all(port);
}
EXPORT_SYMBOL(tty_port_destroy);
@ -196,12 +197,24 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_port_tty_set);
static void tty_port_shutdown(struct tty_port *port)
static void tty_port_shutdown(struct tty_port *port, struct tty_struct *tty)
{
mutex_lock(&port->mutex);
if (port->ops->shutdown && !port->console &&
test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
if (port->console)
goto out;
if (test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags)) {
/*
* Drop DTR/RTS if HUPCL is set. This causes any attached
* modem to hang up the line.
*/
if (tty && C_HUPCL(tty))
tty_port_lower_dtr_rts(port);
if (port->ops->shutdown)
port->ops->shutdown(port);
}
out:
mutex_unlock(&port->mutex);
}
@ -215,23 +228,57 @@ static void tty_port_shutdown(struct tty_port *port)
void tty_port_hangup(struct tty_port *port)
{
struct tty_struct *tty;
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
port->count = 0;
port->flags &= ~ASYNC_NORMAL_ACTIVE;
if (port->tty) {
set_bit(TTY_IO_ERROR, &port->tty->flags);
tty_kref_put(port->tty);
}
tty = port->tty;
if (tty)
set_bit(TTY_IO_ERROR, &tty->flags);
port->tty = NULL;
spin_unlock_irqrestore(&port->lock, flags);
tty_port_shutdown(port, tty);
tty_kref_put(tty);
wake_up_interruptible(&port->open_wait);
wake_up_interruptible(&port->delta_msr_wait);
tty_port_shutdown(port);
}
EXPORT_SYMBOL(tty_port_hangup);
/**
* tty_port_tty_hangup - helper to hang up a tty
*
* @port: tty port
* @check_clocal: hang only ttys with CLOCAL unset?
*/
void tty_port_tty_hangup(struct tty_port *port, bool check_clocal)
{
struct tty_struct *tty = tty_port_tty_get(port);
if (tty && (!check_clocal || !C_CLOCAL(tty))) {
tty_hangup(tty);
tty_kref_put(tty);
}
}
EXPORT_SYMBOL_GPL(tty_port_tty_hangup);
/**
* tty_port_tty_wakeup - helper to wake up a tty
*
* @port: tty port
*/
void tty_port_tty_wakeup(struct tty_port *port)
{
struct tty_struct *tty = tty_port_tty_get(port);
if (tty) {
tty_wakeup(tty);
tty_kref_put(tty);
}
}
EXPORT_SYMBOL_GPL(tty_port_tty_wakeup);
/**
* tty_port_carrier_raised - carrier raised check
* @port: tty port
@ -350,7 +397,7 @@ int tty_port_block_til_ready(struct tty_port *port,
while (1) {
/* Indicate we are open */
if (tty->termios.c_cflag & CBAUD)
if (C_BAUD(tty) && test_bit(ASYNCB_INITIALIZED, &port->flags))
tty_port_raise_dtr_rts(port);
prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE);
@ -395,6 +442,20 @@ int tty_port_block_til_ready(struct tty_port *port,
}
EXPORT_SYMBOL(tty_port_block_til_ready);
static void tty_port_drain_delay(struct tty_port *port, struct tty_struct *tty)
{
unsigned int bps = tty_get_baud_rate(tty);
long timeout;
if (bps > 1200) {
timeout = (HZ * 10 * port->drain_delay) / bps;
timeout = max_t(long, timeout, HZ / 10);
} else {
timeout = 2 * HZ;
}
schedule_timeout_interruptible(timeout);
}
int tty_port_close_start(struct tty_port *port,
struct tty_struct *tty, struct file *filp)
{
@ -427,31 +488,19 @@ int tty_port_close_start(struct tty_port *port,
set_bit(ASYNCB_CLOSING, &port->flags);
tty->closing = 1;
spin_unlock_irqrestore(&port->lock, flags);
/* Don't block on a stalled port, just pull the chain */
if (tty->flow_stopped)
tty_driver_flush_buffer(tty);
if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent_from_close(tty, port->closing_wait);
if (port->drain_delay) {
unsigned int bps = tty_get_baud_rate(tty);
long timeout;
if (bps > 1200)
timeout = max_t(long,
(HZ * 10 * port->drain_delay) / bps, HZ / 10);
else
timeout = 2 * HZ;
schedule_timeout_interruptible(timeout);
if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
/* Don't block on a stalled port, just pull the chain */
if (tty->flow_stopped)
tty_driver_flush_buffer(tty);
if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent_from_close(tty, port->closing_wait);
if (port->drain_delay)
tty_port_drain_delay(port, tty);
}
/* Flush the ldisc buffering */
tty_ldisc_flush(tty);
/* Drop DTR/RTS if HUPCL is set. This causes any attached modem to
hang up the line */
if (tty->termios.c_cflag & HUPCL)
tty_port_lower_dtr_rts(port);
/* Don't call port->drop for the last reference. Callers will want
to drop the last active reference in ->shutdown() or the tty
shutdown path */
@ -486,7 +535,7 @@ void tty_port_close(struct tty_port *port, struct tty_struct *tty,
{
if (tty_port_close_start(port, tty, filp) == 0)
return;
tty_port_shutdown(port);
tty_port_shutdown(port, tty);
set_bit(TTY_IO_ERROR, &tty->flags);
tty_port_close_end(port, tty);
tty_port_tty_set(port, NULL);

View file

@ -194,8 +194,7 @@ static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int
q = p->inverse_translations[i];
if (!q) {
q = p->inverse_translations[i] = (unsigned char *)
kmalloc(MAX_GLYPH, GFP_KERNEL);
q = p->inverse_translations[i] = kmalloc(MAX_GLYPH, GFP_KERNEL);
if (!q) return;
}
memset(q, 0, MAX_GLYPH);

View file

@ -93,7 +93,7 @@ vcs_poll_data_free(struct vcs_poll_data *poll)
static struct vcs_poll_data *
vcs_poll_data_get(struct file *file)
{
struct vcs_poll_data *poll = file->private_data;
struct vcs_poll_data *poll = file->private_data, *kill = NULL;
if (poll)
return poll;
@ -122,10 +122,12 @@ vcs_poll_data_get(struct file *file)
file->private_data = poll;
} else {
/* someone else raced ahead of us */
vcs_poll_data_free(poll);
kill = poll;
poll = file->private_data;
}
spin_unlock(&file->f_lock);
if (kill)
vcs_poll_data_free(kill);
return poll;
}

View file

@ -779,7 +779,6 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */
con_set_default_unimap(vc);
vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
if (!vc->vc_screenbuf) {
tty_port_destroy(&vc->port);
kfree(vc);
vc_cons[currcons].d = NULL;
return -ENOMEM;
@ -986,26 +985,25 @@ static int vt_resize(struct tty_struct *tty, struct winsize *ws)
return ret;
}
void vc_deallocate(unsigned int currcons)
struct vc_data *vc_deallocate(unsigned int currcons)
{
struct vc_data *vc = NULL;
WARN_CONSOLE_UNLOCKED();
if (vc_cons_allocated(currcons)) {
struct vc_data *vc = vc_cons[currcons].d;
struct vt_notifier_param param = { .vc = vc };
struct vt_notifier_param param;
param.vc = vc = vc_cons[currcons].d;
atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, &param);
vcs_remove_sysfs(currcons);
vc->vc_sw->con_deinit(vc);
put_pid(vc->vt_pid);
module_put(vc->vc_sw->owner);
kfree(vc->vc_screenbuf);
if (currcons >= MIN_NR_CONSOLES) {
tty_port_destroy(&vc->port);
kfree(vc);
}
vc_cons[currcons].d = NULL;
}
return vc;
}
/*

View file

@ -283,6 +283,51 @@ do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_
return 0;
}
/* deallocate a single console, if possible (leave 0) */
static int vt_disallocate(unsigned int vc_num)
{
struct vc_data *vc = NULL;
int ret = 0;
if (!vc_num)
return 0;
console_lock();
if (VT_BUSY(vc_num))
ret = -EBUSY;
else
vc = vc_deallocate(vc_num);
console_unlock();
if (vc && vc_num >= MIN_NR_CONSOLES) {
tty_port_destroy(&vc->port);
kfree(vc);
}
return ret;
}
/* deallocate all unused consoles, but leave 0 */
static void vt_disallocate_all(void)
{
struct vc_data *vc[MAX_NR_CONSOLES];
int i;
console_lock();
for (i = 1; i < MAX_NR_CONSOLES; i++)
if (!VT_BUSY(i))
vc[i] = vc_deallocate(i);
else
vc[i] = NULL;
console_unlock();
for (i = 1; i < MAX_NR_CONSOLES; i++) {
if (vc[i] && i >= MIN_NR_CONSOLES) {
tty_port_destroy(&vc[i]->port);
kfree(vc[i]);
}
}
}
/*
@ -769,24 +814,10 @@ int vt_ioctl(struct tty_struct *tty,
ret = -ENXIO;
break;
}
if (arg == 0) {
/* deallocate all unused consoles, but leave 0 */
console_lock();
for (i=1; i<MAX_NR_CONSOLES; i++)
if (! VT_BUSY(i))
vc_deallocate(i);
console_unlock();
} else {
/* deallocate a single console, if possible */
arg--;
if (VT_BUSY(arg))
ret = -EBUSY;
else if (arg) { /* leave 0 */
console_lock();
vc_deallocate(arg);
console_unlock();
}
}
if (arg == 0)
vt_disallocate_all();
else
ret = vt_disallocate(--arg);
break;
case VT_RESIZE: