static int mipi_hsi_send(struct link_device *ld, struct io_device *iod,
			struct sk_buff *skb)
{
	int ret;
	struct mipi_link_device *mipi_ld = to_mipi_link_device(ld);

	struct sk_buff_head *txq;

	switch (iod->format) {
	case IPC_RAW:
		txq = &ld->sk_raw_tx_q;
		break;

	case IPC_RAMDUMP:
		ret = if_hsi_write(&mipi_ld->hsi_channles[
					HSI_CP_RAMDUMP_CHANNEL],
					(u32 *)skb->data, skb->len);
		if (ret < 0) {
			pr_err("[MIPI-HSI] write fail : %d\n", ret);
			dev_kfree_skb_any(skb);
			return ret;
		} else
			pr_debug("[MIPI-HSI] write Done\n");
		dev_kfree_skb_any(skb);
		return ret;

	case IPC_BOOT:
		ret = if_hsi_write(&mipi_ld->hsi_channles[
					HSI_FLASHLESS_CHANNEL],
					(u32 *)skb->data, skb->len);
		if (ret < 0) {
			pr_err("[MIPI-HSI] write fail : %d\n", ret);
			dev_kfree_skb_any(skb);
			return ret;
		} else
			pr_debug("[MIPI-HSI] write Done\n");
		dev_kfree_skb_any(skb);
		return ret;

	case IPC_FMT:
	case IPC_RFS:
	default:
		txq = &ld->sk_fmt_tx_q;
		break;
	}

	/* save io device into cb area */
	*((struct io_device **)skb->cb) = iod;
	/* en queue skb data */
	skb_queue_tail(txq, skb);

	if (iod->format == IPC_RAW)
		queue_delayed_work(ld->tx_raw_wq, &ld->tx_delayed_work, 0);
	else
		queue_work(ld->tx_wq, &ld->tx_work);
	return skb->len;
}
static void if_hsi_cmd_work(struct work_struct *work)
{
	int ret;
	int retry_count = 0;
	unsigned long int flags;
	struct mipi_link_device *mipi_ld =
	container_of(work, struct mipi_link_device, cmd_work.work);
	struct if_hsi_channel *channel =
			&mipi_ld->hsi_channles[HSI_CONTROL_CHANNEL];
	struct if_hsi_command *hsi_cmd;

	pr_debug("[MIPI-HSI] cmd_work\n");

	do {
		spin_lock_irqsave(&mipi_ld->list_cmd_lock, flags);
		if (!list_empty(&mipi_ld->list_of_hsi_cmd)) {
			hsi_cmd = list_entry(mipi_ld->list_of_hsi_cmd.next,
					struct if_hsi_command, list);
			list_del(&hsi_cmd->list);
			spin_unlock_irqrestore(&mipi_ld->list_cmd_lock, flags);

			channel->send_step = STEP_TX;
			if_hsi_set_wakeline(channel, 1);
			mod_timer(&mipi_ld->hsi_acwake_down_timer, jiffies +
					HSI_ACWAKE_DOWN_TIMEOUT);
		} else {
			spin_unlock_irqrestore(&mipi_ld->list_cmd_lock, flags);
			channel->send_step = STEP_IDLE;
			break;
		}
		pr_debug("[MIPI-HSI] take command : %08x\n", hsi_cmd->command);

		ret = if_hsi_write(channel, &hsi_cmd->command, 4);
		if (ret < 0) {
			pr_err("[MIPI-HSI] write command fail : %d\n", ret);

			retry_count++;
			if (retry_count > 5) {
				channel->send_step = STEP_IDLE;
				kfree(hsi_cmd);
				return;
			}

			hsi_conn_err_recovery(mipi_ld);
			channel->send_step = STEP_IDLE;

			spin_lock_irqsave(&mipi_ld->list_cmd_lock, flags);
			list_add(&hsi_cmd->list, &mipi_ld->list_of_hsi_cmd);
			spin_unlock_irqrestore(&mipi_ld->list_cmd_lock, flags);

			pr_err("[MIPI-HSI] retry write command : %d\n",
						retry_count);
			continue;
		}
		pr_debug("[MIPI-HSI] SEND CMD : %08x\n", hsi_cmd->command);

		kfree(hsi_cmd);
	} while (true);
Exemplo n.º 3
0
int hsi_proto_write(int ch, u32 *buffer, int length)
{

	DECLARE_WAITQUEUE(wait, current);
	u32 *data;
	unsigned int data_len = 0, ret = -1;
	struct protocol_queue *entry;

        ret = if_hsi_write(ch, buffer, length);
        if (ret < 0) {
		pr_err("HSI Write ERROR %s \n", __func__);
                goto out2;
        }else
	spin_lock_bh(&hsi_protocol_data[ch].lock);
        hsi_protocol_data[ch].poll_event &= ~(POLLOUT | POLLWRNORM);
        add_wait_queue(&hsi_protocol_data[ch].tx_wait, &wait);
        spin_unlock_bh(&hsi_protocol_data[ch].lock);

	for (;;) {
                data = NULL;
                data_len = 0;

                set_current_state(TASK_INTERRUPTIBLE);
                spin_lock_bh(&hsi_protocol_data[ch].lock);
                if (!list_empty(&hsi_protocol_data[ch].tx_queue)) {
                        entry = list_entry(hsi_protocol_data[ch].tx_queue.next,
                                           struct protocol_queue, list);
                        data = entry->data;
                        data_len = entry->count;
                        list_del(&entry->list);
                        kfree(entry);
                }
                spin_unlock_bh(&hsi_protocol_data[ch].lock);

                if (data_len) {
                        pr_debug("%s, TX finished\n", __func__);
                        //printk("%s, TX finished, data_len = %d, ch-> %d\n", __func__,length,ch);
                        ret = data_len;
                        break;
                } else if (signal_pending(current)) {
                        pr_debug("%s, ERESTARTSYS\n", __func__);
                        ret = -ERESTARTSYS;
                        goto out;
                }

                schedule();
        }