Ejemplo n.º 1
0
/* 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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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
}
Ejemplo n.º 4
0
/*
 * 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);
}