int ps3_vuart_write()

in ps3-vuart.c [474:532]


int ps3_vuart_write(struct ps3_system_bus_device *dev, const void *buf,
	unsigned int bytes)
{
	static unsigned long dbg_number;
	int result;
	struct ps3_vuart_port_priv *priv = to_port_priv(dev);
	unsigned long flags;
	struct list_buffer *lb;

	dev_dbg(&dev->core, "%s:%d: %u(%xh) bytes\n", __func__, __LINE__,
		bytes, bytes);

	spin_lock_irqsave(&priv->tx_list.lock, flags);

	if (list_empty(&priv->tx_list.head)) {
		u64 bytes_written;

		result = ps3_vuart_raw_write(dev, buf, bytes, &bytes_written);

		spin_unlock_irqrestore(&priv->tx_list.lock, flags);

		if (result) {
			dev_dbg(&dev->core,
				"%s:%d: ps3_vuart_raw_write failed\n",
				__func__, __LINE__);
			return result;
		}

		if (bytes_written == bytes) {
			dev_dbg(&dev->core, "%s:%d: wrote %xh bytes\n",
				__func__, __LINE__, bytes);
			return 0;
		}

		bytes -= bytes_written;
		buf += bytes_written;
	} else
		spin_unlock_irqrestore(&priv->tx_list.lock, flags);

	lb = kmalloc(sizeof(struct list_buffer) + bytes, GFP_KERNEL);

	if (!lb)
		return -ENOMEM;

	memcpy(lb->data, buf, bytes);
	lb->head = lb->data;
	lb->tail = lb->data + bytes;
	lb->dbg_number = ++dbg_number;

	spin_lock_irqsave(&priv->tx_list.lock, flags);
	list_add_tail(&lb->link, &priv->tx_list.head);
	ps3_vuart_enable_interrupt_tx(dev);
	spin_unlock_irqrestore(&priv->tx_list.lock, flags);

	dev_dbg(&dev->core, "%s:%d: queued buf_%lu, %xh bytes\n",
		__func__, __LINE__, lb->dbg_number, bytes);

	return 0;
}