diff options
| author | Russell King <rmk@flint.arm.linux.org.uk> | 2003-03-09 14:31:24 +0000 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-03-09 14:31:24 +0000 |
| commit | d9a6bc6ef013bb6bad03b760fb00219b72a5f8a7 (patch) | |
| tree | 7a31b2b68212caee93b738261734d8a03f546689 | |
| parent | 1208e2cb97bcf3492cd37ae3b048046abecba150 (diff) | |
[SERIAL] Add per-port semaphore.
Add a per-port semaphore to protect against simultaneous opens,
closes, hangups, and the like. This removes the need for the
UIF_CLOSING flag, as well as the extra tests and wait queues.
Disable the old PM code for now - it is incompatible with the
per-port semaphore.
| -rw-r--r-- | drivers/serial/core.c | 402 | ||||
| -rw-r--r-- | include/linux/serial_core.h | 3 |
2 files changed, 201 insertions, 204 deletions
diff --git a/drivers/serial/core.c b/drivers/serial/core.c index 2361d96c1260..54854cb06321 100644 --- a/drivers/serial/core.c +++ b/drivers/serial/core.c @@ -21,9 +21,6 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id: core.c,v 1.100 2002/07/28 10:03:28 rmk Exp $ - * */ #include <linux/config.h> #include <linux/module.h> @@ -58,6 +55,8 @@ static DECLARE_MUTEX(port_sem); #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) +#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->blocked_open : 0)) + static void uart_change_speed(struct uart_state *state, struct termios *old_termios); static void uart_wait_until_sent(struct tty_struct *tty, int timeout); @@ -138,7 +137,7 @@ uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) /* * Startup the port. This will be called once per open. All calls - * will be serialised by the global port semaphore. + * will be serialised by the per-port semaphore. */ static int uart_startup(struct uart_state *state, int init_hw) { @@ -196,8 +195,7 @@ static int uart_startup(struct uart_state *state, int init_hw) info->flags |= UIF_INITIALIZED; - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); + clear_bit(TTY_IO_ERROR, &info->tty->flags); } if (retval && capable(CAP_SYS_ADMIN)) @@ -209,7 +207,7 @@ static int uart_startup(struct uart_state *state, int init_hw) /* * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. Calls to - * uart_shutdown are serialised by port_sem. + * uart_shutdown are serialised by the per-port semaphore. */ static void uart_shutdown(struct uart_state *state) { @@ -694,7 +692,7 @@ uart_set_info(struct uart_state *state, struct serial_struct *newinfo) * module insertion/removal doesn't change anything * under us. */ - down(&port_sem); + down(&state->sem); change_irq = new_serial.irq != port->irq; @@ -747,14 +745,14 @@ uart_set_info(struct uart_state *state, struct serial_struct *newinfo) /* * Make sure that we are the sole user of this port. */ - if (state->count > 1 || state->info->blocked_open != 0) + if (uart_users(state) > 1) goto exit; /* * We need to shutdown the serial port at the old * port/type/irq combination. */ - uart_shutdown(state->info); + uart_shutdown(state); } if (change_port) { @@ -820,7 +818,7 @@ uart_set_info(struct uart_state *state, struct serial_struct *newinfo) state->close_delay = new_serial.close_delay * HZ / 100; state->closing_wait = new_serial.closing_wait * HZ / 100; port->fifosize = new_serial.xmit_fifo_size; - if (state->info && state->info->tty) + if (state->info->tty) state->info->tty->low_latency = (port->flags & UPF_LOW_LATENCY) ? 1 : 0; @@ -828,7 +826,7 @@ uart_set_info(struct uart_state *state, struct serial_struct *newinfo) retval = 0; if (port->type == PORT_UNKNOWN) goto exit; - if (state->info && state->info->flags & UIF_INITIALIZED) { + if (state->info->flags & UIF_INITIALIZED) { if (((old_flags ^ port->flags) & UPF_SPD_MASK) || old_custom_divisor != port->custom_divisor) { /* If they're setting up a custom divisor or speed, @@ -844,13 +842,14 @@ uart_set_info(struct uart_state *state, struct serial_struct *newinfo) } else retval = uart_startup(state, 1); exit: - up(&port_sem); + up(&state->sem); return retval; } /* - * uart_get_lsr_info - get line status register info + * uart_get_lsr_info - get line status register info. + * Note: uart_ioctl protects us against hangups. */ static int uart_get_lsr_info(struct uart_state *state, unsigned int *value) { @@ -933,16 +932,16 @@ static int uart_do_autoconfig(struct uart_state *state) return -EPERM; /* - * Take the 'count' lock. This prevents count - * from incrementing, and hence any extra opens - * of the port while we're auto-configging. + * Take the per-port semaphore. This prevents count from + * changing, and hence any extra opens of the port while + * we're auto-configuring. */ - if (down_interruptible(&port_sem)) + if (down_interruptible(&state->sem)) return -ERESTARTSYS; ret = -EBUSY; - if (state->count == 1 && state->info->blocked_open == 0) { - uart_shutdown(state->info); + if (uart_users(state) == 1) { + uart_shutdown(state); /* * If we already have a port type configured, @@ -963,10 +962,16 @@ static int uart_do_autoconfig(struct uart_state *state) ret = uart_startup(state, 1); } - up(&port_sem); + up(&state->sem); return ret; } +/* + * 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 + */ static int uart_wait_modem_status(struct uart_state *state, unsigned long arg) { @@ -1021,105 +1026,132 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg) } /* + * 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 +uart_get_count(struct uart_state *state, struct serial_icounter_struct *icnt) +{ + struct serial_icounter_struct icount; + struct uart_icount cnow; + struct uart_port *port = state->port; + + spin_lock_irq(&port->lock); + memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); + spin_unlock_irq(&port->lock); + + icount.cts = cnow.cts; + icount.dsr = cnow.dsr; + icount.rng = cnow.rng; + icount.dcd = cnow.dcd; + icount.rx = cnow.rx; + icount.tx = cnow.tx; + icount.frame = cnow.frame; + icount.overrun = cnow.overrun; + icount.parity = cnow.parity; + icount.brk = cnow.brk; + icount.buf_overrun = cnow.buf_overrun; + + return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0; +} + +/* * Called via sys_ioctl under the BKL. We can use spin_lock_irq() here. */ static int -uart_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, +uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg) { struct uart_state *state = tty->driver_data; - struct serial_icounter_struct icount; - struct uart_icount cnow; int ret = -ENOIOCTLCMD; BUG_ON(!kernel_locked()); - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; + /* + * These ioctls don't rely on the hardware to be present. + */ + switch (cmd) { + case TIOCGSERIAL: + ret = uart_get_info(state, (struct serial_struct *)arg); + break; + + case TIOCSSERIAL: + ret = uart_set_info(state, (struct serial_struct *)arg); + break; + + case TIOCSERCONFIG: + ret = uart_do_autoconfig(state); + break; + + case TIOCSERGWILD: /* obsolete */ + case TIOCSERSWILD: /* obsolete */ + ret = 0; + break; } - switch (cmd) { - case TIOCMGET: - ret = uart_get_modem_info(state->port, - (unsigned int *)arg); - break; + if (ret != -ENOIOCTLCMD) + goto out; - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - ret = uart_set_modem_info(state->port, cmd, - (unsigned int *)arg); - break; + if (tty->flags & (1 << TTY_IO_ERROR)) { + ret = -EIO; + goto out; + } - case TIOCGSERIAL: - ret = uart_get_info(state, (struct serial_struct *)arg); - break; + /* + * The following should only be used when hardware is present. + */ + switch (cmd) { + case TIOCMIWAIT: + ret = uart_wait_modem_status(state, arg); + break; - case TIOCSSERIAL: - ret = uart_set_info(state, (struct serial_struct *)arg); - break; + case TIOCGICOUNT: + ret = uart_get_count(state, (struct serial_icounter_struct *)arg); + break; + } - case TIOCSERCONFIG: - ret = uart_do_autoconfig(state); - break; + if (ret != -ENOIOCTLCMD) + goto out; - case TIOCSERGETLSR: /* Get line status register */ - ret = uart_get_lsr_info(state, (unsigned int *)arg); - break; + down(&state->sem); - /* - * 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: - ret = uart_wait_modem_status(state, arg); - break; + if (tty_hung_up_p(filp)) { + ret = -EIO; + goto out_up; + } - /* - * 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. - */ - case TIOCGICOUNT: - spin_lock_irq(&state->port->lock); - memcpy(&cnow, &state->port->icount, - sizeof(struct uart_icount)); - spin_unlock_irq(&state->port->lock); - - icount.cts = cnow.cts; - icount.dsr = cnow.dsr; - icount.rng = cnow.rng; - icount.dcd = cnow.dcd; - icount.rx = cnow.rx; - icount.tx = cnow.tx; - icount.frame = cnow.frame; - icount.overrun = cnow.overrun; - icount.parity = cnow.parity; - icount.brk = cnow.brk; - icount.buf_overrun = cnow.buf_overrun; - - ret = copy_to_user((void *)arg, &icount, sizeof(icount)) - ? -EFAULT : 0; - break; + /* + * All these rely on hardware being present and need to be + * protected against the tty being hung up. + */ + switch (cmd) { + case TIOCMGET: + ret = uart_get_modem_info(state->port, (unsigned int *)arg); + break; - case TIOCSERGWILD: /* obsolete */ - case TIOCSERSWILD: /* obsolete */ - ret = 0; - break; + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + ret = uart_set_modem_info(state->port, cmd, + (unsigned int *)arg); + break; - default: { - struct uart_port *port = state->port; - if (port->ops->ioctl) - ret = port->ops->ioctl(port, cmd, arg); - break; - } + case TIOCSERGETLSR: /* Get line status register */ + ret = uart_get_lsr_info(state, (unsigned int *)arg); + break; + + default: { + struct uart_port *port = state->port; + if (port->ops->ioctl) + ret = port->ops->ioctl(port, cmd, arg); + break; } + } + out_up: + up(&state->sem); + out: return ret; } @@ -1186,23 +1218,15 @@ static void uart_close(struct tty_struct *tty, struct file *filp) { struct uart_state *state = tty->driver_data; struct uart_port *port = state->port; - unsigned long flags; BUG_ON(!kernel_locked()); + DPRINTK("uart_close(%d) called\n", port->line); - if (!state->info) - return; - - DPRINTK("uart_close() called\n"); + down(&state->sem); - /* - * This is safe, as long as the BKL exists in - * do_tty_hangup(), and we're protected by the BKL. - */ if (tty_hung_up_p(filp)) goto done; - spin_lock_irqsave(&state->port->lock, flags); if ((tty->count == 1) && (state->count != 1)) { /* * Uh, oh. tty->count is 1, which means that the tty @@ -1220,23 +1244,16 @@ static void uart_close(struct tty_struct *tty, struct file *filp) tty->driver.name, port->line, state->count); state->count = 0; } - if (state->count) { - spin_unlock_irqrestore(&state->port->lock, flags); + if (state->count) goto done; - } - - /* - * The UIF_CLOSING flag protects us against further opens - * of this port. - */ - state->info->flags |= UIF_CLOSING; - spin_unlock_irqrestore(&state->port->lock, flags); /* * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. + * the line discipline to only process XON/XOFF characters by + * setting tty->closing. */ tty->closing = 1; + if (state->closing_wait != USF_CLOSING_WAIT_NONE) tty_wait_until_sent(tty, state->closing_wait); @@ -1245,6 +1262,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) * disable the receive line status interrupts. */ if (state->info->flags & UIF_INITIALIZED) { + unsigned long flags; spin_lock_irqsave(&port->lock, flags); port->ops->stop_rx(port); spin_unlock_irqrestore(&port->lock, flags); @@ -1255,14 +1273,14 @@ static void uart_close(struct tty_struct *tty, struct file *filp) */ uart_wait_until_sent(tty, port->timeout); } - down(&port_sem); - uart_shutdown(state->info); - up(&port_sem); + + uart_shutdown(state); uart_flush_buffer(tty); if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); tty->closing = 0; state->info->tty = NULL; + if (state->info->blocked_open) { if (state->close_delay) { set_current_state(TASK_INTERRUPTIBLE); @@ -1270,25 +1288,18 @@ static void uart_close(struct tty_struct *tty, struct file *filp) set_current_state(TASK_RUNNING); } } else { -#ifdef CONFIG_PM - /* - * Put device into D3 state. - */ - pm_send(state->pm, PM_SUSPEND, (void *)3); -#else if (port->ops->pm) port->ops->pm(port, 3, 0); -#endif } /* * Wake up anyone trying to open this port. */ - state->info->flags &= ~(UIF_NORMAL_ACTIVE|UIF_CLOSING); + state->info->flags &= ~UIF_NORMAL_ACTIVE; wake_up_interruptible(&state->info->open_wait); done: - ; + up(&state->sem); } static void uart_wait_until_sent(struct tty_struct *tty, int timeout) @@ -1361,19 +1372,18 @@ static void uart_hangup(struct tty_struct *tty) struct uart_state *state = tty->driver_data; BUG_ON(!kernel_locked()); + DPRINTK("uart_hangup(%d)\n", state->port->line); - uart_flush_buffer(tty); - down(&port_sem); - if (state->info->flags & UIF_CLOSING) { - up(&port_sem); - return; + down(&state->sem); + if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) { + uart_flush_buffer(tty); + uart_shutdown(state); + state->count = 0; + state->info->flags &= ~UIF_NORMAL_ACTIVE; + state->info->tty = NULL; + wake_up_interruptible(&state->info->open_wait); } - uart_shutdown(state->info); - state->count = 0; - state->info->flags &= ~UIF_NORMAL_ACTIVE; - state->info->tty = NULL; - up(&port_sem); - wake_up_interruptible(&state->info->open_wait); + up(&state->sem); } /* @@ -1414,6 +1424,10 @@ static void uart_update_termios(struct uart_state *state) } } +/* + * Block the open until the port is ready. We must be called with + * the per-port semaphore held. + */ static int uart_block_til_ready(struct file *filp, struct uart_state *state) { @@ -1431,18 +1445,10 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) /* * If we have been hung up, tell userspace/restart open. */ - if (tty_hung_up_p(filp)) + if (tty_hung_up_p(filp) || info->tty == NULL) break; /* - * If the device is in the middle of being closed, block - * until it's done. We will need to re-initialise the - * port. Hmm, is it legal to block a non-blocking open? - */ - if (info->flags & UIF_CLOSING) - goto wait; - - /* * If the port has been closed, tell userspace/restart open. */ if (!(info->flags & UIF_INITIALIZED)) @@ -1478,8 +1484,9 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) if (port->ops->get_mctrl(port) & TIOCM_CAR) break; - wait: + up(&state->sem); schedule(); + down(&state->sem); if (signal_pending(current)) break; @@ -1493,10 +1500,7 @@ uart_block_til_ready(struct file *filp, struct uart_state *state) if (signal_pending(current)) return -ERESTARTSYS; - if (info->tty->flags & (1 << TTY_IO_ERROR)) - return 0; - - if (tty_hung_up_p(filp) || !(info->flags & UIF_INITIALIZED)) + if (!info->tty || tty_hung_up_p(filp)) return (port->flags & UPF_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS; @@ -1509,11 +1513,17 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) down(&port_sem); state = drv->state + line; + if (down_interruptible(&state->sem)) { + state = ERR_PTR(-ERESTARTSYS); + goto out; + } + state->count++; if (!state->port) { - up(&port_sem); state->count--; - return ERR_PTR(-ENXIO); + up(&state->sem); + state = ERR_PTR(-ENXIO); + goto out; } if (!state->info) { @@ -1530,14 +1540,15 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) tasklet_init(&state->info->tlet, uart_tasklet_action, (unsigned long)state); - up(&port_sem); } else { state->count--; - up(&port_sem); - return ERR_PTR(-ENOMEM); + up(&state->sem); + state = ERR_PTR(-ENOMEM); } } + out: + up(&port_sem); return state; } @@ -1558,7 +1569,6 @@ static int uart_open(struct tty_struct *tty, struct file *filp) int retval, line = minor(tty->device) - tty->driver.minor_start; BUG_ON(!kernel_locked()); - DPRINTK("uart_open(%d) called\n", line); /* @@ -1571,8 +1581,11 @@ static int uart_open(struct tty_struct *tty, struct file *filp) goto fail; /* - * FIXME: This one isn't fun. We can't guarantee that the tty isn't - * already in open, nor can we guarantee the state of tty->driver_data + * We take the semaphore inside uart_get to guarantee that we won't + * be re-entered while allocating the info structure, or while we + * request any IRQs that the driver may need. This also has the nice + * side-effect that it delays the action of uart_hangup, so we can + * guarantee that info->tty will always contain something reasonable. */ state = uart_get(drv, line); if (IS_ERR(state)) { @@ -1593,11 +1606,11 @@ static int uart_open(struct tty_struct *tty, struct file *filp) /* * If the port is in the middle of closing, bail out now. */ - if (tty_hung_up_p(filp) || (state->info->flags & UIF_CLOSING)) { - wait_event_interruptible(state->info->open_wait, - !(state->info->flags & UIF_CLOSING)); + if (tty_hung_up_p(filp)) { retval = (state->port->flags & UPF_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS; + state->count--; + up(&state->sem); goto fail; } @@ -1605,30 +1618,22 @@ static int uart_open(struct tty_struct *tty, struct file *filp) * Make sure the device is in D0 state. */ if (state->count == 1) { -#ifdef CONFIG_PM - pm_send(state->pm, PM_RESUME, (void *)0); -#else struct uart_port *port = state->port; if (port->ops->pm) port->ops->pm(port, 0, 3); -#endif } /* - * Start up the serial port. We have this semaphore here to - * prevent uart_startup or uart_shutdown being re-entered if - * we sleep while requesting an IRQ. + * Start up the serial port. */ - down(&port_sem); retval = uart_startup(state, 0); - up(&port_sem); - if (retval) - goto fail; /* - * Wait until the port is ready. + * If we succeeded, wait until the port is ready. */ - retval = uart_block_til_ready(filp, state); + if (retval == 0) + retval = uart_block_til_ready(filp, state); + up(&state->sem); /* * If this is the first open to succeed, adjust things to suit. @@ -1900,8 +1905,8 @@ static int uart_pm_set_state(struct uart_state *state, int pm_state, int oldstat port = state->port; ops = port->ops; - DPRINTK("pm: %08x: %d -> %d, %srunning\n", - port->iobase, dev->state, pm_state, running ? "" : "not "); + DPRINTK("pm: %08x: %ld -> %d, %srunning\n", + port->iobase, state->pm->state, pm_state, running ? "" : "not "); if (pm_state == 0) { if (ops->pm) @@ -2051,42 +2056,33 @@ __uart_register_port(struct uart_driver *drv, struct uart_state *state, port->ops->set_mctrl(port, 0); spin_unlock_irqrestore(&port->lock, flags); -#ifdef CONFIG_PM +#if 0 //def CONFIG_PM /* * Power down all ports by default, except the * console if we have one. We need to drop the * port semaphore here. */ if (state->pm && (!drv->cons || port->line != drv->cons->index)) { - up(&port_sem); pm_send(state->pm, PM_SUSPEND, (void *)3); - down(&port_sem); } #endif } } /* - * Hangup the port. This must be done outside the port_sem - * since uart_hangup() grabs this same semaphore. Grr. + * This reverses the affects of __uart_register_port, hanging up the + * port before removal. */ static void -__uart_hangup_port(struct uart_driver *drv, struct uart_state *state) +__uart_unregister_port(struct uart_driver *drv, struct uart_state *state) { + struct uart_port *port = state->port; struct uart_info *info = state->info; if (info && info->tty) tty_vhangup(info->tty); -} -/* - * This reverses the affects of __uart_register_port. - */ -static void -__uart_unregister_port(struct uart_driver *drv, struct uart_state *state) -{ - struct uart_port *port = state->port; - struct uart_info *info = state->info; + down(&state->sem); state->info = NULL; @@ -2113,6 +2109,8 @@ __uart_unregister_port(struct uart_driver *drv, struct uart_state *state) tasklet_kill(&info->tlet); kfree(info); } + + up(&state->sem); } /** @@ -2214,6 +2212,9 @@ int uart_register_driver(struct uart_driver *drv) state->close_delay = 5 * HZ / 10; state->closing_wait = 30 * HZ; + + init_MUTEX(&state->sem); + #ifdef CONFIG_PM state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm); if (state->pm) @@ -2305,8 +2306,6 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) printk(KERN_ALERT "Removing wrong port: %p != %p\n", state->port, port); - __uart_hangup_port(drv, state); - down(&port_sem); __uart_unregister_port(drv, state); state->port = NULL; @@ -2408,8 +2407,7 @@ int uart_register_port(struct uart_driver *drv, struct uart_port *port) * alter it underneath itself - the port may be open and * trying to do useful work. */ - if (state->count != 0 || - (state->info && state->info->blocked_open != 0)) { + if (uart_users(state) != 0) { ret = -EBUSY; goto out; } @@ -2461,8 +2459,6 @@ void uart_unregister_port(struct uart_driver *drv, int line) state = drv->state + line; - __uart_hangup_port(drv, state); - down(&port_sem); __uart_unregister_port(drv, state); up(&port_sem); diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 0ea3262a03b6..859550b04eaa 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -211,6 +211,8 @@ struct uart_state { struct uart_info *info; struct uart_port *port; + struct semaphore sem; + #ifdef CONFIG_PM struct pm_dev *pm; #endif @@ -235,7 +237,6 @@ struct uart_info { */ #define UIF_CHECK_CD (1 << 25) #define UIF_CTS_FLOW (1 << 26) -#define UIF_CLOSING (1 << 27) #define UIF_NORMAL_ACTIVE (1 << 29) #define UIF_INITIALIZED (1 << 31) |
