static void hisi_clkmbox_default_complete(struct hisi_mbox_task *tx_task)
{
	struct clk_mbox_context *context;

	if (tx_task->tx_error) {
		pr_err("[%s]: tx_task->tx_error = %d\n",
				__func__, tx_task->tx_error);
		goto err;
	}

	context = (struct clk_mbox_context *) tx_task->context;
	if (context) {
		if (tx_task->tx_buffer[0] == tx_task->ack_buffer[0]) {
			pr_info("compelte the context! freq = %d\n",
					tx_task->ack_buffer[1]);

			/*the unit of ack_buffer[1] is MHZ*/
			context->freq = tx_task->ack_buffer[1] * 1000000;
		} else {
			pr_info("compelte the context! freq = 0\n");
			context->freq = 0;
		}
		complete(&context->complete);
	}

err:
	/* reset the buffer */
	kfree(tx_task->tx_buffer);

	tx_task->tx_buffer = NULL;

	hisi_mbox_task_free(&tx_task);
}
static void inputhub_mcu_send_complete(struct hisi_mbox_task *tx_task)
{
#if 0
    if (tx_task->tx_buffer)
        kfree((void *)tx_task->tx_buffer);
    tx_task->tx_buffer = NULL;

    hisi_mbox_task_free(&tx_task);
#endif
    complete(&send_complete);
    return;
}
/* IPC complete function. */
static void adc_complete_func(struct hisi_mbox_task *tx_task)
{
#ifdef HI3XXX_HKADC_DEBUG
	int i;
	for (i = 0; i < tx_task->ack_buffer_len; i++)
		pr_info("%s_debug:[complete] msg[%d] = 0x%x\n", MODULE_NAME, i, tx_task->ack_buffer[i]);
#endif
	if (tx_task->tx_error)
		pr_err("%s: mail box complete error!\n", MODULE_NAME);

	hisi_mbox_task_free(&tx_task);
	return;
}
/* AP sends msgs to LPM3 for adc sampling&converting. */
static int adc_send_ipc_to_lpm3(int channel)
{
	struct hisi_mbox_task *adc_tx_task;
	int loop = ADC_IPC_MAX_CNT;
	int ret = 0;

	if (channel > ADC_CHN_MAX) {
		pr_err("%s: invalid channel!\n", MODULE_NAME);
		ret = -EINVAL;
		goto err_adc_channel;
	}

	if (!hisi_adc_dev) {
		pr_err("%s: adc dev is not initialized yet!\n", MODULE_NAME);
		ret = -ENODEV;
		goto err_adc_dev;
	}

	if (hisi_adc_dev->tx_msg[ADC_IPC_CMD_TYPE] != ADC_IPC_DATA)
		hisi_adc_dev->tx_msg[ADC_IPC_CMD_TYPE] = ADC_IPC_DATA;

	hisi_adc_dev->info.channel = channel;
	hisi_adc_dev->tx_msg[ADC_IPC_CMD_CHANNEL] = channel;

	adc_tx_task = hisi_mbox_task_alloc(hisi_adc_dev->mbox, HISI_MAILBOX_RP_LPM3, hisi_adc_dev->tx_msg,
							ADC_IPC_CMD_LEN, 1, adc_complete_func, NULL);
	if (!adc_tx_task) {
		pr_err("%s: fail to alloc mbox task!\n", MODULE_NAME);
		ret = -ENOMEM;
		goto err_alloc_task;
	}

	do {
		ret = hisi_mbox_msg_send_async(hisi_adc_dev->mbox, adc_tx_task);
		loop--;
	} while (ret == -ENOMEM && loop > 0);
	if (ret) {
		pr_err("%s: fail to send mbox msg, ret = %d!\n", MODULE_NAME, ret);
		goto err_msg_async;
	}

	return ret;

err_msg_async:
	hisi_mbox_task_free(&adc_tx_task);
err_alloc_task:
	hisi_adc_dev->info.channel = ADC_RESULT_ERR;
err_adc_dev:
err_adc_channel:
	return ret;
}
static int hisi_clkmbox_send_ipc(mbox_msg_t *msg, void *context, int autoack)
{
	struct hisi_mbox_task *tx_task;
	int loop = MAX_SEND_IPC_TRY;
	mbox_msg_t	*tx_msg;
	int ret, i;

	tx_msg = kzalloc(sizeof(mbox_msg_t) * LPM3_CMD_LEN, GFP_ATOMIC);
	if (!tx_msg) {
		pr_err("[%s] fail to alloc tx_msg!\n", __func__);
		ret = -ENOMEM;
		goto err;
	}

	/* construct cmd */
	for (i = 0; i < LPM3_CMD_LEN; i++) {
		tx_msg[i] = msg[i];
		pr_debug("[%s] tx_msg[i] = 0x%x\n",	__func__, tx_msg[i]);
	}


	tx_task = hisi_mbox_task_alloc(mbox_clk->mbox, HISI_MAILBOX_RP_LPM3,
							tx_msg, LPM3_CMD_LEN, autoack, hisi_clkmbox_default_complete, context);
	if (!tx_task) {
		pr_err("[%s] fail to alloc mbox task!\n", __func__);
		ret = -ENOMEM;
		goto err_task;
	}

	/* try again if failing to send */
	do {
		ret = hisi_mbox_msg_send_async(mbox_clk->mbox, tx_task);
		loop--;
	} while (ret == -ENOMEM && loop > 0);
	if (ret) {
		pr_err("[%s] fail to send mbox msg, ret = %d!\n",
				__func__, ret);
		goto err_snd_async;
	}

	return 0;

err_snd_async:
	hisi_mbox_task_free(&tx_task);
err_task:
	kfree(tx_msg);
	tx_msg = NULL;
err:
	return ret;
}
static void mbox_debugfs_send_work(struct work_struct *work)
{
	struct mbox_info *mbox_info =
		container_of(work, struct mbox_info, work);
	struct mbox_task *task_info = NULL;
	struct hisi_mbox_task *tx_task = NULL;
	int i = 0;
	int time = debugfs_ipc_times;

	while (time) {
		pr_info("%s debugfs msg send NO.%d\n",
				mbox_info->mbox->tx->name, ++i);
		task_info = kmalloc(sizeof(*task_info), GFP_KERNEL);
		if (!task_info)
			continue;
		task_info->mbox_index = mbox_info->index;
		task_info->mail_index = i;

		tx_task = mbox_debugfs_get_task(mbox_info->mbox,
						mbox_info->msg,
						mbox_info->len,
						mbox_info->rp_name,
						task_info);
		if (!tx_task) {
			msleep(100);
			continue;
		}

		if (hisi_mbox_msg_send_async(mbox_info->mbox, tx_task)) {
			kfree(task_info->tx_buffer);
			kfree(task_info);
			hisi_mbox_task_free(&tx_task);

			if (i == debugfs_ipc_times) {
				debugfs_ipc_times -= 1;
				break;
			}

			msleep(100);
		}

		time--;
	}

	return;
}
static void mbox_debugfs_complete(struct hisi_mbox_task *tx_task)
{
	struct mbox_task *task_info = (struct mbox_task *)tx_task->context;
	int i;

	if (task_info) {
		pr_debug("mailbox-%d debugfs msg NO.%d complete\n",
			task_info->mbox_index, task_info->mail_index);

		kfree(task_info->tx_buffer);
		kfree(task_info);
		tx_task->context = NULL;
	}

	for (i = 0; i < tx_task->ack_buffer_len; i++)
		pr_debug("msg[%d] = 0x%x\n", i, tx_task->ack_buffer[i]);

	hisi_mbox_task_free(&tx_task);
	return;
}
static void inputhub_power_on_complete(struct hisi_mbox_task *tx_task)
{
    hisi_mbox_task_free(&tx_task);
    return;
}
int inputhub_mcu_send(const char *buf, unsigned long length)
{
    struct hisi_mbox_task *tx_task = NULL;
    mbox_msg_t *tx_buffer = NULL;
    mbox_msg_len_t len=0;
    int i = 0;
    int ret = -1;

    if(NULL==mbox)
        inputhub_mcu_connect();
    if(NULL==mbox)
        return ret;

    len = (length + sizeof(mbox_msg_t) - 1) / (sizeof(mbox_msg_t));
    //todo:send 256 bytes max one time, and repeat until buf was sent.
    tx_buffer = (mbox_msg_t *)kmalloc(sizeof(mbox_msg_t)*len, GFP_KERNEL);
    if (!tx_buffer)
        return ret;

    memcpy(tx_buffer, buf, length);
    pr_debug("inputhub_mcu_send------------->length = %d, len = %d\n", (int)length, (int)len);
    for (i = 0; i < len; i++)
        pr_debug("tx_buffer[%d] = 0x%x\n", i, tx_buffer[i]);

    tx_task = hisi_mbox_task_alloc(mbox,
                HISI_MAILBOX_RP_IOM3,
                tx_buffer,
                len,
                0,
                inputhub_mcu_send_complete,
                NULL);

    if (!tx_task) {
        kfree((void *)tx_buffer);
        return ret;
    }

    INIT_COMPLETION(send_complete);
    ret=hisi_mbox_msg_send_async(mbox,tx_task);
    if(ret)
    {
        hwlog_err("hisi_mbox_msg_send_async return %d.\n", ret);
        if (tx_task->tx_buffer)
            kfree((void *)tx_task->tx_buffer);
        tx_task->tx_buffer = NULL;
        hisi_mbox_task_free(&tx_task);
        return -1;
    }

    wait_for_completion(&send_complete);
    if ((-ETIMEOUT) == tx_task->tx_error) {
        hwlog_err("send failed timeout\n");
        if(!dsm_client_ocuppy(shb_dclient)){
            dsm_client_record(shb_dclient, "IOM3RSTSTAT: 0x%x\n", read_reg32(IOM3RSTSTAT_ADDR));
            dsm_client_record(shb_dclient, "PERRSTSTAT4: 0x%x\n", read_reg32(PERRSTSTAT4_ADDR));
            dsm_client_record(shb_dclient, "PERSTAT5: 0x%x\n", read_reg32(PERSTAT5_ADDR));
            dsm_client_record(shb_dclient, "IOM3CLKEN: 0x%x\n", read_reg32(IOM3CLKEN_ADDR));
            dsm_client_notify(shb_dclient, DSM_SHB_ERR_IPC_TIMEOUT);
        }
        ret = -1;
    }else{
        hwlog_debug("send success\n");
        ret = 0;
    }

    kfree((void *)tx_task->tx_buffer);
    tx_task->tx_buffer = NULL;
    hisi_mbox_task_free(&tx_task);
    return ret;
}