commit be349c985a7a4944ce2d35517f27341355a64056 (patch)
parent 3f287943138c36 mxser: use irq from uart_port
tree f472e0a5e95e57bbb0e5d520ea32976c88387c04
author Jiri Slaby <jslaby@suse.cz> 2021-12-01 12:29:17 +0100
committer Jiri Slaby (SUSE) <jirislaby@kernel.org> 2024-12-16 10:38:59 +0100
mxser: switch to uart_driver
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
drivers/tty/mxser.c | 758 +++++++++++-----------------------------------------
1 file changed, 154 insertions(+), 604 deletions(-)
diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c
index 0a3927a64a2ad7..63c6d910fc5d9c 100644
--- a/drivers/tty/mxser.c
+++ b/drivers/tty/mxser.c
@@ -252,7 +252,6 @@ MODULE_LICENSE("GPL");
struct mxser_board;
struct mxser_port {
- struct tty_port port;
struct uart_port uport;
struct mxser_board *board;
@@ -278,11 +277,10 @@ struct mxser_board {
};
static DECLARE_BITMAP(mxser_boards, MXSER_BOARDS);
-static struct tty_driver *mxvar_sdriver;
-static inline struct mxser_port *to_mport(struct tty_port *tport)
+static inline struct mxser_port *to_mport(struct uart_port *uport)
{
- return container_of(tport, struct mxser_port, port);
+ return container_of(uport, struct mxser_port, uport);
}
static u8 __mxser_must_set_EFR(unsigned long baseio, u8 clear, u8 set,
@@ -432,56 +430,23 @@ static void mxser_process_txrx_fifo(struct mxser_port *info)
}
}
-static void __mxser_start_tx(struct mxser_port *info)
+static void mxser_start_tx(struct uart_port *uport)
{
- struct uart_port *uport = &info->uport;
+ struct mxser_port *info = to_mport(uport);
outb(info->IER & ~UART_IER_THRI, uport->iobase + UART_IER);
info->IER |= UART_IER_THRI;
outb(info->IER, uport->iobase + UART_IER);
}
-static void mxser_start_tx(struct mxser_port *info)
+static void mxser_stop_tx(struct uart_port *uport)
{
- struct uart_port *uport = &info->uport;
- unsigned long flags;
-
- spin_lock_irqsave(&uport->lock, flags);
- __mxser_start_tx(info);
- spin_unlock_irqrestore(&uport->lock, flags);
-}
-
-static void __mxser_stop_tx(struct mxser_port *info)
-{
- struct uart_port *uport = &info->uport;
+ struct mxser_port *info = to_mport(uport);
info->IER &= ~UART_IER_THRI;
outb(info->IER, uport->iobase + UART_IER);
}
-static bool mxser_carrier_raised(struct tty_port *port)
-{
- struct uart_port *uport = &to_mport(port)->uport;
-
- return inb(uport->iobase + UART_MSR) & UART_MSR_DCD;
-}
-
-static void mxser_dtr_rts(struct tty_port *port, bool active)
-{
- struct uart_port *uport = &to_mport(port)->uport;
- unsigned long flags;
- u8 mcr;
-
- spin_lock_irqsave(&uport->lock, flags);
- mcr = inb(uport->iobase + UART_MCR);
- if (active)
- mcr |= UART_MCR_DTR | UART_MCR_RTS;
- else
- mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
- outb(mcr, uport->iobase + UART_MCR);
- spin_unlock_irqrestore(&uport->lock, flags);
-}
-
static int mxser_set_baud(struct mxser_port *info, struct ktermios *termios)
{
struct uart_port *uport = &info->uport;
@@ -541,8 +506,7 @@ static int mxser_set_baud(struct mxser_port *info, struct ktermios *termios)
return 0;
}
-static void mxser_handle_cts(struct tty_struct *tty, struct mxser_port *info,
- u8 msr)
+static void mxser_handle_cts(struct mxser_port *info, u8 msr)
{
struct uart_port *uport = &info->uport;
bool cts = msr & UART_MSR_CTS;
@@ -552,8 +516,8 @@ static void mxser_handle_cts(struct tty_struct *tty, struct mxser_port *info,
uport->hw_stopped = false;
if (!mxser_16550A_or_MUST(info))
- __mxser_start_tx(info);
- tty_wakeup(tty);
+ mxser_start_tx(uport);
+ uart_write_wakeup(uport);
}
return;
} else if (cts)
@@ -561,17 +525,17 @@ static void mxser_handle_cts(struct tty_struct *tty, struct mxser_port *info,
uport->hw_stopped = true;
if (!mxser_16550A_or_MUST(info))
- __mxser_stop_tx(info);
+ mxser_stop_tx(uport);
}
/*
* This routine is called to set the UART divisor registers to match
* the specified baud rate for a serial port.
*/
-static void mxser_change_speed(struct tty_struct *tty, struct ktermios *termios,
+static void mxser_change_speed(struct mxser_port *info,
+ struct ktermios *termios,
const struct ktermios *old_termios)
{
- struct mxser_port *info = tty->driver_data;
struct uart_port *uport = &info->uport;
unsigned cflag, cval;
@@ -623,18 +587,17 @@ static void mxser_change_speed(struct tty_struct *tty, struct ktermios *termios,
/* CTS flow control flag and modem status interrupts */
info->IER &= ~UART_IER_MSI;
info->MCR &= ~UART_MCR_AFE;
- tty_port_set_cts_flow(&info->port, cflag & CRTSCTS);
+ //tty_port_set_cts_flow(&info->port, cflag & CRTSCTS);
if (cflag & CRTSCTS) {
info->IER |= UART_IER_MSI;
if (mxser_16550A_or_MUST(info)) {
info->MCR |= UART_MCR_AFE;
} else {
- mxser_handle_cts(tty, info,
- inb(uport->iobase + UART_MSR));
+ mxser_handle_cts(info, inb(uport->iobase + UART_MSR));
}
}
outb(info->MCR, uport->iobase + UART_MCR);
- tty_port_set_check_carrier(&info->port, ~cflag & CLOCAL);
+ //tty_port_set_check_carrier(&info->port, ~cflag & CLOCAL);
if (~cflag & CLOCAL)
info->IER |= UART_IER_MSI;
outb(info->IER, uport->iobase + UART_IER);
@@ -682,8 +645,7 @@ static void mxser_change_speed(struct tty_struct *tty, struct ktermios *termios,
outb(cval, uport->iobase + UART_LCR);
}
-static u8 mxser_check_modem_status(struct tty_struct *tty,
- struct mxser_port *port)
+static u8 mxser_check_modem_status(struct mxser_port *port)
{
struct uart_port *uport = &port->uport;
u8 msr = inb(uport->iobase + UART_MSR);
@@ -697,18 +659,10 @@ static u8 mxser_check_modem_status(struct tty_struct *tty,
if (msr & UART_MSR_DDSR)
uport->icount.dsr++;
if (msr & UART_MSR_DDCD)
- uport->icount.dcd++;
+ uart_handle_dcd_change(uport, msr & UART_MSR_DCD);
if (msr & UART_MSR_DCTS)
- uport->icount.cts++;
- wake_up_interruptible(&port->port.delta_msr_wait);
-
- if (tty_port_check_carrier(&port->port) && (msr & UART_MSR_DDCD)) {
- if (msr & UART_MSR_DCD)
- wake_up_interruptible(&port->port.open_wait);
- }
-
- if (tty_port_cts_enabled(&port->port))
- mxser_handle_cts(tty, port, msr);
+ mxser_handle_cts(port, msr);
+ wake_up_interruptible(&uport->state->port.delta_msr_wait);
return msr;
}
@@ -724,24 +678,16 @@ static void mxser_disable_and_clear_FIFO(struct mxser_port *info)
outb(fcr, uport->iobase + UART_FCR);
}
-static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
+static int mxser_startup(struct uart_port *uport)
{
- struct mxser_port *info = to_mport(port);
- struct uart_port *uport = &info->uport;
+ struct mxser_port *info = to_mport(uport);
unsigned long flags;
- int ret;
- ret = tty_port_alloc_xmit_buf(port);
- if (ret < 0)
- return ret;
-
- spin_lock_irqsave(&uport->lock, flags);
+ uart_port_lock_irqsave(uport, &flags);
if (!uport->type) {
- set_bit(TTY_IO_ERROR, &tty->flags);
- spin_unlock_irqrestore(&uport->lock, flags);
- ret = 0;
- goto err_free_xmit;
+ uart_port_unlock_irqrestore(uport, flags);
+ return -EINVAL;
}
/*
@@ -756,14 +702,8 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
* here.
*/
if (inb(uport->iobase + UART_LSR) == 0xff) {
- spin_unlock_irqrestore(&uport->lock, flags);
- if (capable(CAP_SYS_ADMIN)) {
- set_bit(TTY_IO_ERROR, &tty->flags);
- return 0;
- }
-
- ret = -ENODEV;
- goto err_free_xmit;
+ uart_port_unlock_irqrestore(uport, flags);
+ return -ENODEV;
}
/*
@@ -798,19 +738,9 @@ static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
(void) inb(uport->iobase + UART_IIR);
(void) inb(uport->iobase + UART_MSR);
- clear_bit(TTY_IO_ERROR, &tty->flags);
- kfifo_reset(&port->xmit_fifo);
-
- /*
- * and set the speed of the serial port
- */
- mxser_change_speed(tty, &tty->termios, NULL);
- spin_unlock_irqrestore(&uport->lock, flags);
+ uart_port_unlock_irqrestore(uport, flags);
return 0;
-err_free_xmit:
- tty_port_free_xmit_buf(port);
- return ret;
}
/*
@@ -818,9 +748,9 @@ err_free_xmit:
* tell the interrupt driver to stop checking the data ready bit in the line
* status register.
*/
-static void mxser_stop_rx(struct mxser_port *info)
+static void mxser_stop_rx(struct uart_port *uport)
{
- struct uart_port *uport = &info->uport;
+ struct mxser_port *info = to_mport(uport);
info->IER &= ~UART_IER_RLSI;
if (info->board->must_hwid)
@@ -832,21 +762,12 @@ static void mxser_stop_rx(struct mxser_port *info)
/*
* This routine will shutdown a serial port
*/
-static void mxser_shutdown_port(struct tty_port *port)
+static void mxser_shutdown(struct uart_port *uport)
{
- struct mxser_port *info = to_mport(port);
- struct uart_port *uport = &info->uport;
+ struct mxser_port *info = to_mport(uport);
unsigned long flags;
- spin_lock_irqsave(&uport->lock, flags);
-
- mxser_stop_rx(info);
-
- /*
- * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
- * here so the queue might never be waken up
- */
- wake_up_interruptible(&info->port.delta_msr_wait);
+ uart_port_lock_irqsave(uport, &flags);
info->IER = 0;
outb(0x00, uport->iobase + UART_IER);
@@ -861,146 +782,28 @@ static void mxser_shutdown_port(struct tty_port *port)
if (info->board->must_hwid)
mxser_must_no_sw_flow_control(uport->iobase);
- spin_unlock_irqrestore(&uport->lock, flags);
-
- /* make sure ISR is not running while we free the buffer */
- synchronize_irq(uport->irq);
-
- tty_port_free_xmit_buf(port);
-}
-
-/*
- * This routine is called whenever a serial port is opened. It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain. It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int mxser_open(struct tty_struct *tty, struct file *filp)
-{
- struct tty_port *tport = tty->port;
- struct mxser_port *port = to_mport(tport);
-
- tty->driver_data = port;
-
- return tty_port_open(tport, tty, filp);
+ uart_port_unlock_irqrestore(uport, flags);
}
-static void mxser_flush_buffer(struct tty_struct *tty)
+static void mxser_flush_buffer(struct uart_port *uport)
{
- struct mxser_port *info = tty->driver_data;
- struct uart_port *uport = &info->uport;
- unsigned long flags;
-
- spin_lock_irqsave(&uport->lock, flags);
- kfifo_reset(&info->port.xmit_fifo);
+ struct mxser_port *info = to_mport(uport);
outb(info->FCR | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
uport->iobase + UART_FCR);
-
- spin_unlock_irqrestore(&uport->lock, flags);
-
- tty_wakeup(tty);
}
-static void mxser_close(struct tty_struct *tty, struct file *filp)
+static int mxser_verify_port(struct uart_port *uport, struct serial_struct *ss)
{
- tty_port_close(tty->port, tty, filp);
-}
-
-static ssize_t mxser_write(struct tty_struct *tty, const u8 *buf, size_t count)
-{
- struct mxser_port *info = tty->driver_data;
- struct uart_port *uport = &info->uport;
- unsigned long flags;
- size_t written;
- bool is_empty;
-
- spin_lock_irqsave(&uport->lock, flags);
- written = kfifo_in(&info->port.xmit_fifo, buf, count);
- is_empty = kfifo_is_empty(&info->port.xmit_fifo);
- spin_unlock_irqrestore(&uport->lock, flags);
-
- if (!is_empty && !tty->flow.stopped)
- if (!uport->hw_stopped || mxser_16550A_or_MUST(info))
- mxser_start_tx(info);
-
- return written;
-}
-
-static int mxser_put_char(struct tty_struct *tty, u8 ch)
-{
- struct mxser_port *info = tty->driver_data;
- struct uart_port *uport = &info->uport;
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&uport->lock, flags);
- ret = kfifo_put(&info->port.xmit_fifo, ch);
- spin_unlock_irqrestore(&uport->lock, flags);
-
- return ret;
-}
-
-
-static void mxser_flush_chars(struct tty_struct *tty)
-{
- struct mxser_port *info = tty->driver_data;
- struct uart_port *uport = &info->uport;
-
- if (kfifo_is_empty(&info->port.xmit_fifo) || tty->flow.stopped ||
- (uport->hw_stopped && !mxser_16550A_or_MUST(info)))
- return;
-
- mxser_start_tx(info);
-}
-
-static unsigned int mxser_write_room(struct tty_struct *tty)
-{
- struct mxser_port *info = tty->driver_data;
-
- return kfifo_avail(&info->port.xmit_fifo);
-}
-
-static unsigned int mxser_chars_in_buffer(struct tty_struct *tty)
-{
- struct mxser_port *info = tty->driver_data;
-
- return kfifo_len(&info->port.xmit_fifo);
-}
-
-/*
- * ------------------------------------------------------------
- * friends of mxser_ioctl()
- * ------------------------------------------------------------
- */
-static int mxser_get_serial_info(struct tty_struct *tty,
- struct serial_struct *ss)
-{
- struct mxser_port *info = tty->driver_data;
- struct uart_port *uport = &info->uport;
- struct tty_port *port = &info->port;
- unsigned int closing_wait, close_delay;
-
- mutex_lock(&port->mutex);
+ if (ss->irq != uport->irq)
+ return -EINVAL;
+ if (ss->port != uport->iobase)
+ return -EINVAL;
- close_delay = jiffies_to_msecs(info->port.close_delay) / 10;
- closing_wait = info->port.closing_wait;
- if (closing_wait != ASYNC_CLOSING_WAIT_NONE)
- closing_wait = jiffies_to_msecs(closing_wait) / 10;
-
- ss->type = uport->type;
- ss->line = tty->index;
- ss->port = uport->iobase;
- ss->irq = uport->irq;
- ss->flags = info->port.flags;
- ss->baud_base = MXSER_BAUD_BASE;
- ss->close_delay = close_delay;
- ss->closing_wait = closing_wait;
- ss->custom_divisor = MXSER_CUSTOM_DIVISOR;
- mutex_unlock(&port->mutex);
return 0;
}
+#ifdef OLD
static int mxser_set_serial_info(struct tty_struct *tty,
struct serial_struct *ss)
{
@@ -1062,13 +865,13 @@ static int mxser_set_serial_info(struct tty_struct *tty,
uport->type = ss->type;
- mxser_process_txrx_fifo(info);
+ mxser_process_txrx_fifo(info); // TODO
}
if (tty_port_initialized(port)) {
if (old_speed != (port->flags & ASYNC_SPD_MASK)) {
spin_lock_irqsave(&uport->lock, sl_flags);
- mxser_change_speed(tty, &tty->termios, NULL);
+ mxser_change_speed(info, &tty->termios, NULL);
spin_unlock_irqrestore(&uport->lock, sl_flags);
}
} else {
@@ -1079,47 +882,15 @@ static int mxser_set_serial_info(struct tty_struct *tty,
mutex_unlock(&port->mutex);
return retval;
}
+#endif
-/*
- * mxser_get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * is emptied. On bus types like RS485, the transmitter must
- * release the bus after transmitting. This must be done when
- * the transmit shift register is empty, not be done when the
- * transmit holding register is empty. This functionality
- * allows an RS485 driver to be written in user space.
- */
-static int mxser_get_lsr_info(struct mxser_port *info,
- unsigned int __user *value)
+static unsigned int mxser_get_mctrl(struct uart_port *uport)
{
- struct uart_port *uport = &info->uport;
- unsigned char status;
- unsigned int result;
- unsigned long flags;
-
- spin_lock_irqsave(&uport->lock, flags);
- status = inb(uport->iobase + UART_LSR);
- spin_unlock_irqrestore(&uport->lock, flags);
- result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
- return put_user(result, value);
-}
+ struct mxser_port *info = to_mport(uport);
+ u8 msr, control;
-static int mxser_tiocmget(struct tty_struct *tty)
-{
- struct mxser_port *info = tty->driver_data;
- struct uart_port *uport = &info->uport;
- unsigned char control;
- unsigned long flags;
- u8 msr;
-
- if (tty_io_error(tty))
- return -EIO;
-
- spin_lock_irqsave(&uport->lock, flags);
control = info->MCR;
- msr = mxser_check_modem_status(tty, info);
- spin_unlock_irqrestore(&uport->lock, flags);
+ msr = mxser_check_modem_status(info);
return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
@@ -1129,55 +900,23 @@ static int mxser_tiocmget(struct tty_struct *tty)
((msr & UART_MSR_CTS) ? TIOCM_CTS : 0);
}
-static int mxser_tiocmset(struct tty_struct *tty,
- unsigned int set, unsigned int clear)
+static void mxser_set_mctrl(struct uart_port *uport, unsigned int mctrl)
{
- struct mxser_port *info = tty->driver_data;
- struct uart_port *uport = &info->uport;
- unsigned long flags;
-
- if (tty_io_error(tty))
- return -EIO;
-
- spin_lock_irqsave(&uport->lock, flags);
+ struct mxser_port *info = to_mport(uport);
- if (set & TIOCM_RTS)
+ if (mctrl & TIOCM_RTS)
info->MCR |= UART_MCR_RTS;
- if (set & TIOCM_DTR)
- info->MCR |= UART_MCR_DTR;
-
- if (clear & TIOCM_RTS)
+ else
info->MCR &= ~UART_MCR_RTS;
- if (clear & TIOCM_DTR)
+
+ if (mctrl & TIOCM_DTR)
+ info->MCR |= UART_MCR_DTR;
+ else
info->MCR &= ~UART_MCR_DTR;
outb(info->MCR, uport->iobase + UART_MCR);
- spin_unlock_irqrestore(&uport->lock, flags);
- return 0;
-}
-
-static int mxser_cflags_changed(struct mxser_port *info, unsigned long arg,
- struct uart_icount *cprev)
-{
- struct uart_port *uport = &info->uport;
- struct uart_icount cnow;
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&uport->lock, flags);
- cnow = uport->icount; /* atomic copy */
- spin_unlock_irqrestore(&uport->lock, flags);
-
- ret = ((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
- ((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
- ((arg & TIOCM_CD) && (cnow.dcd != cprev->dcd)) ||
- ((arg & TIOCM_CTS) && (cnow.cts != cprev->cts));
-
- *cprev = cnow;
-
- return ret;
}
-
+#ifdef OLD
/* We should likely switch to TIOCGRS485/TIOCSRS485. */
static int mxser_ioctl_op_mode(struct mxser_port *port, int index, bool set,
int __user *u_opmode)
@@ -1227,63 +966,7 @@ static int mxser_ioctl(struct tty_struct *tty,
return mxser_ioctl_op_mode(info, tty->index,
cmd == MOXA_SET_OP_MODE, argp);
- if (cmd != TIOCMIWAIT && tty_io_error(tty))
- return -EIO;
-
- switch (cmd) {
- case TIOCSERGETLSR: /* Get line status register */
- return mxser_get_lsr_info(info, argp);
- /*
- * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
- * - mask passed in arg for lines of interest
- * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
- * Caller should use TIOCGICOUNT to see which one it was
- */
- case TIOCMIWAIT:
- spin_lock_irqsave(&uport->lock, flags);
- cnow = uport->icount; /* note the counters on entry */
- spin_unlock_irqrestore(&uport->lock, flags);
-
- return wait_event_interruptible(info->port.delta_msr_wait,
- mxser_cflags_changed(info, arg, &cnow));
- default:
- return -ENOIOCTLCMD;
- }
- return 0;
-}
-
- /*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
-
-static int mxser_get_icount(struct tty_struct *tty,
- struct serial_icounter_struct *icount)
-
-{
- struct mxser_port *info = tty->driver_data;
- struct uart_port *uport = &info->uport;
- struct uart_icount cnow;
- unsigned long flags;
-
- spin_lock_irqsave(&uport->lock, flags);
- cnow = uport->icount;
- spin_unlock_irqrestore(&uport->lock, flags);
-
- icount->frame = cnow.frame;
- icount->brk = cnow.brk;
- icount->overrun = cnow.overrun;
- icount->buf_overrun = cnow.buf_overrun;
- icount->parity = cnow.parity;
- icount->rx = cnow.rx;
- icount->tx = cnow.tx;
- icount->cts = cnow.cts;
- icount->dsr = cnow.dsr;
- icount->rng = cnow.rng;
- icount->dcd = cnow.dcd;
- return 0;
+ return -EIO;
}
/*
@@ -1355,7 +1038,7 @@ static void mxser_stop(struct tty_struct *tty)
spin_lock_irqsave(&uport->lock, flags);
if (info->IER & UART_IER_THRI)
- __mxser_stop_tx(info);
+ mxser_stop_tx(uport);
spin_unlock_irqrestore(&uport->lock, flags);
}
@@ -1370,122 +1053,36 @@ static void mxser_start(struct tty_struct *tty)
__mxser_start_tx(info);
spin_unlock_irqrestore(&uport->lock, flags);
}
-
-static void mxser_set_termios(struct tty_struct *tty,
+#endif
+static void mxser_set_termios(struct uart_port *uport, struct ktermios *termios,
const struct ktermios *old_termios)
{
- struct ktermios *termios = &tty->termios;
- struct mxser_port *info = tty->driver_data;
- struct uart_port *uport = &info->uport;
- unsigned long flags;
-
- spin_lock_irqsave(&uport->lock, flags);
- mxser_change_speed(tty, termios, old_termios);
- spin_unlock_irqrestore(&uport->lock, flags);
-
- if ((old_termios->c_cflag & CRTSCTS) && !(termios->c_cflag & CRTSCTS)) {
- uport->hw_stopped = false;
- mxser_start(tty);
- }
-
- /* Handle sw stopped */
- if ((old_termios->c_iflag & IXON) && !(termios->c_iflag & IXON)) {
- tty->flow.stopped = 0;
-
- if (info->board->must_hwid) {
- spin_lock_irqsave(&uport->lock, flags);
- mxser_must_set_rx_sw_flow_control(uport->iobase, false);
- spin_unlock_irqrestore(&uport->lock, flags);
- }
-
- mxser_start(tty);
- }
-}
-
-static bool mxser_tx_empty(struct mxser_port *info)
-{
- struct uart_port *uport = &info->uport;
+ struct mxser_port *info = to_mport(uport);
unsigned long flags;
- u8 lsr;
-
- spin_lock_irqsave(&uport->lock, flags);
- lsr = inb(uport->iobase + UART_LSR);
- spin_unlock_irqrestore(&uport->lock, flags);
- return !(lsr & UART_LSR_TEMT);
+ uart_port_lock_irqsave(uport, &flags);
+ mxser_change_speed(info, termios, old_termios);
+ uart_port_unlock_irqrestore(uport, flags);
}
-/*
- * mxser_wait_until_sent() --- wait until the transmitter is empty
- */
-static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
+static const char *mxser_type(struct uart_port *port)
{
- struct mxser_port *info = tty->driver_data;
- struct uart_port *uport = &info->uport;
- unsigned long expire, char_time, fifo_timeout;
-
- if (uport->type == PORT_UNKNOWN)
- return;
-
- if (uport->fifosize == 0)
- return; /* Just in case.... */
-
- /*
- * Set the check interval to be 1/5 of the estimated time to
- * send a single character, and make it at least 1. The check
- * interval should also be less than the timeout.
- *
- * Note: we have to use pretty tight timings here to satisfy
- * the NIST-PCTS.
- */
- char_time = max(nsecs_to_jiffies(uport->frame_time / 5), 1UL);
- if (timeout && timeout < char_time)
- char_time = timeout;
-
- char_time = jiffies_to_msecs(char_time);
-
- /*
- * If the transmitter hasn't cleared in twice the approximate
- * amount of time to send the entire FIFO, it probably won't
- * ever clear. This assumes the UART isn't doing flow
- * control, which is currently the case. Hence, if it ever
- * takes longer than uport->timeout, this is probably due to a
- * UART bug of some kind. So, we clamp the timeout parameter at
- * 2*uport->timeout.
- */
- fifo_timeout = uart_fifo_timeout(uport);
- if (!timeout || timeout > 2 * fifo_timeout)
- timeout = 2 * fifo_timeout;
-
- expire = jiffies + timeout;
-
- while (mxser_tx_empty(info)) {
- msleep_interruptible(char_time);
- if (signal_pending(current))
- break;
- if (time_after(jiffies, expire))
- break;
- }
+ return port->type == PORT_16550A ? "16550A" : NULL;
}
-/*
- * This routine is called by tty_hangup() when a hangup is signaled.
- */
-static void mxser_hangup(struct tty_struct *tty)
+static unsigned int mxser_tx_empty(struct uart_port *uport)
{
- struct mxser_port *info = tty->driver_data;
+ if (inb(uport->iobase + UART_LSR) & UART_LSR_TEMT)
+ return TIOCSER_TEMT;
- mxser_flush_buffer(tty);
- tty_port_hangup(&info->port);
+ return 0;
}
/*
- * mxser_rs_break() --- routine which turns the break handling on or off
+ * mxser_break_ctl() --- routine which turns the break handling on or off
*/
-static int mxser_rs_break(struct tty_struct *tty, int break_state)
+static void mxser_break_ctl(struct uart_port *uport, int break_state)
{
- struct mxser_port *info = tty->driver_data;
- struct uart_port *uport = &info->uport;
unsigned long flags;
u8 lcr;
@@ -1495,10 +1092,9 @@ static int mxser_rs_break(struct tty_struct *tty, int break_state)
lcr |= UART_LCR_SBC;
else
lcr &= ~UART_LCR_SBC;
+
outb(lcr, uport->iobase + UART_LCR);
spin_unlock_irqrestore(&uport->lock, flags);
-
- return 0;
}
static bool mxser_receive_chars_new(struct mxser_port *port, u8 status)
@@ -1518,15 +1114,14 @@ static bool mxser_receive_chars_new(struct mxser_port *port, u8 status)
while (gdl--) {
u8 ch = inb(uport->iobase + UART_RX);
- if (!tty_insert_flip_char(&port->port, ch, 0))
- uport->icount.buf_overrun++;
+ if (!uart_prepare_sysrq_char(uport, ch))
+ uart_insert_char(uport, 0, 0, ch, 0);
}
return true;
}
-static u8 mxser_receive_chars_old(struct tty_struct *tty,
- struct mxser_port *port, u8 status)
+static u8 mxser_receive_chars_old(struct mxser_port *port, u8 status)
{
struct uart_port *uport = &port->uport;
enum mxser_must_hwid hwid = port->board->must_hwid;
@@ -1552,9 +1147,8 @@ static u8 mxser_receive_chars_old(struct tty_struct *tty,
if (status & UART_LSR_BI) {
flag = TTY_BREAK;
uport->icount.brk++;
-
- if (port->port.flags & ASYNC_SAK)
- do_SAK(tty);
+ if (uart_handle_break(uport))
+ continue;
} else if (status & UART_LSR_PE) {
flag = TTY_PARITY;
uport->icount.parity++;
@@ -1566,10 +1160,9 @@ static u8 mxser_receive_chars_old(struct tty_struct *tty,
uport->icount.overrun++;
}
}
- if (!tty_insert_flip_char(&port->port, ch, flag)) {
- uport->icount.buf_overrun++;
- break;
- }
+ if (!uart_prepare_sysrq_char(uport, ch))
+ uart_insert_char(uport, status, UART_LSR_OE, ch,
+ flag);
}
if (hwid)
@@ -1581,20 +1174,20 @@ static u8 mxser_receive_chars_old(struct tty_struct *tty,
return status;
}
-static u8 mxser_receive_chars(struct tty_struct *tty,
- struct mxser_port *port, u8 status)
+static u8 mxser_receive_chars(struct mxser_port *port, u8 status)
{
if (!mxser_receive_chars_new(port, status))
- status = mxser_receive_chars_old(tty, port, status);
+ status = mxser_receive_chars_old(port, status);
- tty_flip_buffer_push(&port->port);
+ tty_flip_buffer_push(&port->uport.state->port);
return status;
}
-static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port)
+static void mxser_transmit_chars(struct mxser_port *port)
{
struct uart_port *uport = &port->uport;
+ struct tty_port *tport = &uport->state->port;
int count;
if (uport->x_char) {
@@ -1604,9 +1197,10 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port
return;
}
- if (kfifo_is_empty(&port->port.xmit_fifo) || tty->flow.stopped ||
- (uport->hw_stopped && !mxser_16550A_or_MUST(port))) {
- __mxser_stop_tx(port);
+ if (kfifo_is_empty(&tport->xmit_fifo) ||
+ (tport->tty && tport->tty->flow.stopped) ||
+ (uport->hw_stopped && !mxser_16550A_or_MUST(port))) {
+ mxser_stop_tx(uport);
return;
}
@@ -1614,42 +1208,30 @@ static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port
do {
u8 c;
- if (!kfifo_get(&port->port.xmit_fifo, &c))
+ if (!kfifo_get(&tport->xmit_fifo, &c))
break;
outb(c, uport->iobase + UART_TX);
uport->icount.tx++;
} while (--count > 0);
- if (kfifo_len(&port->port.xmit_fifo) < WAKEUP_CHARS)
- tty_wakeup(tty);
+ if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
+ uart_write_wakeup(uport);
- if (kfifo_is_empty(&port->port.xmit_fifo))
- __mxser_stop_tx(port);
+ if (kfifo_is_empty(&tport->xmit_fifo))
+ mxser_stop_tx(uport);
}
static bool mxser_port_isr(struct mxser_port *port)
{
struct uart_port *uport = &port->uport;
- struct tty_struct *tty;
u8 iir, status;
- bool error = false;
iir = inb(uport->iobase + UART_IIR);
if (iir & UART_IIR_NO_INT)
return true;
iir &= MOXA_MUST_IIR_MASK;
- tty = tty_port_tty_get(&port->port);
- if (!tty) {
- status = inb(uport->iobase + UART_LSR);
- outb(port->FCR | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
- uport->iobase + UART_FCR);
- inb(uport->iobase + UART_MSR);
-
- error = true;
- goto put_tty;
- }
status = inb(uport->iobase + UART_LSR);
@@ -1658,29 +1240,25 @@ static bool mxser_port_isr(struct mxser_port *port)
iir == MOXA_MUST_IIR_RDA ||
iir == MOXA_MUST_IIR_RTO ||
iir == MOXA_MUST_IIR_LSR)
- status = mxser_receive_chars(tty, port, status);
+ status = mxser_receive_chars(port, status);
} else {
status &= uport->read_status_mask;
if (status & UART_LSR_DR)
- status = mxser_receive_chars(tty, port, status);
+ status = mxser_receive_chars(port, status);
}
- mxser_check_modem_status(tty, port);
+ mxser_check_modem_status(port);
if (port->board->must_hwid) {
if (iir == 0x02 && (status & UART_LSR_THRE))
- mxser_transmit_chars(tty, port);
+ mxser_transmit_chars(port);
} else {
if (status & UART_LSR_THRE)
- mxser_transmit_chars(tty, port);
+ mxser_transmit_chars(port);
}
-put_tty:
- tty_kref_put(tty);
-
- return error;
+ return false;
}
-
/*
* This is the serial driver's generic interrupt routine
*/
@@ -1709,50 +1287,48 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
uport = &port->uport;
int_cnt = 0;
- spin_lock(&uport->lock);
+ uart_port_lock(uport);
do {
if (mxser_port_isr(port))
break;
} while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
- spin_unlock(&uport->lock);
+ uart_port_unlock(uport);
}
}
return handled;
}
-static const struct tty_operations mxser_ops = {
- .open = mxser_open,
- .close = mxser_close,
- .write = mxser_write,
- .put_char = mxser_put_char,
- .flush_chars = mxser_flush_chars,
- .write_room = mxser_write_room,
- .chars_in_buffer = mxser_chars_in_buffer,
- .flush_buffer = mxser_flush_buffer,
- .ioctl = mxser_ioctl,
- .throttle = mxser_throttle,
- .unthrottle = mxser_unthrottle,
- .set_termios = mxser_set_termios,
- .stop = mxser_stop,
- .start = mxser_start,
- .hangup = mxser_hangup,
- .break_ctl = mxser_rs_break,
- .wait_until_sent = mxser_wait_until_sent,
- .tiocmget = mxser_tiocmget,
- .tiocmset = mxser_tiocmset,
- .set_serial = mxser_set_serial_info,
- .get_serial = mxser_get_serial_info,
- .get_icount = mxser_get_icount,
+static struct uart_driver mxser_uart_driver = {
+ .owner = THIS_MODULE,
+ .dev_name = "ttyMI",
+ .nr = MXSER_PORTS,
};
-static const struct tty_port_operations mxser_port_ops = {
- .carrier_raised = mxser_carrier_raised,
- .dtr_rts = mxser_dtr_rts,
- .activate = mxser_activate,
- .shutdown = mxser_shutdown_port,
+static void mxser_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE)
+ port->type = PORT_16550A;
+}
+
+static const struct uart_ops mxser_ops = {
+ .tx_empty = mxser_tx_empty,
+ .get_mctrl = mxser_get_mctrl,
+ .set_mctrl = mxser_set_mctrl,
+ .stop_tx = mxser_stop_tx,
+ .start_tx = mxser_start_tx,
+ .stop_rx = mxser_stop_rx,
+ .break_ctl = mxser_break_ctl,
+ .startup = mxser_startup,
+ .shutdown = mxser_shutdown,
+ .flush_buffer = mxser_flush_buffer,
+ .set_termios = mxser_set_termios,
+ .type = mxser_type,
+ .config_port = mxser_config_port,
+ .verify_port = mxser_verify_port,
};
+
/*
* The MOXA Smartio/Industio serial driver boot-time initialization code!
*/
@@ -1804,8 +1380,6 @@ static void mxser_initbrd(struct pci_dev *pdev, struct mxser_board *brd,
else
info->opmode_ioaddr = brd->vector + 0x0c;
}
- tty_port_init(&info->port);
- info->port.ops = &mxser_port_ops;
info->board = brd;
uport->iobase = ioaddress + 8 * i;
@@ -1813,12 +1387,15 @@ static void mxser_initbrd(struct pci_dev *pdev, struct mxser_board *brd,
if (brd->must_hwid != MOXA_OTHER_UART)
mxser_must_set_enhance_mode(uport->iobase, true);
- uport->type = PORT_16550A;
+ uport->dev = &pdev->dev;
+ uport->iotype = UPIO_PORT;
+ uport->irq = pdev->irq;
+ uport->ops = &mxser_ops;
+ uport->flags = UPF_BOOT_AUTOCONF;
+ uport->line = i;
mxser_process_txrx_fifo(info);
- spin_lock_init(&uport->lock);
-
/* before set INT ISR, disable all int */
outb(inb(uport->iobase + UART_IER) & 0xf0,
uport->iobase + UART_IER);
@@ -1829,9 +1406,8 @@ static int mxser_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct mxser_board *brd;
- unsigned int i, base;
+ unsigned int i;
unsigned short nports = mxser_get_nports(pdev);
- struct device *tty_dev;
int retval = -EINVAL;
i = find_first_zero_bit(mxser_boards, MXSER_BOARDS);
@@ -1848,7 +1424,6 @@ static int mxser_probe(struct pci_dev *pdev,
brd->idx = i;
__set_bit(brd->idx, mxser_boards);
- base = i * MXSER_PORTS_PER_BOARD;
retval = pcim_enable_device(pdev);
if (retval) {
@@ -1872,27 +1447,23 @@ static int mxser_probe(struct pci_dev *pdev,
IRQF_SHARED, "mxser", brd);
if (retval) {
dev_err(&pdev->dev, "request irq failed");
- goto err_relbrd;
+ goto err_zero;
}
for (i = 0; i < nports; i++) {
- tty_dev = tty_port_register_device(&brd->ports[i].port,
- mxvar_sdriver, base + i, &pdev->dev);
- if (IS_ERR(tty_dev)) {
- retval = PTR_ERR(tty_dev);
+ retval = uart_add_one_port(&mxser_uart_driver,
+ &brd->ports[i].uport);
+ if (retval) {
for (; i > 0; i--)
- tty_unregister_device(mxvar_sdriver,
- base + i - 1);
- goto err_relbrd;
+ uart_remove_one_port(&mxser_uart_driver,
+ &brd->ports[i - 1].uport);
+ goto err_zero;
}
}
pci_set_drvdata(pdev, brd);
return 0;
-err_relbrd:
- for (i = 0; i < nports; i++)
- tty_port_destroy(&brd->ports[i].port);
err_zero:
__clear_bit(brd->idx, mxser_boards);
err:
@@ -1902,12 +1473,10 @@ err:
static void mxser_remove(struct pci_dev *pdev)
{
struct mxser_board *brd = pci_get_drvdata(pdev);
- unsigned int i, base = brd->idx * MXSER_PORTS_PER_BOARD;
+ unsigned int i;
- for (i = 0; i < brd->nports; i++) {
- tty_unregister_device(mxvar_sdriver, base + i);
- tty_port_destroy(&brd->ports[i].port);
- }
+ for (i = 0; i < brd->nports; i++)
+ uart_remove_one_port(&mxser_uart_driver, &brd->ports[i].uport);
__clear_bit(brd->idx, mxser_boards);
}
@@ -1923,27 +1492,11 @@ static int __init mxser_module_init(void)
{
int retval;
- mxvar_sdriver = tty_alloc_driver(MXSER_PORTS, TTY_DRIVER_REAL_RAW |
- TTY_DRIVER_DYNAMIC_DEV);
- if (IS_ERR(mxvar_sdriver))
- return PTR_ERR(mxvar_sdriver);
-
- /* Initialize the tty_driver structure */
- mxvar_sdriver->name = "ttyMI";
- mxvar_sdriver->major = ttymajor;
- mxvar_sdriver->minor_start = 0;
- mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL;
- mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
- mxvar_sdriver->init_termios = tty_std_termios;
- mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
- tty_set_operations(mxvar_sdriver, &mxser_ops);
-
- retval = tty_register_driver(mxvar_sdriver);
- if (retval) {
- printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family "
- "tty driver !\n");
- goto err_put;
- }
+ mxser_uart_driver.major = ttymajor;
+
+ retval = uart_register_driver(&mxser_uart_driver);
+ if (retval)
+ return retval;
retval = pci_register_driver(&mxser_driver);
if (retval) {
@@ -1953,17 +1506,14 @@ static int __init mxser_module_init(void)
return 0;
err_unr:
- tty_unregister_driver(mxvar_sdriver);
-err_put:
- tty_driver_kref_put(mxvar_sdriver);
+ uart_unregister_driver(&mxser_uart_driver);
return retval;
}
static void __exit mxser_module_exit(void)
{
pci_unregister_driver(&mxser_driver);
- tty_unregister_driver(mxvar_sdriver);
- tty_driver_kref_put(mxvar_sdriver);
+ uart_unregister_driver(&mxser_uart_driver);
}
module_init(mxser_module_init);
glossary
--------
Commit objects reference one tree, and zero or more parents.
Single parent commits can typically generate a patch in
unified diff format via `git format-patch'.
Multiple parents means the commit is a merge.
Root commits have no ancestor. Note that it is
possible to have multiple root commits when merging independent histories.
Every commit references one top-level tree object.
git clone https://yhbt.net/lore/pub/scm/linux/kernel/git/jirislaby/linux.git