/* If all data has been read, return 1, else 0 */ static int receive_data(enum port_type index, struct nozomi *dc) { u8 buf[RECEIVE_BUF_MAX] = { 0 }; int size; u32 offset = 4; struct port *port = &dc->port[index]; void __iomem *addr = port->dl_addr[port->toggle_dl]; struct tty_struct *tty = tty_port_tty_get(&port->port); int i, ret; size = __le32_to_cpu(readl(addr)); /* DBG1( "%d bytes port: %d", size, index); */ if (tty && tty_throttled(tty)) { DBG1("No room in tty, don't read data, don't ack interrupt, " "disable interrupt"); /* disable interrupt in downlink... */ disable_transmit_dl(index, dc); ret = 0; goto put; } if (unlikely(size == 0)) { dev_err(&dc->pdev->dev, "size == 0?\n"); ret = 1; goto put; } while (size > 0) { read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX); if (size == 1) { tty_insert_flip_char(&port->port, buf[0], TTY_NORMAL); size = 0; } else if (size < RECEIVE_BUF_MAX) { size -= tty_insert_flip_string(&port->port, (char *)buf, size); } else { i = tty_insert_flip_string(&port->port, (char *)buf, RECEIVE_BUF_MAX); size -= i; offset += i; } } set_bit(index, &dc->flip); ret = 1; put: tty_kref_put(tty); return ret; }
int tty_unthrottle_safe(struct tty_struct *tty) { int ret = 0; mutex_lock(&tty->throttle_mutex); if (tty_throttled(tty)) { if (tty->flow_change != TTY_UNTHROTTLE_SAFE) ret = 1; else { clear_bit(TTY_THROTTLED, &tty->flags); if (tty->ops->unthrottle) tty->ops->unthrottle(tty); } } mutex_unlock(&tty->throttle_mutex); return ret; }
static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct serial_state *info = tty->driver_data; unsigned long flags; unsigned int cflag = tty->termios.c_cflag; change_speed(tty, info, old_termios); /* Handle transition to B0 status */ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) { info->MCR &= ~(SER_DTR|SER_RTS); local_irq_save(flags); rtsdtr_ctrl(info->MCR); local_irq_restore(flags); } /* Handle transition away from B0 status */ if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { info->MCR |= SER_DTR; if (!C_CRTSCTS(tty) || !tty_throttled(tty)) info->MCR |= SER_RTS; local_irq_save(flags); rtsdtr_ctrl(info->MCR); local_irq_restore(flags); } /* Handle turning off CRTSCTS */ if ((old_termios->c_cflag & CRTSCTS) && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; rs_start(tty); } #if 0 /* * No need to wake up processes in open wait, since they * sample the CLOCAL flag once, and don't recheck it. * XXX It's not clear whether the current behavior is correct * or not. Hence, this may change..... */ if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty)) wake_up_interruptible(&info->open_wait); #endif }
/* * RX tasklet takes data out of the RX queue and hands it up to the TTY * layer until it refuses to take any more data (or is throttled back). * Then it issues reads for any further data. * * If the RX queue becomes full enough that no usb_request is queued, * the OUT endpoint may begin NAKing as soon as its FIFO fills up. * So QUEUE_SIZE packets plus however many the FIFO holds (usually two) * can be buffered before the TTY layer's buffers (currently 64 KB). */ static void gs_rx_push(unsigned long _port) { struct gs_port *port = (void *)_port; struct tty_struct *tty; struct list_head *queue = &port->read_queue; bool disconnect = false; bool do_push = false; /* hand any queued data to the tty */ spin_lock_irq(&port->port_lock); tty = port->port.tty; while (!list_empty(queue)) { struct usb_request *req; req = list_first_entry(queue, struct usb_request, list); /* leave data queued if tty was rx throttled */ if (tty && tty_throttled(tty)) break; switch (req->status) { case -ESHUTDOWN: disconnect = true; pr_vdebug("ttyGS%d: shutdown\n", port->port_num); break; default: /* presumably a transient fault */ pr_warn("ttyGS%d: unexpected RX status %d\n", port->port_num, req->status); /* FALLTHROUGH */ case 0: /* normal completion */ break; } /* push data to (open) tty */ if (req->actual && tty) { char *packet = req->buf; unsigned size = req->actual; unsigned n; int count; /* we may have pushed part of this packet already... */ n = port->n_read; if (n) { packet += n; size -= n; } count = tty_insert_flip_string(&port->port, packet, size); if (count) do_push = true; if (count != size) { /* stop pushing; TTY layer can't handle more */ port->n_read += count; pr_vdebug("ttyGS%d: rx block %d/%d\n", port->port_num, count, req->actual); break; } port->n_read = 0; } list_move(&req->list, &port->read_pool); port->read_started--; } /* Push from tty to ldisc; this is handled by a workqueue, * so we won't get callbacks and can hold port_lock */ if (do_push) tty_flip_buffer_push(&port->port); /* We want our data queue to become empty ASAP, keeping data * in the tty and ldisc (not here). If we couldn't push any * this time around, there may be trouble unless there's an * implicit tty_unthrottle() call on its way... * * REVISIT we should probably add a timer to keep the tasklet * from starving ... but it's not clear that case ever happens. */ if (!list_empty(queue) && tty) { if (!tty_throttled(tty)) { if (do_push) tasklet_schedule(&port->push); else pr_warn("ttyGS%d: RX not scheduled?\n", port->port_num); } } /* If we're still connected, refill the USB RX queue. */ if (!disconnect && port->port_usb) gs_start_rx(port); spin_unlock_irq(&port->port_lock); }