diff options
Diffstat (limited to 'drivers/staging/dgnc/dgnc_tty.c')
-rw-r--r-- | drivers/staging/dgnc/dgnc_tty.c | 577 |
1 files changed, 212 insertions, 365 deletions
diff --git a/drivers/staging/dgnc/dgnc_tty.c b/drivers/staging/dgnc/dgnc_tty.c index c3b8fc5..9e98781 100644 --- a/drivers/staging/dgnc/dgnc_tty.c +++ b/drivers/staging/dgnc/dgnc_tty.c @@ -58,16 +58,15 @@ static const struct digi_t dgnc_digi_init = { * This defines a raw port at 9600 baud, 8 data bits, no parity, * 1 stop bit. */ -static struct ktermios default_termios = { - .c_iflag = (DEFAULT_IFLAGS), /* iflags */ - .c_oflag = (DEFAULT_OFLAGS), /* oflags */ - .c_cflag = (DEFAULT_CFLAGS), /* cflags */ - .c_lflag = (DEFAULT_LFLAGS), /* lflags */ +static const struct ktermios default_termios = { + .c_iflag = (DEFAULT_IFLAGS), + .c_oflag = (DEFAULT_OFLAGS), + .c_cflag = (DEFAULT_CFLAGS), + .c_lflag = (DEFAULT_LFLAGS), .c_cc = INIT_C_CC, .c_line = 0, }; -/* Our function prototypes */ static int dgnc_tty_open(struct tty_struct *tty, struct file *file); static void dgnc_tty_close(struct tty_struct *tty, struct file *file); static int dgnc_block_til_ready(struct tty_struct *tty, struct file *file, @@ -130,10 +129,8 @@ static const struct tty_operations dgnc_tty_ops = { /* TTY Initialization/Cleanup Functions */ -/* - * dgnc_tty_register() - * - * Init the tty subsystem for this board. +/** + * dgnc_tty_register() - Init the tty subsystem for this board. */ int dgnc_tty_register(struct dgnc_board *brd) { @@ -143,7 +140,6 @@ int dgnc_tty_register(struct dgnc_board *brd) TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK); - if (IS_ERR(brd->serial_driver)) return PTR_ERR(brd->serial_driver); @@ -181,7 +177,6 @@ int dgnc_tty_register(struct dgnc_board *brd) TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK); - if (IS_ERR(brd->print_driver)) { rc = PTR_ERR(brd->print_driver); goto unregister_serial_driver; @@ -232,15 +227,15 @@ void dgnc_tty_unregister(struct dgnc_board *brd) put_tty_driver(brd->serial_driver); } -/* - * dgnc_tty_init() +/** + * dgnc_tty_init() - Initialize the tty subsystem. * - * Init the tty subsystem. Called once per board after board has been - * downloaded and init'ed. + * Called once per board after board has been downloaded and initialized. */ int dgnc_tty_init(struct dgnc_board *brd) { int i; + int rc; void __iomem *vaddr; struct channel_t *ch; @@ -254,14 +249,12 @@ int dgnc_tty_init(struct dgnc_board *brd) brd->nasync = brd->maxports; for (i = 0; i < brd->nasync; i++) { - /* - * Okay to malloc with GFP_KERNEL, we are not at - * interrupt context, and there are no locks held. - */ brd->channels[i] = kzalloc(sizeof(*brd->channels[i]), GFP_KERNEL); - if (!brd->channels[i]) + if (!brd->channels[i]) { + rc = -ENOMEM; goto err_free_channels; + } } ch = brd->channels[0]; @@ -271,14 +264,10 @@ int dgnc_tty_init(struct dgnc_board *brd) for (i = 0; i < brd->nasync; i++, ch = brd->channels[i]) { spin_lock_init(&ch->ch_lock); - /* Store all our magic numbers */ - ch->magic = DGNC_CHANNEL_MAGIC; - ch->ch_tun.magic = DGNC_UNIT_MAGIC; ch->ch_tun.un_ch = ch; ch->ch_tun.un_type = DGNC_SERIAL; ch->ch_tun.un_dev = i; - ch->ch_pun.magic = DGNC_UNIT_MAGIC; ch->ch_pun.un_ch = ch; ch->ch_pun.un_type = DGNC_PRINT; ch->ch_pun.un_dev = i + 128; @@ -319,11 +308,12 @@ err_free_channels: kfree(brd->channels[i]); brd->channels[i] = NULL; } - return -ENOMEM; + + return rc; } -/* - * dgnc_cleanup_tty() +/** + * dgnc_cleanup_tty() - Cleanup driver. * * Uninitialize the TTY portion of this driver. Free all memory and * resources. @@ -346,19 +336,18 @@ void dgnc_cleanup_tty(struct dgnc_board *brd) put_tty_driver(brd->print_driver); } -/* - * dgnc_wmove - Write data to transmit queue. - * - * ch - Pointer to channel structure. - * buf - Pointer to characters to be moved. - * n - Number of characters to move. +/** + * dgnc_wmove() - Write data to transmit queue. + * @ch: Pointer to channel structure. + * @buf: Pointer to characters to be moved. + * @n: Number of characters to move. */ static void dgnc_wmove(struct channel_t *ch, char *buf, uint n) { int remain; uint head; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; head = ch->ch_w_head & WQUEUEMASK; @@ -388,10 +377,9 @@ static void dgnc_wmove(struct channel_t *ch, char *buf, uint n) ch->ch_w_head = head; } -/* - * dgnc_input - Process received data. - * - * ch - Pointer to channel structure. +/** + * dgnc_input() - Process received data. + * @ch: Pointer to channel structure. */ void dgnc_input(struct channel_t *ch) { @@ -409,21 +397,17 @@ void dgnc_input(struct channel_t *ch) int s = 0; int i = 0; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; tp = ch->ch_tun.un_tty; bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) + if (!bd) return; spin_lock_irqsave(&ch->ch_lock, flags); - /* - * Figure the number of characters in the buffer. - * Exit immediately if none. - */ rmask = RQUEUEMASK; head = ch->ch_r_head & rmask; tail = ch->ch_r_tail & rmask; @@ -436,7 +420,7 @@ void dgnc_input(struct channel_t *ch) * If the device is not open, or CREAD is off, * flush input data and return immediately. */ - if (!tp || (tp->magic != TTY_MAGIC) || + if (!tp || !(ch->ch_tun.un_flags & UN_ISOPEN) || !C_CREAD(tp) || (ch->ch_tun.un_flags & UN_CLOSING)) { @@ -448,32 +432,18 @@ void dgnc_input(struct channel_t *ch) goto exit_unlock; } - /* If we are throttled, simply don't read any data. */ - if (ch->ch_flags & CH_FORCED_STOPI) goto exit_unlock; flip_len = TTY_FLIPBUF_SIZE; - /* Chop down the length, if needed */ len = min(data_len, flip_len); len = min(len, (N_TTY_BUF_SIZE - 1)); ld = tty_ldisc_ref(tp); - - /* - * If we were unable to get a reference to the ld, - * don't flush our buffer, and act like the ld doesn't - * have any space to put the data right now. - */ if (!ld) { len = 0; } else { - /* - * If ld doesn't have a pointer to a receive_buf function, - * flush the data, then act like the ld doesn't have any - * space to put the data right now. - */ if (!ld->ops->receive_buf) { ch->ch_r_head = ch->ch_r_tail; len = 0; @@ -562,7 +532,9 @@ exit_unlock: tty_ldisc_deref(ld); } -/* +/** + * dgnc_carrier() + * * Determines when CARRIER changes state and takes appropriate * action. */ @@ -571,7 +543,7 @@ void dgnc_carrier(struct channel_t *ch) int virt_carrier = 0; int phys_carrier = 0; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; if (ch->ch_mistat & UART_MSR_DCD) @@ -652,7 +624,6 @@ void dgnc_carrier(struct channel_t *ch) } /* Assign the custom baud rate to the channel structure */ - static void dgnc_set_custom_speed(struct channel_t *ch, uint newrate) { int testdiv; @@ -716,7 +687,6 @@ void dgnc_check_queue_flow_control(struct channel_t *ch) { int qleft; - /* Store how much space we have left in the queue */ qleft = ch->ch_r_tail - ch->ch_r_head - 1; if (qleft < 0) qleft += RQUEUEMASK + 1; @@ -797,7 +767,7 @@ void dgnc_wakeup_writes(struct channel_t *ch) int qlen = 0; unsigned long flags; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; spin_lock_irqsave(&ch->ch_lock, flags); @@ -883,8 +853,6 @@ static struct dgnc_board *find_board_by_major(unsigned int major) /* TTY Entry points and helper functions */ -/* dgnc_tty_open() */ - static int dgnc_tty_open(struct tty_struct *tty, struct file *file) { struct dgnc_board *brd; @@ -903,39 +871,30 @@ static int dgnc_tty_open(struct tty_struct *tty, struct file *file) if (major > 255) return -ENXIO; - /* Get board pointer from our array of majors we have allocated */ brd = find_board_by_major(major); if (!brd) return -ENXIO; - /* - * If board is not yet up to a state of READY, go to - * sleep waiting for it to happen or they cancel the open. - */ rc = wait_event_interruptible(brd->state_wait, (brd->state & BOARD_READY)); - if (rc) return rc; spin_lock_irqsave(&brd->bd_lock, flags); - /* If opened device is greater than our number of ports, bail. */ if (PORT_NUM(minor) >= brd->nasync) { - spin_unlock_irqrestore(&brd->bd_lock, flags); - return -ENXIO; + rc = -ENXIO; + goto err_brd_unlock; } ch = brd->channels[PORT_NUM(minor)]; if (!ch) { - spin_unlock_irqrestore(&brd->bd_lock, flags); - return -ENXIO; + rc = -ENXIO; + goto err_brd_unlock; } - /* Drop board lock */ spin_unlock_irqrestore(&brd->bd_lock, flags); - /* Grab channel lock */ spin_lock_irqsave(&ch->ch_lock, flags); /* Figure out our type */ @@ -946,8 +905,8 @@ static int dgnc_tty_open(struct tty_struct *tty, struct file *file) un = &brd->channels[PORT_NUM(minor)]->ch_pun; un->un_type = DGNC_PRINT; } else { - spin_unlock_irqrestore(&ch->ch_lock, flags); - return -ENXIO; + rc = -ENXIO; + goto err_ch_unlock; } /* @@ -959,7 +918,6 @@ static int dgnc_tty_open(struct tty_struct *tty, struct file *file) rc = wait_event_interruptible(ch->ch_flags_wait, ((ch->ch_flags & CH_OPENING) == 0)); - /* If ret is non-zero, user ctrl-c'ed us */ if (rc) return -EINTR; @@ -975,21 +933,18 @@ static int dgnc_tty_open(struct tty_struct *tty, struct file *file) ch->ch_flags_wait, (((ch->ch_tun.un_flags | ch->ch_pun.un_flags) & UN_CLOSING) == 0)); - /* If ret is non-zero, user ctrl-c'ed us */ if (rc) return -EINTR; spin_lock_irqsave(&ch->ch_lock, flags); - /* Store our unit into driver_data, so we always have it available. */ tty->driver_data = un; /* Initialize tty's */ if (!(un->un_flags & UN_ISOPEN)) { - /* Store important variables. */ - un->un_tty = tty; + un->un_tty = tty; /* Maybe do something here to the TTY struct as well? */ } @@ -1000,7 +955,6 @@ static int dgnc_tty_open(struct tty_struct *tty, struct file *file) */ ch->ch_flags |= (CH_OPENING); - /* Drop locks, as malloc with GFP_KERNEL can sleep */ spin_unlock_irqrestore(&ch->ch_lock, flags); if (!ch->ch_rqueue) @@ -1014,7 +968,6 @@ static int dgnc_tty_open(struct tty_struct *tty, struct file *file) kfree(ch->ch_rqueue); kfree(ch->ch_equeue); kfree(ch->ch_wqueue); - return -ENOMEM; } @@ -1062,19 +1015,14 @@ static int dgnc_tty_open(struct tty_struct *tty, struct file *file) brd->bd_ops->uart_init(ch); } - /* Run param in case we changed anything */ - brd->bd_ops->param(tty); dgnc_carrier(ch); - /* follow protocol for opening port */ - spin_unlock_irqrestore(&ch->ch_lock, flags); rc = dgnc_block_til_ready(tty, file, ch); - /* No going back now, increment our unit and channel counters */ spin_lock_irqsave(&ch->ch_lock, flags); ch->ch_open_count++; un->un_open_count++; @@ -1082,18 +1030,23 @@ static int dgnc_tty_open(struct tty_struct *tty, struct file *file) spin_unlock_irqrestore(&ch->ch_lock, flags); return rc; + +err_brd_unlock: + spin_unlock_irqrestore(&brd->bd_lock, flags); + + return rc; +err_ch_unlock: + spin_unlock_irqrestore(&ch->ch_lock, flags); + + return rc; } -/* - * dgnc_block_til_ready() - * - * Wait for DCD, if needed. - */ +/* Wait for DCD, if needed. */ static int dgnc_block_til_ready(struct tty_struct *tty, struct file *file, struct channel_t *ch) { - int retval = 0; + int rc = 0; struct un_t *un = tty->driver_data; unsigned long flags; uint old_flags = 0; @@ -1106,22 +1059,16 @@ static int dgnc_block_til_ready(struct tty_struct *tty, ch->ch_wopen++; - /* Loop forever */ while (1) { sleep_on_un_flags = 0; - /* - * If board has failed somehow during our sleep, - * bail with error. - */ if (ch->ch_bd->state == BOARD_FAILED) { - retval = -ENXIO; + rc = -ENXIO; break; } - /* If tty was hung up, break out of loop and set error. */ if (tty_hung_up_p(file)) { - retval = -EAGAIN; + rc = -EAGAIN; break; } @@ -1146,7 +1093,7 @@ static int dgnc_block_til_ready(struct tty_struct *tty, break; if (tty_io_error(tty)) { - retval = -EIO; + rc = -EIO; break; } @@ -1162,15 +1109,12 @@ static int dgnc_block_til_ready(struct tty_struct *tty, /* * If there is a signal pending, the user probably * interrupted (ctrl-c) us. - * Leave loop with error set. */ if (signal_pending(current)) { - retval = -ERESTARTSYS; + rc = -ERESTARTSYS; break; } - /* Store the flags before we let go of channel lock */ - if (sleep_on_un_flags) old_flags = ch->ch_tun.un_flags | ch->ch_pun.un_flags; else @@ -1189,12 +1133,12 @@ static int dgnc_block_til_ready(struct tty_struct *tty, * from the current value. */ if (sleep_on_un_flags) - retval = wait_event_interruptible + rc = wait_event_interruptible (un->un_flags_wait, (old_flags != (ch->ch_tun.un_flags | ch->ch_pun.un_flags))); else - retval = wait_event_interruptible( + rc = wait_event_interruptible( ch->ch_flags_wait, (old_flags != ch->ch_flags)); @@ -1209,25 +1153,19 @@ static int dgnc_block_til_ready(struct tty_struct *tty, spin_unlock_irqrestore(&ch->ch_lock, flags); - return retval; + return rc; } -/* - * dgnc_tty_hangup() - * - * Hangup the port. Like a close, but don't wait for output to drain. - */ +/* Hangup the port. Like a close, but don't wait for output to drain. */ static void dgnc_tty_hangup(struct tty_struct *tty) { - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return; /* flush the transmit queues */ dgnc_tty_flush_buffer(tty); } -/* dgnc_tty_close() */ - static void dgnc_tty_close(struct tty_struct *tty, struct file *file) { struct dgnc_board *bd; @@ -1235,19 +1173,19 @@ static void dgnc_tty_close(struct tty_struct *tty, struct file *file) struct un_t *un; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) + if (!bd) return; spin_lock_irqsave(&ch->ch_lock, flags); @@ -1361,8 +1299,6 @@ static void dgnc_tty_close(struct tty_struct *tty, struct file *file) } /* - * dgnc_tty_chars_in_buffer() - * * Return number of characters that have not been transmitted yet. * * This routine is used by the line discipline to determine if there @@ -1375,18 +1311,18 @@ static int dgnc_tty_chars_in_buffer(struct tty_struct *tty) ushort thead; ushort ttail; uint tmask; - uint chars = 0; + uint chars; unsigned long flags; if (!tty) return 0; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return 0; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return 0; spin_lock_irqsave(&ch->ch_lock, flags); @@ -1397,21 +1333,17 @@ static int dgnc_tty_chars_in_buffer(struct tty_struct *tty) spin_unlock_irqrestore(&ch->ch_lock, flags); - if (ttail == thead) { + if (ttail == thead) chars = 0; - } else { - if (thead >= ttail) - chars = thead - ttail; - else - chars = thead - ttail + WQUEUESIZE; - } + else if (thead > ttail) + chars = thead - ttail; + else + chars = thead - ttail + WQUEUESIZE; return chars; } /* - * dgnc_maxcps_room - * * Reduces bytes_available to the max number of characters * that can be sent currently given the maxcps value, and * returns the new bytes_available. This only affects printer @@ -1419,6 +1351,8 @@ static int dgnc_tty_chars_in_buffer(struct tty_struct *tty) */ static int dgnc_maxcps_room(struct channel_t *ch, int bytes_available) { + int rc = bytes_available; + if (ch->ch_digi.digi_maxcps > 0 && ch->ch_digi.digi_bufsize > 0) { int cps_limit = 0; unsigned long current_time = jiffies; @@ -1439,17 +1373,13 @@ static int dgnc_maxcps_room(struct channel_t *ch, int bytes_available) cps_limit = 0; } - bytes_available = min(cps_limit, bytes_available); + rc = min(cps_limit, bytes_available); } - return bytes_available; + return rc; } -/* - * dgnc_tty_write_room() - * - * Return space available in Tx buffer - */ +/* Return room available in Tx buffer */ static int dgnc_tty_write_room(struct tty_struct *tty) { struct channel_t *ch = NULL; @@ -1457,18 +1387,18 @@ static int dgnc_tty_write_room(struct tty_struct *tty) ushort head; ushort tail; ushort tmask; - int ret = 0; + int room = 0; unsigned long flags; if (!tty) return 0; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return 0; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return 0; spin_lock_irqsave(&ch->ch_lock, flags); @@ -1477,53 +1407,45 @@ static int dgnc_tty_write_room(struct tty_struct *tty) head = (ch->ch_w_head) & tmask; tail = (ch->ch_w_tail) & tmask; - ret = tail - head - 1; - if (ret < 0) - ret += WQUEUESIZE; + room = tail - head - 1; + if (room < 0) + room += WQUEUESIZE; /* Limit printer to maxcps */ if (un->un_type != DGNC_PRINT) - ret = dgnc_maxcps_room(ch, ret); + room = dgnc_maxcps_room(ch, room); /* - * If we are printer device, leave space for + * If we are printer device, leave room for * possibly both the on and off strings. */ if (un->un_type == DGNC_PRINT) { if (!(ch->ch_flags & CH_PRON)) - ret -= ch->ch_digi.digi_onlen; - ret -= ch->ch_digi.digi_offlen; + room -= ch->ch_digi.digi_onlen; + room -= ch->ch_digi.digi_offlen; } else { if (ch->ch_flags & CH_PRON) - ret -= ch->ch_digi.digi_offlen; + room -= ch->ch_digi.digi_offlen; } - if (ret < 0) - ret = 0; + if (room < 0) + room = 0; spin_unlock_irqrestore(&ch->ch_lock, flags); - - return ret; + return room; } /* - * dgnc_tty_put_char() - * * Put a character into ch->ch_buf - * - * - used by the line discipline for OPOST processing + * Used by the line discipline for OPOST processing */ static int dgnc_tty_put_char(struct tty_struct *tty, unsigned char c) { - /* Simply call tty_write. */ - dgnc_tty_write(tty, &c, 1); return 1; } /* - * dgnc_tty_write() - * * Take data from the user or kernel and send it out to the FEP. * In here exists all the Transparent Print magic as well. */ @@ -1543,11 +1465,11 @@ static int dgnc_tty_write(struct tty_struct *tty, return 0; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return 0; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return 0; if (!count) @@ -1561,7 +1483,6 @@ static int dgnc_tty_write(struct tty_struct *tty, spin_lock_irqsave(&ch->ch_lock, flags); - /* Get our space available for the channel from the board */ tmask = WQUEUEMASK; head = (ch->ch_w_head) & tmask; tail = (ch->ch_w_tail) & tmask; @@ -1577,14 +1498,7 @@ static int dgnc_tty_write(struct tty_struct *tty, if (un->un_type != DGNC_PRINT) bufcount = dgnc_maxcps_room(ch, bufcount); - /* - * Take minimum of what the user wants to send, and the - * space available in the FEP buffer. - */ count = min(count, bufcount); - - /* Bail if no space left. */ - if (count <= 0) goto exit_retry; @@ -1646,42 +1560,36 @@ static int dgnc_tty_write(struct tty_struct *tty, spin_unlock_irqrestore(&ch->ch_lock, flags); - if (count) { - /* - * Channel lock is grabbed and then released - * inside this routine. - */ + if (count) ch->ch_bd->bd_ops->copy_data_from_queue_to_uart(ch); - } return count; exit_retry: - spin_unlock_irqrestore(&ch->ch_lock, flags); + return 0; } /* Return modem signals to ld. */ - static int dgnc_tty_tiocmget(struct tty_struct *tty) { struct channel_t *ch; struct un_t *un; - int result = -EIO; + int rc; unsigned char mstat = 0; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) - return result; + if (!tty) + return -EIO; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) - return result; + if (!un) + return -EIO; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return result; + if (!ch) + return -EIO; spin_lock_irqsave(&ch->ch_lock, flags); @@ -1689,53 +1597,47 @@ static int dgnc_tty_tiocmget(struct tty_struct *tty) spin_unlock_irqrestore(&ch->ch_lock, flags); - result = 0; + rc = 0; if (mstat & UART_MCR_DTR) - result |= TIOCM_DTR; + rc |= TIOCM_DTR; if (mstat & UART_MCR_RTS) - result |= TIOCM_RTS; + rc |= TIOCM_RTS; if (mstat & UART_MSR_CTS) - result |= TIOCM_CTS; + rc |= TIOCM_CTS; if (mstat & UART_MSR_DSR) - result |= TIOCM_DSR; + rc |= TIOCM_DSR; if (mstat & UART_MSR_RI) - result |= TIOCM_RI; + rc |= TIOCM_RI; if (mstat & UART_MSR_DCD) - result |= TIOCM_CD; + rc |= TIOCM_CD; - return result; + return rc; } -/* - * dgnc_tty_tiocmset() - * - * Set modem signals, called by ld. - */ - +/* Set modem signals, called by ld. */ static int dgnc_tty_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct dgnc_board *bd; struct channel_t *ch; struct un_t *un; - int ret = -EIO; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) - return ret; + if (!tty) + return -EIO; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) - return ret; + if (!un) + return -EIO; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return ret; + if (!ch) + return -EIO; bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) - return ret; + if (!bd) + return -EIO; spin_lock_irqsave(&ch->ch_lock, flags); @@ -1751,95 +1653,74 @@ static int dgnc_tty_tiocmset(struct tty_struct *tty, if (clear & TIOCM_DTR) ch->ch_mostat &= ~(UART_MCR_DTR); - ch->ch_bd->bd_ops->assert_modem_signals(ch); + bd->bd_ops->assert_modem_signals(ch); spin_unlock_irqrestore(&ch->ch_lock, flags); return 0; } -/* - * dgnc_tty_send_break() - * - * Send a Break, called by ld. - */ +/* Send a Break, called by ld. */ static int dgnc_tty_send_break(struct tty_struct *tty, int msec) { struct dgnc_board *bd; struct channel_t *ch; struct un_t *un; - int ret = -EIO; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) - return ret; + if (!tty) + return -EIO; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) - return ret; + if (!un) + return -EIO; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) - return ret; + if (!ch) + return -EIO; bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) - return ret; + if (!bd) + return -EIO; - switch (msec) { - case -1: + if (msec < 0) msec = 0xFFFF; - break; - case 0: - msec = 0; - break; - default: - break; - } spin_lock_irqsave(&ch->ch_lock, flags); - ch->ch_bd->bd_ops->send_break(ch, msec); + bd->bd_ops->send_break(ch, msec); spin_unlock_irqrestore(&ch->ch_lock, flags); return 0; } -/* - * dgnc_tty_wait_until_sent() - * - * wait until data has been transmitted, called by ld. - */ +/* wait until data has been transmitted, called by ld. */ static void dgnc_tty_wait_until_sent(struct tty_struct *tty, int timeout) { struct dgnc_board *bd; struct channel_t *ch; struct un_t *un; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) + if (!bd) return; bd->bd_ops->drain(tty, 0); } -/* - * dgnc_send_xchar() - * - * send a high priority character, called by ld. - */ +/* send a high priority character, called by ld. */ static void dgnc_tty_send_xchar(struct tty_struct *tty, char c) { struct dgnc_board *bd; @@ -1847,39 +1728,34 @@ static void dgnc_tty_send_xchar(struct tty_struct *tty, char c) struct un_t *un; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) + if (!bd) return; - dev_dbg(tty->dev, "dgnc_tty_send_xchar start\n"); - spin_lock_irqsave(&ch->ch_lock, flags); bd->bd_ops->send_immediate_char(ch, c); spin_unlock_irqrestore(&ch->ch_lock, flags); - - dev_dbg(tty->dev, "dgnc_tty_send_xchar finish\n"); } /* Return modem signals to ld. */ - static inline int dgnc_get_mstat(struct channel_t *ch) { unsigned char mstat; - int result = 0; unsigned long flags; + int rc; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return -ENXIO; spin_lock_irqsave(&ch->ch_lock, flags); @@ -1888,46 +1764,43 @@ static inline int dgnc_get_mstat(struct channel_t *ch) spin_unlock_irqrestore(&ch->ch_lock, flags); + rc = 0; + if (mstat & UART_MCR_DTR) - result |= TIOCM_DTR; + rc |= TIOCM_DTR; if (mstat & UART_MCR_RTS) - result |= TIOCM_RTS; + rc |= TIOCM_RTS; if (mstat & UART_MSR_CTS) - result |= TIOCM_CTS; + rc |= TIOCM_CTS; if (mstat & UART_MSR_DSR) - result |= TIOCM_DSR; + rc |= TIOCM_DSR; if (mstat & UART_MSR_RI) - result |= TIOCM_RI; + rc |= TIOCM_RI; if (mstat & UART_MSR_DCD) - result |= TIOCM_CD; + rc |= TIOCM_CD; - return result; + return rc; } /* Return modem signals to ld. */ - static int dgnc_get_modem_info(struct channel_t *ch, unsigned int __user *value) { return put_user(dgnc_get_mstat(ch), value); } -/* - * dgnc_set_modem_info() - * - * Set modem signals, called by ld. - */ +/* Set modem signals, called by ld. */ static int dgnc_set_modem_info(struct channel_t *ch, unsigned int command, unsigned int __user *value) { - int ret = -ENXIO; + int rc; unsigned int arg = 0; unsigned long flags; - ret = get_user(arg, value); - if (ret) - return ret; + rc = get_user(arg, value); + if (rc) + return rc; switch (command) { case TIOCMBIS: @@ -1975,11 +1848,7 @@ static int dgnc_set_modem_info(struct channel_t *ch, return 0; } -/* - * dgnc_tty_digigeta() - * - * Ioctl to get the information for ditty. - */ +/* Ioctl to get the information for ditty. */ static int dgnc_tty_digigeta(struct tty_struct *tty, struct digi_t __user *retinfo) { @@ -1991,15 +1860,15 @@ static int dgnc_tty_digigeta(struct tty_struct *tty, if (!retinfo) return -EFAULT; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return -EFAULT; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return -EFAULT; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return -EFAULT; memset(&tmp, 0, sizeof(tmp)); @@ -2014,11 +1883,7 @@ static int dgnc_tty_digigeta(struct tty_struct *tty, return 0; } -/* - * dgnc_tty_digiseta() - * - * Ioctl to set the information for ditty. - */ +/* Ioctl to set the information for ditty. */ static int dgnc_tty_digiseta(struct tty_struct *tty, struct digi_t __user *new_info) { @@ -2028,19 +1893,19 @@ static int dgnc_tty_digiseta(struct tty_struct *tty, struct digi_t new_digi; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return -EFAULT; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return -EFAULT; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return -EFAULT; bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) + if (!bd) return -EFAULT; if (copy_from_user(&new_digi, new_info, sizeof(new_digi))) @@ -2089,15 +1954,13 @@ static int dgnc_tty_digiseta(struct tty_struct *tty, if (ch->ch_digi.digi_offlen > DIGI_PLEN) ch->ch_digi.digi_offlen = DIGI_PLEN; - ch->ch_bd->bd_ops->param(tty); + bd->bd_ops->param(tty); spin_unlock_irqrestore(&ch->ch_lock, flags); return 0; } -/* dgnc_set_termios() */ - static void dgnc_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { @@ -2106,19 +1969,19 @@ static void dgnc_tty_set_termios(struct tty_struct *tty, struct un_t *un; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) + if (!bd) return; spin_lock_irqsave(&ch->ch_lock, flags); @@ -2130,7 +1993,7 @@ static void dgnc_tty_set_termios(struct tty_struct *tty, ch->ch_startc = tty->termios.c_cc[VSTART]; ch->ch_stopc = tty->termios.c_cc[VSTOP]; - ch->ch_bd->bd_ops->param(tty); + bd->bd_ops->param(tty); dgnc_carrier(ch); spin_unlock_irqrestore(&ch->ch_lock, flags); @@ -2142,15 +2005,15 @@ static void dgnc_tty_throttle(struct tty_struct *tty) struct un_t *un; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; spin_lock_irqsave(&ch->ch_lock, flags); @@ -2166,15 +2029,15 @@ static void dgnc_tty_unthrottle(struct tty_struct *tty) struct un_t *un; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; spin_lock_irqsave(&ch->ch_lock, flags); @@ -2191,19 +2054,19 @@ static void dgnc_tty_start(struct tty_struct *tty) struct un_t *un; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) + if (!bd) return; spin_lock_irqsave(&ch->ch_lock, flags); @@ -2220,19 +2083,19 @@ static void dgnc_tty_stop(struct tty_struct *tty) struct un_t *un; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) + if (!bd) return; spin_lock_irqsave(&ch->ch_lock, flags); @@ -2243,8 +2106,6 @@ static void dgnc_tty_stop(struct tty_struct *tty) } /* - * dgnc_tty_flush_chars() - * * Flush the cook buffer * * Note to self, and any other poor souls who venture here: @@ -2262,19 +2123,19 @@ static void dgnc_tty_flush_chars(struct tty_struct *tty) struct un_t *un; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) + if (!bd) return; spin_lock_irqsave(&ch->ch_lock, flags); @@ -2284,26 +2145,22 @@ static void dgnc_tty_flush_chars(struct tty_struct *tty) spin_unlock_irqrestore(&ch->ch_lock, flags); } -/* - * dgnc_tty_flush_buffer() - * - * Flush Tx buffer (make in == out) - */ +/* Flush Tx buffer (make in == out) */ static void dgnc_tty_flush_buffer(struct tty_struct *tty) { struct channel_t *ch; struct un_t *un; unsigned long flags; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return; spin_lock_irqsave(&ch->ch_lock, flags); @@ -2328,11 +2185,7 @@ static void dgnc_tty_flush_buffer(struct tty_struct *tty) spin_unlock_irqrestore(&ch->ch_lock, flags); } -/* - * dgnc_wake_up_unit() - * - * Wakes up processes waiting in the unit's (teminal/printer) wait queue - */ +/* Wakes up processes waiting in the unit's (teminal/printer) wait queue */ static void dgnc_wake_up_unit(struct un_t *unit) { unit->un_flags &= ~(UN_LOW | UN_EMPTY); @@ -2341,11 +2194,7 @@ static void dgnc_wake_up_unit(struct un_t *unit) /* The IOCTL function and all of its helpers */ -/* - * dgnc_tty_ioctl() - * - * The usual assortment of ioctl's - */ +/* The usual assortment of ioctl's */ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { @@ -2357,19 +2206,19 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long flags; void __user *uarg = (void __user *)arg; - if (!tty || tty->magic != TTY_MAGIC) + if (!tty) return -ENODEV; un = tty->driver_data; - if (!un || un->magic != DGNC_UNIT_MAGIC) + if (!un) return -ENODEV; ch = un->un_ch; - if (!ch || ch->magic != DGNC_CHANNEL_MAGIC) + if (!ch) return -ENODEV; bd = ch->ch_bd; - if (!bd || bd->magic != DGNC_BOARD_MAGIC) + if (!bd) return -ENODEV; ch_bd_ops = bd->bd_ops; @@ -2377,8 +2226,8 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, spin_lock_irqsave(&ch->ch_lock, flags); if (un->un_open_count <= 0) { - spin_unlock_irqrestore(&ch->ch_lock, flags); - return -EIO; + rc = -EIO; + goto err_unlock; } switch (cmd) { @@ -2399,7 +2248,6 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, return rc; rc = ch_bd_ops->drain(tty, 0); - if (rc) return -EINTR; @@ -2504,10 +2352,8 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, * also. */ rc = tty_check_change(tty); - if (rc) { - spin_unlock_irqrestore(&ch->ch_lock, flags); - return rc; - } + if (rc) + goto err_unlock; if ((arg == TCIFLUSH) || (arg == TCIOFLUSH)) { ch->ch_r_head = ch->ch_r_tail; @@ -2588,7 +2434,6 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, if (cmd == (DIGI_SETAW)) { spin_unlock_irqrestore(&ch->ch_lock, flags); rc = ch_bd_ops->drain(tty, 0); - if (rc) return -EINTR; @@ -2634,7 +2479,7 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, case DIGI_SETCUSTOMBAUD: { int new_rate; - /* Let go of locks when accessing user space, could sleep */ + spin_unlock_irqrestore(&ch->ch_lock, flags); rc = get_user(new_rate, (int __user *)arg); if (rc) @@ -2732,8 +2577,6 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, spin_unlock_irqrestore(&ch->ch_lock, flags); - /* Get data from user first. */ - if (copy_from_user(&buf, uarg, sizeof(buf))) return -EFAULT; @@ -2787,4 +2630,8 @@ static int dgnc_tty_ioctl(struct tty_struct *tty, unsigned int cmd, return -ENOIOCTLCMD; } +err_unlock: + spin_unlock_irqrestore(&ch->ch_lock, flags); + + return rc; } |