/**
 * Dump individual input/output item pair.
 *
 * @s:   pointer to output file
 */
static void smp2p_item(struct seq_file *s, int remote_pid)
{
	struct smp2p_smem *out_ptr;
	struct smp2p_smem *in_ptr;
	struct smp2p_interrupt_config *int_cfg;
	char tmp_buff[64];
	int state;
	int entry;
	struct smp2p_entry_v1 *out_entries = NULL;
	struct smp2p_entry_v1 *in_entries = NULL;
	int out_valid = 0;
	int in_valid = 0;
	char entry_name[SMP2P_MAX_ENTRY_NAME];

	int_cfg = smp2p_get_interrupt_config();
	if (!int_cfg)
		return;
	if (!int_cfg[remote_pid].is_configured &&
			remote_pid != SMP2P_REMOTE_MOCK_PROC)
		return;

	out_ptr = smp2p_get_out_item(remote_pid, &state);
	in_ptr = smp2p_get_in_item(remote_pid);

	if (!out_ptr && !in_ptr)
		return;

	/* print item headers */
	seq_printf(s, "%s%s\n",
		" ====================================== ",
		"======================================");
	scnprintf(tmp_buff, sizeof(tmp_buff),
		"Apps(%d)->%s(%d)",
		SMP2P_APPS_PROC, int_cfg[remote_pid].name, remote_pid);
	seq_printf(s, "| %-37s", tmp_buff);

	scnprintf(tmp_buff, sizeof(tmp_buff),
		"%s(%d)->Apps(%d)",
		int_cfg[remote_pid].name, remote_pid, SMP2P_APPS_PROC);
	seq_printf(s, "| %-37s|\n", tmp_buff);
	seq_printf(s, "%s%s\n",
		" ====================================== ",
		"======================================");

	smp2p_item_header1(tmp_buff, sizeof(tmp_buff), out_ptr, state);
	seq_printf(s, "| %-37s", tmp_buff);
	smp2p_item_header1(tmp_buff, sizeof(tmp_buff), in_ptr, -1);
	seq_printf(s, "| %-37s|\n", tmp_buff);

	smp2p_item_header2(tmp_buff, sizeof(tmp_buff), out_ptr);
	seq_printf(s, "| %-37s", tmp_buff);
	smp2p_item_header2(tmp_buff, sizeof(tmp_buff), in_ptr);
	seq_printf(s, "| %-37s|\n", tmp_buff);

	smp2p_item_header3(tmp_buff, sizeof(tmp_buff), out_ptr);
	seq_printf(s, "| %-37s", tmp_buff);
	smp2p_item_header3(tmp_buff, sizeof(tmp_buff), in_ptr);
	seq_printf(s, "| %-37s|\n", tmp_buff);

	seq_printf(s, " %s%s\n",
		"-------------------------------------- ",
		"--------------------------------------");
	seq_printf(s, "| %-37s",
		"Entry Name       Value");
	seq_printf(s, "| %-37s|\n",
		"Entry Name       Value");
	seq_printf(s, " %s%s\n",
		"-------------------------------------- ",
		"--------------------------------------");

	/* print entries */
	if (out_ptr) {
		out_entries = (struct smp2p_entry_v1 *)((void *)out_ptr +
				sizeof(struct smp2p_smem));
		out_valid = SMP2P_GET_ENT_VALID(out_ptr->valid_total_ent);
	}

	if (in_ptr) {
		in_entries = (struct smp2p_entry_v1 *)((void *)in_ptr +
				sizeof(struct smp2p_smem));
		in_valid = SMP2P_GET_ENT_VALID(in_ptr->valid_total_ent);
	}

	for (entry = 0; out_entries || in_entries; ++entry) {
		if (out_entries && entry < out_valid) {
			memcpy_fromio(entry_name, out_entries->name,
							SMP2P_MAX_ENTRY_NAME);
			scnprintf(tmp_buff, sizeof(tmp_buff),
					"%-16s 0x%08x",
					entry_name,
					out_entries->entry);
			++out_entries;
		} else {
			out_entries = NULL;
			scnprintf(tmp_buff, sizeof(tmp_buff), "None");
		}
		seq_printf(s, "| %-37s", tmp_buff);

		if (in_entries && entry < in_valid) {
			memcpy_fromio(entry_name, in_entries->name,
							SMP2P_MAX_ENTRY_NAME);
			scnprintf(tmp_buff, sizeof(tmp_buff),
					"%-16s 0x%08x",
					entry_name,
					in_entries->entry);
			++in_entries;
		} else {
			in_entries = NULL;
			scnprintf(tmp_buff, sizeof(tmp_buff), "None");
		}
		seq_printf(s, "| %-37s|\n", tmp_buff);
	}
	seq_printf(s, " %s%s\n\n",
		"-------------------------------------- ",
		"--------------------------------------");
}
static void smp2p_ut_local_ssr_ack(struct seq_file *s)
{
	int failed = 0;
	struct msm_smp2p_remote_mock *rmp = NULL;
	int ret;

	seq_printf(s, "Running %s\n", __func__);
	do {
		struct smp2p_smem *rhdr;
		struct smp2p_smem *lhdr;
		int negotiation_state;

		/*                                                     */
		ret = smp2p_reset_mock_edge();
		UT_ASSERT_INT(ret, ==, 0);
		rmp = msm_smp2p_get_remote_mock();
		UT_ASSERT_PTR(rmp, !=, NULL);
		rhdr = &rmp->remote_item.header;

		rmp->rx_interrupt_count = 0;
		memset(&rmp->remote_item, 0, sizeof(struct smp2p_smem_item));
		rhdr->magic = SMP2P_MAGIC;
		SMP2P_SET_LOCAL_PID(rhdr->rem_loc_proc_id,
				SMP2P_REMOTE_MOCK_PROC);
		SMP2P_SET_REMOTE_PID(rhdr->rem_loc_proc_id, SMP2P_APPS_PROC);
		SMP2P_SET_VERSION(rhdr->feature_version, 1);
		SMP2P_SET_FEATURES(rhdr->feature_version, 0);
		SMP2P_SET_ENT_TOTAL(rhdr->valid_total_ent, SMP2P_MAX_ENTRY);
		SMP2P_SET_ENT_VALID(rhdr->valid_total_ent, 0);
		rhdr->flags = 0x0;
		msm_smp2p_set_remote_mock_exists(true);
		rmp->tx_interrupt();

		/*                     */
		lhdr = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC,
					&negotiation_state);
		UT_ASSERT_PTR(NULL, !=, lhdr);
		UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENED);
		UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);

		/*                                   */
		rmp->rx_interrupt_count = 0;
		SMP2P_SET_RESTART_DONE(rhdr->flags, 1);
		rmp->tx_interrupt();
		UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags));
		UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_ACK(lhdr->flags));
		UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 0);

		/*                                                  */
		ret = smp2p_reset_mock_edge();
		UT_ASSERT_INT(ret, ==, 0);
		rmp = msm_smp2p_get_remote_mock();
		UT_ASSERT_PTR(rmp, !=, NULL);
		rhdr = &rmp->remote_item.header;

		rmp->rx_interrupt_count = 0;
		memset(&rmp->remote_item, 0, sizeof(struct smp2p_smem_item));
		rhdr->magic = SMP2P_MAGIC;
		SMP2P_SET_LOCAL_PID(rhdr->rem_loc_proc_id,
				SMP2P_REMOTE_MOCK_PROC);
		SMP2P_SET_REMOTE_PID(rhdr->rem_loc_proc_id, SMP2P_APPS_PROC);
		SMP2P_SET_VERSION(rhdr->feature_version, 1);
		SMP2P_SET_FEATURES(rhdr->feature_version,
				SMP2P_FEATURE_SSR_ACK);
		SMP2P_SET_ENT_TOTAL(rhdr->valid_total_ent, SMP2P_MAX_ENTRY);
		SMP2P_SET_ENT_VALID(rhdr->valid_total_ent, 0);
		rmp->rx_interrupt_count = 0;
		rhdr->flags = 0x0;
		msm_smp2p_set_remote_mock_exists(true);
		rmp->tx_interrupt();

		/*                     */
		lhdr = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC,
					&negotiation_state);
		UT_ASSERT_PTR(NULL, !=, lhdr);
		UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENED);
		UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);

		/*                                */
		rmp->rx_interrupt_count = 0;
		SMP2P_SET_RESTART_DONE(rhdr->flags, 1);
		rmp->tx_interrupt();
		UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags));
		UT_ASSERT_INT(1, ==, SMP2P_GET_RESTART_ACK(lhdr->flags));
		UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);

		rmp->rx_interrupt_count = 0;
		SMP2P_SET_RESTART_DONE(rhdr->flags, 0);
		rmp->tx_interrupt();
		UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_DONE(lhdr->flags));
		UT_ASSERT_INT(0, ==, SMP2P_GET_RESTART_ACK(lhdr->flags));
		UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);

		seq_puts(s, "\tOK\n");
	} while (0);

	if (failed) {
		pr_err("%s: Failed\n", __func__);
		seq_puts(s, "\tFailed\n");
	}
}
/**
 * smp2p_ut_local_early_open - Verify pre-negotiation opening.
 *
 * @s: pointer to output file
 *
 * Verify entry creation for opening entries before negotiation is complete.
 */
static void smp2p_ut_local_early_open(struct seq_file *s)
{
	int failed = 0;
	struct msm_smp2p_out *smp2p_obj;
	struct msm_smp2p_remote_mock *rmp = NULL;
	struct smp2p_smem *outbound_item;
	int negotiation_state;
	int ret;
	uint32_t test_request;
	uint32_t test_response = 0;
	static struct mock_cb_data cb_data;

	seq_printf(s, "Running %s\n", __func__);
	mock_cb_data_init(&cb_data);
	do {
		/* initialize mock edge, but don't enable, yet */
		ret = smp2p_reset_mock_edge();
		UT_ASSERT_INT(ret, ==, 0);

		rmp = msm_smp2p_get_remote_mock();
		UT_ASSERT_PTR(rmp, !=, NULL);

		rmp->rx_interrupt_count = 0;
		memset(&rmp->remote_item, 0,
			sizeof(struct smp2p_smem_item));
		rmp->remote_item.header.magic = SMP2P_MAGIC;
		SMP2P_SET_LOCAL_PID(
		rmp->remote_item.header.rem_loc_proc_id,
						SMP2P_REMOTE_MOCK_PROC);
		SMP2P_SET_REMOTE_PID(
		rmp->remote_item.header.rem_loc_proc_id,
						SMP2P_APPS_PROC);
		SMP2P_SET_VERSION(
		rmp->remote_item.header.feature_version, 1);
		SMP2P_SET_FEATURES(
		rmp->remote_item.header.feature_version, 0);
		SMP2P_SET_ENT_TOTAL(
		rmp->remote_item.header.valid_total_ent, SMP2P_MAX_ENTRY);
		SMP2P_SET_ENT_VALID(
		rmp->remote_item.header.valid_total_ent, 0);
		rmp->remote_item.header.reserved = 0x0;

		msm_smp2p_set_remote_mock_exists(false);
		UT_ASSERT_PTR(NULL, ==,
				smp2p_get_in_item(SMP2P_REMOTE_MOCK_PROC));

		/* initiate open, but verify it doesn't complete */
		ret = msm_smp2p_out_open(SMP2P_REMOTE_MOCK_PROC, "smp2p",
			&cb_data.nb, &smp2p_obj);
		UT_ASSERT_INT(ret, ==, 0);

		UT_ASSERT_INT(
			(int)wait_for_completion_timeout(
					&cb_data.cb_completion, HZ / 8),
			==, 0);
		UT_ASSERT_INT(cb_data.cb_count, ==, 0);
		UT_ASSERT_INT(cb_data.event_open, ==, 0);
		UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);

		outbound_item = smp2p_get_out_item(SMP2P_REMOTE_MOCK_PROC,
				&negotiation_state);
		UT_ASSERT_PTR(outbound_item, !=, NULL);
		UT_ASSERT_INT(negotiation_state, ==, SMP2P_EDGE_STATE_OPENING);
		UT_ASSERT_INT(0, ==,
			SMP2P_GET_ENT_VALID(outbound_item->valid_total_ent));

		/* verify that read/write don't work yet */
		rmp->rx_interrupt_count = 0;
		test_request = 0x0;
		ret = msm_smp2p_out_write(smp2p_obj, test_request);
		UT_ASSERT_INT(ret, ==, -ENODEV);
		UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 0);

		ret = msm_smp2p_out_read(smp2p_obj, &test_response);
		UT_ASSERT_INT(ret, ==, -ENODEV);

		/* allocate remote entry and verify open */
		msm_smp2p_set_remote_mock_exists(true);
		rmp->tx_interrupt();

		UT_ASSERT_INT(
			(int)wait_for_completion_timeout(
					&cb_data.cb_completion, HZ / 2),
			>, 0);
		UT_ASSERT_INT(cb_data.cb_count, ==, 1);
		UT_ASSERT_INT(cb_data.event_open, ==, 1);
		UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2);

		/* do write (test outbound entries) */
		rmp->rx_interrupt_count = 0;
		test_request = 0xC0DE;
		ret = msm_smp2p_out_write(smp2p_obj, test_request);
		UT_ASSERT_INT(ret, ==, 0);
		UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1);

		/* do read (test inbound entries) */
		ret = msm_smp2p_out_read(smp2p_obj, &test_response);
		UT_ASSERT_INT(ret, ==, 0);
		UT_ASSERT_INT(test_request, ==, test_response);

		ret = msm_smp2p_out_close(&smp2p_obj);
		UT_ASSERT_INT(ret, ==, 0);
		UT_ASSERT_PTR(smp2p_obj, ==, 0);

		seq_printf(s, "\tOK\n");
	} while (0);

	if (failed) {
		pr_err("%s: Failed\n", __func__);
		seq_printf(s, "\tFailed\n");
		(void)msm_smp2p_out_close(&smp2p_obj);
	}
}
static void smp2p_ut_remotesubsys_ssr_ack(struct seq_file *s, uint32_t rpid,
		struct smp2p_interrupt_config *int_cfg)
{
	int failed = 0;

	seq_printf(s, "Running %s\n", __func__);
	do {
		struct smp2p_smem *rhdr;
		struct smp2p_smem *lhdr;
		int negotiation_state;
		bool ssr_ack_enabled;
		uint32_t ssr_done_start;

		lhdr = smp2p_get_out_item(rpid, &negotiation_state);
		UT_ASSERT_PTR(NULL, !=, lhdr);
		UT_ASSERT_INT(SMP2P_EDGE_STATE_OPENED, ==, negotiation_state);

		rhdr = smp2p_get_in_item(rpid);
		UT_ASSERT_PTR(NULL, !=, rhdr);

		/*                                */
		if (SMP2P_GET_FEATURES(rhdr->feature_version)
				& SMP2P_FEATURE_SSR_ACK)
			ssr_ack_enabled = true;
		else
			ssr_ack_enabled = false;

		ssr_done_start = SMP2P_GET_RESTART_DONE(rhdr->flags);
		UT_ASSERT_INT(ssr_done_start, ==,
				SMP2P_GET_RESTART_ACK(lhdr->flags));

		/*                 */
		seq_printf(s, "Restarting '%s'\n", int_cfg->name);
		subsystem_restart(int_cfg->name);
		msleep(10*1000);

		/*                      */
		if (ssr_ack_enabled) {
			ssr_done_start ^= 1;
			UT_ASSERT_INT(ssr_done_start, ==,
					SMP2P_GET_RESTART_ACK(lhdr->flags));
			UT_ASSERT_INT(ssr_done_start, ==,
					SMP2P_GET_RESTART_DONE(rhdr->flags));
			UT_ASSERT_INT(0, ==,
					SMP2P_GET_RESTART_DONE(lhdr->flags));
			seq_puts(s, "\tSSR ACK Enabled and Toggled\n");
		} else {
			UT_ASSERT_INT(0, ==,
					SMP2P_GET_RESTART_DONE(lhdr->flags));
			UT_ASSERT_INT(0, ==,
					SMP2P_GET_RESTART_ACK(lhdr->flags));

			UT_ASSERT_INT(0, ==,
					SMP2P_GET_RESTART_DONE(rhdr->flags));
			UT_ASSERT_INT(0, ==,
					SMP2P_GET_RESTART_ACK(rhdr->flags));
			seq_puts(s, "\tSSR ACK Disabled\n");
		}

		seq_puts(s, "\tOK\n");
	} while (0);