summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/tty/cyclades.c237
1 files changed, 115 insertions, 122 deletions
diff --git a/drivers/tty/cyclades.c b/drivers/tty/cyclades.c
index 42a329b8af9f..345bd0e0884e 100644
--- a/drivers/tty/cyclades.c
+++ b/drivers/tty/cyclades.c
@@ -917,7 +917,7 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
return 0;
} /* cyz_issue_cmd */
-static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty)
+static void cyz_handle_rx(struct cyclades_port *info)
{
struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
struct cyclades_card *cinfo = info->card;
@@ -940,80 +940,77 @@ static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty)
else
char_count = rx_put - rx_get + rx_bufsize;
- if (char_count) {
+ if (!char_count)
+ return;
+
#ifdef CY_ENABLE_MONITORING
- info->mon.int_count++;
- info->mon.char_count += char_count;
- if (char_count > info->mon.char_max)
- info->mon.char_max = char_count;
- info->mon.char_last = char_count;
+ info->mon.int_count++;
+ info->mon.char_count += char_count;
+ if (char_count > info->mon.char_max)
+ info->mon.char_max = char_count;
+ info->mon.char_last = char_count;
#endif
- if (tty == NULL) {
- /* flush received characters */
- new_rx_get = (new_rx_get + char_count) &
- (rx_bufsize - 1);
- info->rflush_count++;
- } else {
+
#ifdef BLOCKMOVE
- /* we'd like to use memcpy(t, f, n) and memset(s, c, count)
- for performance, but because of buffer boundaries, there
- may be several steps to the operation */
- while (1) {
- len = tty_prepare_flip_string(port, &buf,
- char_count);
- if (!len)
- break;
+ /* we'd like to use memcpy(t, f, n) and memset(s, c, count)
+ for performance, but because of buffer boundaries, there
+ may be several steps to the operation */
+ while (1) {
+ len = tty_prepare_flip_string(port, &buf,
+ char_count);
+ if (!len)
+ break;
- len = min_t(unsigned int, min(len, char_count),
- rx_bufsize - new_rx_get);
+ len = min_t(unsigned int, min(len, char_count),
+ rx_bufsize - new_rx_get);
- memcpy_fromio(buf, cinfo->base_addr +
- rx_bufaddr + new_rx_get, len);
+ memcpy_fromio(buf, cinfo->base_addr +
+ rx_bufaddr + new_rx_get, len);
- new_rx_get = (new_rx_get + len) &
- (rx_bufsize - 1);
- char_count -= len;
- info->icount.rx += len;
- info->idle_stats.recv_bytes += len;
- }
+ new_rx_get = (new_rx_get + len) &
+ (rx_bufsize - 1);
+ char_count -= len;
+ info->icount.rx += len;
+ info->idle_stats.recv_bytes += len;
+ }
#else
- len = tty_buffer_request_room(port, char_count);
- while (len--) {
- data = readb(cinfo->base_addr + rx_bufaddr +
- new_rx_get);
- new_rx_get = (new_rx_get + 1) &
- (rx_bufsize - 1);
- tty_insert_flip_char(port, data, TTY_NORMAL);
- info->idle_stats.recv_bytes++;
- info->icount.rx++;
- }
+ len = tty_buffer_request_room(port, char_count);
+ while (len--) {
+ data = readb(cinfo->base_addr + rx_bufaddr +
+ new_rx_get);
+ new_rx_get = (new_rx_get + 1) &
+ (rx_bufsize - 1);
+ tty_insert_flip_char(port, data, TTY_NORMAL);
+ info->idle_stats.recv_bytes++;
+ info->icount.rx++;
+ }
#endif
#ifdef CONFIG_CYZ_INTR
- /* Recalculate the number of chars in the RX buffer and issue
- a cmd in case it's higher than the RX high water mark */
- rx_put = readl(&buf_ctrl->rx_put);
- if (rx_put >= rx_get)
- char_count = rx_put - rx_get;
- else
- char_count = rx_put - rx_get + rx_bufsize;
- if (char_count >= readl(&buf_ctrl->rx_threshold) &&
- !timer_pending(&cyz_rx_full_timer[
- info->line]))
- mod_timer(&cyz_rx_full_timer[info->line],
- jiffies + 1);
+ /* Recalculate the number of chars in the RX buffer and issue
+ a cmd in case it's higher than the RX high water mark */
+ rx_put = readl(&buf_ctrl->rx_put);
+ if (rx_put >= rx_get)
+ char_count = rx_put - rx_get;
+ else
+ char_count = rx_put - rx_get + rx_bufsize;
+ if (char_count >= readl(&buf_ctrl->rx_threshold) &&
+ !timer_pending(&cyz_rx_full_timer[
+ info->line]))
+ mod_timer(&cyz_rx_full_timer[info->line],
+ jiffies + 1);
#endif
- info->idle_stats.recv_idle = jiffies;
- tty_schedule_flip(&info->port);
- }
- /* Update rx_get */
- cy_writel(&buf_ctrl->rx_get, new_rx_get);
- }
+ info->idle_stats.recv_idle = jiffies;
+ tty_schedule_flip(&info->port);
+
+ /* Update rx_get */
+ cy_writel(&buf_ctrl->rx_get, new_rx_get);
}
-static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty)
+static void cyz_handle_tx(struct cyclades_port *info)
{
struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
struct cyclades_card *cinfo = info->card;
+ struct tty_struct *tty;
u8 data;
unsigned int char_count;
#ifdef BLOCKMOVE
@@ -1033,63 +1030,63 @@ static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty)
else
char_count = tx_get - tx_put - 1;
- if (char_count) {
-
- if (tty == NULL)
- goto ztxdone;
+ if (!char_count)
+ return;
+
+ tty = tty_port_tty_get(&info->port);
+ if (tty == NULL)
+ goto ztxdone;
- if (info->x_char) { /* send special char */
- data = info->x_char;
+ if (info->x_char) { /* send special char */
+ data = info->x_char;
- cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
- tx_put = (tx_put + 1) & (tx_bufsize - 1);
- info->x_char = 0;
- char_count--;
- info->icount.tx++;
- }
+ cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
+ tx_put = (tx_put + 1) & (tx_bufsize - 1);
+ info->x_char = 0;
+ char_count--;
+ info->icount.tx++;
+ }
#ifdef BLOCKMOVE
- while (0 < (small_count = min_t(unsigned int,
- tx_bufsize - tx_put, min_t(unsigned int,
- (SERIAL_XMIT_SIZE - info->xmit_tail),
- min_t(unsigned int, info->xmit_cnt,
- char_count))))) {
-
- memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr +
- tx_put),
- &info->port.xmit_buf[info->xmit_tail],
- small_count);
-
- tx_put = (tx_put + small_count) & (tx_bufsize - 1);
- char_count -= small_count;
- info->icount.tx += small_count;
- info->xmit_cnt -= small_count;
- info->xmit_tail = (info->xmit_tail + small_count) &
- (SERIAL_XMIT_SIZE - 1);
- }
+ while (0 < (small_count = min_t(unsigned int,
+ tx_bufsize - tx_put, min_t(unsigned int,
+ (SERIAL_XMIT_SIZE - info->xmit_tail),
+ min_t(unsigned int, info->xmit_cnt,
+ char_count))))) {
+
+ memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + tx_put),
+ &info->port.xmit_buf[info->xmit_tail],
+ small_count);
+
+ tx_put = (tx_put + small_count) & (tx_bufsize - 1);
+ char_count -= small_count;
+ info->icount.tx += small_count;
+ info->xmit_cnt -= small_count;
+ info->xmit_tail = (info->xmit_tail + small_count) &
+ (SERIAL_XMIT_SIZE - 1);
+ }
#else
- while (info->xmit_cnt && char_count) {
- data = info->port.xmit_buf[info->xmit_tail];
- info->xmit_cnt--;
- info->xmit_tail = (info->xmit_tail + 1) &
- (SERIAL_XMIT_SIZE - 1);
-
- cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
- tx_put = (tx_put + 1) & (tx_bufsize - 1);
- char_count--;
- info->icount.tx++;
- }
+ while (info->xmit_cnt && char_count) {
+ data = info->port.xmit_buf[info->xmit_tail];
+ info->xmit_cnt--;
+ info->xmit_tail = (info->xmit_tail + 1) &
+ (SERIAL_XMIT_SIZE - 1);
+
+ cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
+ tx_put = (tx_put + 1) & (tx_bufsize - 1);
+ char_count--;
+ info->icount.tx++;
+ }
#endif
- tty_wakeup(tty);
+ tty_wakeup(tty);
+ tty_kref_put(tty);
ztxdone:
- /* Update tx_put */
- cy_writel(&buf_ctrl->tx_put, tx_put);
- }
+ /* Update tx_put */
+ cy_writel(&buf_ctrl->tx_put, tx_put);
}
static void cyz_handle_cmd(struct cyclades_card *cinfo)
{
struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
- struct tty_struct *tty;
struct cyclades_port *info;
__u32 channel, param, fw_ver;
__u8 cmd;
@@ -1102,9 +1099,6 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
special_count = 0;
delta_count = 0;
info = &cinfo->ports[channel];
- tty = tty_port_tty_get(&info->port);
- if (tty == NULL)
- continue;
switch (cmd) {
case C_CM_PR_ERROR:
@@ -1130,8 +1124,14 @@ 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
- tty_hangup(tty);
+ else {
+ struct tty_struct *tty;
+ tty = tty_port_tty_get(&info->port);
+ if (tty) {
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ }
+ }
}
break;
case C_CM_MCTS:
@@ -1160,7 +1160,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
"port %ld\n", info->card, channel);
#endif
- cyz_handle_rx(info, tty);
+ cyz_handle_rx(info);
break;
case C_CM_TXBEMPTY:
case C_CM_TXLOWWM:
@@ -1170,7 +1170,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
"port %ld\n", info->card, channel);
#endif
- cyz_handle_tx(info, tty);
+ cyz_handle_tx(info);
break;
#endif /* CONFIG_CYZ_INTR */
case C_CM_FATAL:
@@ -1183,7 +1183,6 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
wake_up_interruptible(&info->port.delta_msr_wait);
if (special_count)
tty_schedule_flip(&info->port);
- tty_kref_put(tty);
}
}
@@ -1249,17 +1248,11 @@ static void cyz_poll(unsigned long arg)
cyz_handle_cmd(cinfo);
for (port = 0; port < cinfo->nports; port++) {
- struct tty_struct *tty;
-
info = &cinfo->ports[port];
- tty = tty_port_tty_get(&info->port);
- /* OK to pass NULL to the handle functions below.
- They need to drop the data in that case. */
if (!info->throttle)
- cyz_handle_rx(info, tty);
- cyz_handle_tx(info, tty);
- tty_kref_put(tty);
+ cyz_handle_rx(info);
+ cyz_handle_tx(info);
}
/* poll every 'cyz_polling_cycle' period */
expires = jiffies + cyz_polling_cycle;