|
@@ -441,7 +441,7 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
|
|
|
void __iomem *base_addr)
|
|
void __iomem *base_addr)
|
|
|
{
|
|
{
|
|
|
struct cyclades_port *info;
|
|
struct cyclades_port *info;
|
|
|
- struct tty_struct *tty;
|
|
|
|
|
|
|
+ struct tty_port *port;
|
|
|
int len, index = cinfo->bus_index;
|
|
int len, index = cinfo->bus_index;
|
|
|
u8 ivr, save_xir, channel, save_car, data, char_count;
|
|
u8 ivr, save_xir, channel, save_car, data, char_count;
|
|
|
|
|
|
|
@@ -452,22 +452,11 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
|
|
|
save_xir = readb(base_addr + (CyRIR << index));
|
|
save_xir = readb(base_addr + (CyRIR << index));
|
|
|
channel = save_xir & CyIRChannel;
|
|
channel = save_xir & CyIRChannel;
|
|
|
info = &cinfo->ports[channel + chip * 4];
|
|
info = &cinfo->ports[channel + chip * 4];
|
|
|
|
|
+ port = &info->port;
|
|
|
save_car = cyy_readb(info, CyCAR);
|
|
save_car = cyy_readb(info, CyCAR);
|
|
|
cyy_writeb(info, CyCAR, save_xir);
|
|
cyy_writeb(info, CyCAR, save_xir);
|
|
|
ivr = cyy_readb(info, CyRIVR) & CyIVRMask;
|
|
ivr = cyy_readb(info, CyRIVR) & CyIVRMask;
|
|
|
|
|
|
|
|
- tty = tty_port_tty_get(&info->port);
|
|
|
|
|
- /* if there is nowhere to put the data, discard it */
|
|
|
|
|
- if (tty == NULL) {
|
|
|
|
|
- if (ivr == CyIVRRxEx) { /* exception */
|
|
|
|
|
- data = cyy_readb(info, CyRDSR);
|
|
|
|
|
- } else { /* normal character reception */
|
|
|
|
|
- char_count = cyy_readb(info, CyRDCR);
|
|
|
|
|
- while (char_count--)
|
|
|
|
|
- data = cyy_readb(info, CyRDSR);
|
|
|
|
|
- }
|
|
|
|
|
- goto end;
|
|
|
|
|
- }
|
|
|
|
|
/* there is an open port for this data */
|
|
/* there is an open port for this data */
|
|
|
if (ivr == CyIVRRxEx) { /* exception */
|
|
if (ivr == CyIVRRxEx) { /* exception */
|
|
|
data = cyy_readb(info, CyRDSR);
|
|
data = cyy_readb(info, CyRDSR);
|
|
@@ -484,40 +473,45 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
|
|
|
|
|
|
|
|
if (data & info->ignore_status_mask) {
|
|
if (data & info->ignore_status_mask) {
|
|
|
info->icount.rx++;
|
|
info->icount.rx++;
|
|
|
- tty_kref_put(tty);
|
|
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- if (tty_buffer_request_room(tty, 1)) {
|
|
|
|
|
|
|
+ if (tty_buffer_request_room(port, 1)) {
|
|
|
if (data & info->read_status_mask) {
|
|
if (data & info->read_status_mask) {
|
|
|
if (data & CyBREAK) {
|
|
if (data & CyBREAK) {
|
|
|
- tty_insert_flip_char(tty,
|
|
|
|
|
|
|
+ tty_insert_flip_char(port,
|
|
|
cyy_readb(info, CyRDSR),
|
|
cyy_readb(info, CyRDSR),
|
|
|
TTY_BREAK);
|
|
TTY_BREAK);
|
|
|
info->icount.rx++;
|
|
info->icount.rx++;
|
|
|
- if (info->port.flags & ASYNC_SAK)
|
|
|
|
|
- do_SAK(tty);
|
|
|
|
|
|
|
+ if (port->flags & ASYNC_SAK) {
|
|
|
|
|
+ struct tty_struct *tty =
|
|
|
|
|
+ tty_port_tty_get(port);
|
|
|
|
|
+ if (tty) {
|
|
|
|
|
+ do_SAK(tty);
|
|
|
|
|
+ tty_kref_put(tty);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
} else if (data & CyFRAME) {
|
|
} else if (data & CyFRAME) {
|
|
|
- tty_insert_flip_char(tty,
|
|
|
|
|
|
|
+ tty_insert_flip_char(port,
|
|
|
cyy_readb(info, CyRDSR),
|
|
cyy_readb(info, CyRDSR),
|
|
|
TTY_FRAME);
|
|
TTY_FRAME);
|
|
|
info->icount.rx++;
|
|
info->icount.rx++;
|
|
|
info->idle_stats.frame_errs++;
|
|
info->idle_stats.frame_errs++;
|
|
|
} else if (data & CyPARITY) {
|
|
} else if (data & CyPARITY) {
|
|
|
/* Pieces of seven... */
|
|
/* Pieces of seven... */
|
|
|
- tty_insert_flip_char(tty,
|
|
|
|
|
|
|
+ tty_insert_flip_char(port,
|
|
|
cyy_readb(info, CyRDSR),
|
|
cyy_readb(info, CyRDSR),
|
|
|
TTY_PARITY);
|
|
TTY_PARITY);
|
|
|
info->icount.rx++;
|
|
info->icount.rx++;
|
|
|
info->idle_stats.parity_errs++;
|
|
info->idle_stats.parity_errs++;
|
|
|
} else if (data & CyOVERRUN) {
|
|
} else if (data & CyOVERRUN) {
|
|
|
- tty_insert_flip_char(tty, 0,
|
|
|
|
|
|
|
+ tty_insert_flip_char(port, 0,
|
|
|
TTY_OVERRUN);
|
|
TTY_OVERRUN);
|
|
|
info->icount.rx++;
|
|
info->icount.rx++;
|
|
|
/* If the flip buffer itself is
|
|
/* If the flip buffer itself is
|
|
|
overflowing, we still lose
|
|
overflowing, we still lose
|
|
|
the next incoming character.
|
|
the next incoming character.
|
|
|
*/
|
|
*/
|
|
|
- tty_insert_flip_char(tty,
|
|
|
|
|
|
|
+ tty_insert_flip_char(port,
|
|
|
cyy_readb(info, CyRDSR),
|
|
cyy_readb(info, CyRDSR),
|
|
|
TTY_FRAME);
|
|
TTY_FRAME);
|
|
|
info->icount.rx++;
|
|
info->icount.rx++;
|
|
@@ -527,12 +521,12 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
|
|
|
/* } else if(data & CyTIMEOUT) { */
|
|
/* } else if(data & CyTIMEOUT) { */
|
|
|
/* } else if(data & CySPECHAR) { */
|
|
/* } else if(data & CySPECHAR) { */
|
|
|
} else {
|
|
} else {
|
|
|
- tty_insert_flip_char(tty, 0,
|
|
|
|
|
|
|
+ tty_insert_flip_char(port, 0,
|
|
|
TTY_NORMAL);
|
|
TTY_NORMAL);
|
|
|
info->icount.rx++;
|
|
info->icount.rx++;
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
|
- tty_insert_flip_char(tty, 0, TTY_NORMAL);
|
|
|
|
|
|
|
+ tty_insert_flip_char(port, 0, TTY_NORMAL);
|
|
|
info->icount.rx++;
|
|
info->icount.rx++;
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
@@ -552,10 +546,10 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
|
|
|
info->mon.char_max = char_count;
|
|
info->mon.char_max = char_count;
|
|
|
info->mon.char_last = char_count;
|
|
info->mon.char_last = char_count;
|
|
|
#endif
|
|
#endif
|
|
|
- len = tty_buffer_request_room(tty, char_count);
|
|
|
|
|
|
|
+ len = tty_buffer_request_room(port, char_count);
|
|
|
while (len--) {
|
|
while (len--) {
|
|
|
data = cyy_readb(info, CyRDSR);
|
|
data = cyy_readb(info, CyRDSR);
|
|
|
- tty_insert_flip_char(tty, data, TTY_NORMAL);
|
|
|
|
|
|
|
+ tty_insert_flip_char(port, data, TTY_NORMAL);
|
|
|
info->idle_stats.recv_bytes++;
|
|
info->idle_stats.recv_bytes++;
|
|
|
info->icount.rx++;
|
|
info->icount.rx++;
|
|
|
#ifdef CY_16Y_HACK
|
|
#ifdef CY_16Y_HACK
|
|
@@ -564,9 +558,8 @@ static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
|
|
|
}
|
|
}
|
|
|
info->idle_stats.recv_idle = jiffies;
|
|
info->idle_stats.recv_idle = jiffies;
|
|
|
}
|
|
}
|
|
|
- tty_schedule_flip(tty);
|
|
|
|
|
- tty_kref_put(tty);
|
|
|
|
|
-end:
|
|
|
|
|
|
|
+ tty_schedule_flip(port);
|
|
|
|
|
+
|
|
|
/* end of service */
|
|
/* end of service */
|
|
|
cyy_writeb(info, CyRIR, save_xir & 0x3f);
|
|
cyy_writeb(info, CyRIR, save_xir & 0x3f);
|
|
|
cyy_writeb(info, CyCAR, save_car);
|
|
cyy_writeb(info, CyCAR, save_car);
|
|
@@ -924,10 +917,11 @@ cyz_issue_cmd(struct cyclades_card *cinfo,
|
|
|
return 0;
|
|
return 0;
|
|
|
} /* cyz_issue_cmd */
|
|
} /* 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 BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
|
|
|
struct cyclades_card *cinfo = info->card;
|
|
struct cyclades_card *cinfo = info->card;
|
|
|
|
|
+ struct tty_port *port = &info->port;
|
|
|
unsigned int char_count;
|
|
unsigned int char_count;
|
|
|
int len;
|
|
int len;
|
|
|
#ifdef BLOCKMOVE
|
|
#ifdef BLOCKMOVE
|
|
@@ -946,80 +940,77 @@ static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty)
|
|
|
else
|
|
else
|
|
|
char_count = rx_put - rx_get + rx_bufsize;
|
|
char_count = rx_put - rx_get + rx_bufsize;
|
|
|
|
|
|
|
|
- if (char_count) {
|
|
|
|
|
|
|
+ if (!char_count)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
#ifdef CY_ENABLE_MONITORING
|
|
#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
|
|
#endif
|
|
|
- if (tty == NULL) {
|
|
|
|
|
- /* flush received characters */
|
|
|
|
|
- new_rx_get = (new_rx_get + char_count) &
|
|
|
|
|
- (rx_bufsize - 1);
|
|
|
|
|
- info->rflush_count++;
|
|
|
|
|
- } else {
|
|
|
|
|
|
|
+
|
|
|
#ifdef BLOCKMOVE
|
|
#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(tty, &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
|
|
#else
|
|
|
- len = tty_buffer_request_room(tty, 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(tty, 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
|
|
#endif
|
|
|
#ifdef CONFIG_CYZ_INTR
|
|
#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
|
|
#endif
|
|
|
- info->idle_stats.recv_idle = jiffies;
|
|
|
|
|
- tty_schedule_flip(tty);
|
|
|
|
|
- }
|
|
|
|
|
- /* 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 BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
|
|
|
struct cyclades_card *cinfo = info->card;
|
|
struct cyclades_card *cinfo = info->card;
|
|
|
|
|
+ struct tty_struct *tty;
|
|
|
u8 data;
|
|
u8 data;
|
|
|
unsigned int char_count;
|
|
unsigned int char_count;
|
|
|
#ifdef BLOCKMOVE
|
|
#ifdef BLOCKMOVE
|
|
@@ -1039,63 +1030,63 @@ static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty)
|
|
|
else
|
|
else
|
|
|
char_count = tx_get - tx_put - 1;
|
|
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
|
|
#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
|
|
#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
|
|
#endif
|
|
|
- tty_wakeup(tty);
|
|
|
|
|
|
|
+ tty_wakeup(tty);
|
|
|
|
|
+ tty_kref_put(tty);
|
|
|
ztxdone:
|
|
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)
|
|
static void cyz_handle_cmd(struct cyclades_card *cinfo)
|
|
|
{
|
|
{
|
|
|
struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
|
|
struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
|
|
|
- struct tty_struct *tty;
|
|
|
|
|
struct cyclades_port *info;
|
|
struct cyclades_port *info;
|
|
|
__u32 channel, param, fw_ver;
|
|
__u32 channel, param, fw_ver;
|
|
|
__u8 cmd;
|
|
__u8 cmd;
|
|
@@ -1108,23 +1099,20 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
|
|
|
special_count = 0;
|
|
special_count = 0;
|
|
|
delta_count = 0;
|
|
delta_count = 0;
|
|
|
info = &cinfo->ports[channel];
|
|
info = &cinfo->ports[channel];
|
|
|
- tty = tty_port_tty_get(&info->port);
|
|
|
|
|
- if (tty == NULL)
|
|
|
|
|
- continue;
|
|
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
switch (cmd) {
|
|
|
case C_CM_PR_ERROR:
|
|
case C_CM_PR_ERROR:
|
|
|
- tty_insert_flip_char(tty, 0, TTY_PARITY);
|
|
|
|
|
|
|
+ tty_insert_flip_char(&info->port, 0, TTY_PARITY);
|
|
|
info->icount.rx++;
|
|
info->icount.rx++;
|
|
|
special_count++;
|
|
special_count++;
|
|
|
break;
|
|
break;
|
|
|
case C_CM_FR_ERROR:
|
|
case C_CM_FR_ERROR:
|
|
|
- tty_insert_flip_char(tty, 0, TTY_FRAME);
|
|
|
|
|
|
|
+ tty_insert_flip_char(&info->port, 0, TTY_FRAME);
|
|
|
info->icount.rx++;
|
|
info->icount.rx++;
|
|
|
special_count++;
|
|
special_count++;
|
|
|
break;
|
|
break;
|
|
|
case C_CM_RXBRK:
|
|
case C_CM_RXBRK:
|
|
|
- tty_insert_flip_char(tty, 0, TTY_BREAK);
|
|
|
|
|
|
|
+ tty_insert_flip_char(&info->port, 0, TTY_BREAK);
|
|
|
info->icount.rx++;
|
|
info->icount.rx++;
|
|
|
special_count++;
|
|
special_count++;
|
|
|
break;
|
|
break;
|
|
@@ -1136,8 +1124,14 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
|
|
|
readl(&info->u.cyz.ch_ctrl->rs_status);
|
|
readl(&info->u.cyz.ch_ctrl->rs_status);
|
|
|
if (dcd & C_RS_DCD)
|
|
if (dcd & C_RS_DCD)
|
|
|
wake_up_interruptible(&info->port.open_wait);
|
|
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;
|
|
break;
|
|
|
case C_CM_MCTS:
|
|
case C_CM_MCTS:
|
|
@@ -1166,7 +1160,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
|
|
|
printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
|
|
printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
|
|
|
"port %ld\n", info->card, channel);
|
|
"port %ld\n", info->card, channel);
|
|
|
#endif
|
|
#endif
|
|
|
- cyz_handle_rx(info, tty);
|
|
|
|
|
|
|
+ cyz_handle_rx(info);
|
|
|
break;
|
|
break;
|
|
|
case C_CM_TXBEMPTY:
|
|
case C_CM_TXBEMPTY:
|
|
|
case C_CM_TXLOWWM:
|
|
case C_CM_TXLOWWM:
|
|
@@ -1176,7 +1170,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
|
|
|
printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
|
|
printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
|
|
|
"port %ld\n", info->card, channel);
|
|
"port %ld\n", info->card, channel);
|
|
|
#endif
|
|
#endif
|
|
|
- cyz_handle_tx(info, tty);
|
|
|
|
|
|
|
+ cyz_handle_tx(info);
|
|
|
break;
|
|
break;
|
|
|
#endif /* CONFIG_CYZ_INTR */
|
|
#endif /* CONFIG_CYZ_INTR */
|
|
|
case C_CM_FATAL:
|
|
case C_CM_FATAL:
|
|
@@ -1188,8 +1182,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
|
|
|
if (delta_count)
|
|
if (delta_count)
|
|
|
wake_up_interruptible(&info->port.delta_msr_wait);
|
|
wake_up_interruptible(&info->port.delta_msr_wait);
|
|
|
if (special_count)
|
|
if (special_count)
|
|
|
- tty_schedule_flip(tty);
|
|
|
|
|
- tty_kref_put(tty);
|
|
|
|
|
|
|
+ tty_schedule_flip(&info->port);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1255,17 +1248,11 @@ static void cyz_poll(unsigned long arg)
|
|
|
cyz_handle_cmd(cinfo);
|
|
cyz_handle_cmd(cinfo);
|
|
|
|
|
|
|
|
for (port = 0; port < cinfo->nports; port++) {
|
|
for (port = 0; port < cinfo->nports; port++) {
|
|
|
- struct tty_struct *tty;
|
|
|
|
|
-
|
|
|
|
|
info = &cinfo->ports[port];
|
|
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)
|
|
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 */
|
|
/* poll every 'cyz_polling_cycle' period */
|
|
|
expires = jiffies + cyz_polling_cycle;
|
|
expires = jiffies + cyz_polling_cycle;
|