Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cf045260 authored by Jag Raman's avatar Jag Raman Committed by David S. Miller
Browse files

sparc64: vcc: Add write & write_room TTY operations



Add handlers to support TTY write & write_room operations

Signed-off-by: default avatarJagannathan Raman <jag.raman@oracle.com>
Reviewed-by: default avatarLiam Merwick <liam.merwick@oracle.com>
Reviewed-by: default avatarShannon Nelson <shannon.nelson@oracle.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6a3ff25b
Loading
Loading
Loading
Loading
+98 −3
Original line number Diff line number Diff line
@@ -844,10 +844,105 @@ static void vcc_hangup(struct tty_struct *tty)
	tty_port_hangup(tty->port);
}

static int vcc_write(struct tty_struct *tty, const unsigned char *buf,
		     int count)
{
	struct vcc_port *port;
	struct vio_vcc *pkt;
	unsigned long flags;
	int total_sent = 0;
	int tosend = 0;
	int rv = -EINVAL;

	if (unlikely(!tty)) {
		pr_err("VCC: write: Invalid TTY handle\n");
		return -ENXIO;
	}

	port = vcc_get_ne(tty->index);
	if (unlikely(!port)) {
		pr_err("VCC: write: Failed to find VCC port");
		return -ENODEV;
	}

	spin_lock_irqsave(&port->lock, flags);

	pkt = &port->buffer;
	pkt->tag.type = VIO_TYPE_DATA;

	while (count > 0) {
		/* Minimum of data to write and space available */
		tosend = min(count, (VCC_BUFF_LEN - port->chars_in_buffer));

		if (!tosend)
			break;

		memcpy(&pkt->data[port->chars_in_buffer], &buf[total_sent],
		       tosend);
		port->chars_in_buffer += tosend;
		pkt->tag.stype = tosend;

		vccdbg("TAG [%02x:%02x:%04x:%08x]\n", pkt->tag.type,
		       pkt->tag.stype, pkt->tag.stype_env, pkt->tag.sid);
		vccdbg("DATA [%s]\n", pkt->data);
		vccdbgl(port->vio.lp);

		/* Since we know we have enough room in VCC buffer for tosend
		 * we record that it was sent regardless of whether the
		 * hypervisor actually took it because we have it buffered.
		 */
		rv = ldc_write(port->vio.lp, pkt, (VIO_TAG_SIZE + tosend));
		vccdbg("VCC: write: ldc_write(%d)=%d\n",
		       (VIO_TAG_SIZE + tosend), rv);

		total_sent += tosend;
		count -= tosend;
		if (rv < 0) {
			vcc_kick_tx(port);
			break;
		}

		port->chars_in_buffer = 0;
	}

	spin_unlock_irqrestore(&port->lock, flags);

	vcc_put(port, false);

	vccdbg("VCC: write: total=%d rv=%d", total_sent, rv);

	return total_sent ? total_sent : rv;
}

static int vcc_write_room(struct tty_struct *tty)
{
	struct vcc_port *port;
	u64 num;

	if (unlikely(!tty)) {
		pr_err("VCC: write_room: Invalid TTY handle\n");
		return -ENXIO;
	}

	port = vcc_get_ne(tty->index);
	if (unlikely(!port)) {
		pr_err("VCC: write_room: Failed to find VCC port\n");
		return -ENODEV;
	}

	num = VCC_BUFF_LEN - port->chars_in_buffer;

	vcc_put(port, false);

	return num;
}

static const struct tty_operations vcc_ops = {
	.open		= vcc_open,
	.close		= vcc_close,
	.hangup		= vcc_hangup,
	.write		= vcc_write,
	.write_room	= vcc_write_room,
};

#define VCC_TTY_FLAGS   (TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_REAL_RAW)