| /* arch/arm/mach-msm/smp2p_test.c |
| * |
| * Copyright (c) 2013, The Linux Foundation. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 and |
| * only version 2 as published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| #include <linux/debugfs.h> |
| #include <linux/ctype.h> |
| #include <linux/jiffies.h> |
| #include <linux/delay.h> |
| #include <linux/completion.h> |
| #include <mach/subsystem_restart.h> |
| #include "smp2p_private.h" |
| #include "smp2p_test_common.h" |
| |
| /** |
| * smp2p_ut_local_basic - Basic sanity test using local loopback. |
| * |
| * @s: pointer to output file |
| * |
| * This test simulates a simple write and read |
| * when remote processor does not exist. |
| */ |
| static void smp2p_ut_local_basic(struct seq_file *s) |
| { |
| int failed = 0; |
| struct msm_smp2p_out *smp2p_obj; |
| struct msm_smp2p_remote_mock *rmp = NULL; |
| 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 and start opening */ |
| 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)); |
| |
| msm_smp2p_set_remote_mock_exists(false); |
| |
| ret = msm_smp2p_out_open(SMP2P_REMOTE_MOCK_PROC, "smp2p", |
| &cb_data.nb, &smp2p_obj); |
| UT_ASSERT_INT(ret, ==, 0); |
| |
| UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); |
| UT_ASSERT_INT(cb_data.cb_count, ==, 0); |
| rmp->rx_interrupt_count = 0; |
| |
| /* simulate response from remote side */ |
| 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.flags = 0x0; |
| msm_smp2p_set_remote_mock_exists(true); |
| rmp->tx_interrupt(); |
| |
| /* verify port was opened */ |
| 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); |
| } |
| } |
| |
| /** |
| * smp2p_ut_local_late_open - Verify post-negotiation opening. |
| * |
| * @s: pointer to output file |
| * |
| * Verify entry creation for opening entries after negotiation is complete. |
| */ |
| static void smp2p_ut_local_late_open(struct seq_file *s) |
| { |
| int failed = 0; |
| struct msm_smp2p_out *smp2p_obj; |
| struct msm_smp2p_remote_mock *rmp = NULL; |
| 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 */ |
| 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.flags = 0x0; |
| |
| msm_smp2p_set_remote_mock_exists(true); |
| |
| ret = msm_smp2p_out_open(SMP2P_REMOTE_MOCK_PROC, "smp2p", |
| &cb_data.nb, &smp2p_obj); |
| UT_ASSERT_INT(ret, ==, 0); |
| |
| /* verify port was opened */ |
| 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); |
| } |
| } |
| |
| /** |
| * 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.flags = 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); |
| } |
| } |
| |
| /** |
| * smp2p_ut_mock_loopback - Exercise the remote loopback using remote mock. |
| * |
| * @s: pointer to output file |
| * |
| * This test exercises the remote loopback code using |
| * remote mock object. The remote mock object simulates the remote |
| * processor sending remote loopback commands to the local processor. |
| */ |
| static void smp2p_ut_mock_loopback(struct seq_file *s) |
| { |
| int failed = 0; |
| struct msm_smp2p_remote_mock *rmp = NULL; |
| int ret; |
| uint32_t test_request = 0; |
| uint32_t test_response = 0; |
| struct msm_smp2p_out *local; |
| |
| seq_printf(s, "Running %s\n", __func__); |
| do { |
| /* Initialize the mock edge */ |
| ret = smp2p_reset_mock_edge(); |
| UT_ASSERT_INT(ret, ==, 0); |
| |
| rmp = msm_smp2p_get_remote_mock(); |
| UT_ASSERT_PTR(rmp, !=, NULL); |
| |
| 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, 1); |
| rmp->remote_item.header.flags = 0x0; |
| msm_smp2p_set_remote_mock_exists(true); |
| |
| /* Create test entry and attach loopback server */ |
| rmp->rx_interrupt_count = 0; |
| INIT_COMPLETION(rmp->cb_completion); |
| strlcpy(rmp->remote_item.entries[0].name, "smp2p", |
| SMP2P_MAX_ENTRY_NAME); |
| rmp->remote_item.entries[0].entry = 0; |
| rmp->tx_interrupt(); |
| |
| local = msm_smp2p_init_rmt_lpb_proc(SMP2P_REMOTE_MOCK_PROC); |
| UT_ASSERT_INT( |
| (int)wait_for_completion_timeout( |
| &rmp->cb_completion, HZ / 2), |
| >, 0); |
| UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 2); |
| |
| /* Send Echo Command */ |
| rmp->rx_interrupt_count = 0; |
| INIT_COMPLETION(rmp->cb_completion); |
| SMP2P_SET_RMT_CMD_TYPE(test_request, 1); |
| SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_ECHO); |
| SMP2P_SET_RMT_DATA(test_request, 10); |
| rmp->remote_item.entries[0].entry = test_request; |
| rmp->tx_interrupt(); |
| UT_ASSERT_INT( |
| (int)wait_for_completion_timeout( |
| &rmp->cb_completion, HZ / 2), |
| >, 0); |
| |
| /* Verify Echo Response */ |
| UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); |
| ret = msm_smp2p_out_read(local, |
| &test_response); |
| UT_ASSERT_INT(ret, ==, 0); |
| test_response = SMP2P_GET_RMT_DATA(test_response); |
| UT_ASSERT_INT(test_response, ==, 10); |
| |
| /* Send PINGPONG command */ |
| test_request = 0; |
| test_response = 0; |
| rmp->rx_interrupt_count = 0; |
| INIT_COMPLETION(rmp->cb_completion); |
| SMP2P_SET_RMT_CMD_TYPE(test_request, 1); |
| SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_PINGPONG); |
| SMP2P_SET_RMT_DATA(test_request, 10); |
| rmp->remote_item.entries[0].entry = test_request; |
| rmp->tx_interrupt(); |
| UT_ASSERT_INT( |
| (int)wait_for_completion_timeout( |
| &rmp->cb_completion, HZ / 2), |
| >, 0); |
| |
| /* Verify PINGPONG Response */ |
| UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); |
| ret = msm_smp2p_out_read(local, &test_response); |
| UT_ASSERT_INT(ret, ==, 0); |
| test_response = SMP2P_GET_RMT_DATA(test_response); |
| UT_ASSERT_INT(test_response, ==, 9); |
| |
| /* Send CLEARALL command */ |
| test_request = 0; |
| test_response = 0; |
| rmp->rx_interrupt_count = 0; |
| INIT_COMPLETION(rmp->cb_completion); |
| SMP2P_SET_RMT_CMD_TYPE(test_request, 1); |
| SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_CLEARALL); |
| SMP2P_SET_RMT_DATA(test_request, 10); |
| rmp->remote_item.entries[0].entry = test_request; |
| rmp->tx_interrupt(); |
| UT_ASSERT_INT( |
| (int)wait_for_completion_timeout( |
| &rmp->cb_completion, HZ / 2), |
| >, 0); |
| |
| /* Verify CLEARALL response */ |
| UT_ASSERT_INT(rmp->rx_interrupt_count, ==, 1); |
| ret = msm_smp2p_out_read(local, &test_response); |
| UT_ASSERT_INT(ret, ==, 0); |
| test_response = SMP2P_GET_RMT_DATA(test_response); |
| UT_ASSERT_INT(test_response, ==, 0); |
| |
| ret = msm_smp2p_deinit_rmt_lpb_proc(SMP2P_REMOTE_MOCK_PROC); |
| UT_ASSERT_INT(ret, ==, 0); |
| seq_printf(s, "\tOK\n"); |
| } while (0); |
| |
| if (failed) { |
| pr_err("%s: Failed\n", __func__); |
| seq_printf(s, "\tFailed\n"); |
| msm_smp2p_deinit_rmt_lpb_proc(SMP2P_REMOTE_MOCK_PROC); |
| } |
| } |
| |
| /** |
| * smp2p_ut_remote_inout_core - Verify inbound/outbound functionality. |
| * |
| * @s: pointer to output file |
| * @remote_pid: Remote processor to test |
| * |
| * This test verifies inbound/outbound functionality for the remote processor. |
| */ |
| static void smp2p_ut_remote_inout_core(struct seq_file *s, int remote_pid) |
| { |
| int failed = 0; |
| struct msm_smp2p_out *handle; |
| int ret; |
| uint32_t test_request; |
| uint32_t test_response = 0; |
| static struct mock_cb_data cb_out; |
| static struct mock_cb_data cb_in; |
| |
| seq_printf(s, "Running %s for '%s' remote pid %d\n", |
| __func__, smp2p_pid_to_name(remote_pid), remote_pid); |
| mock_cb_data_init(&cb_out); |
| mock_cb_data_init(&cb_in); |
| do { |
| /* Open output entry */ |
| ret = msm_smp2p_out_open(remote_pid, "smp2p", |
| &cb_out.nb, &handle); |
| UT_ASSERT_INT(ret, ==, 0); |
| UT_ASSERT_INT( |
| (int)wait_for_completion_timeout( |
| &cb_out.cb_completion, HZ / 2), |
| >, 0); |
| UT_ASSERT_INT(cb_out.cb_count, ==, 1); |
| UT_ASSERT_INT(cb_out.event_open, ==, 1); |
| |
| /* Open inbound entry */ |
| ret = msm_smp2p_in_register(remote_pid, "smp2p", |
| &cb_in.nb); |
| UT_ASSERT_INT(ret, ==, 0); |
| UT_ASSERT_INT( |
| (int)wait_for_completion_timeout( |
| &cb_in.cb_completion, HZ / 2), |
| >, 0); |
| UT_ASSERT_INT(cb_in.cb_count, ==, 1); |
| UT_ASSERT_INT(cb_in.event_open, ==, 1); |
| |
| /* Write an echo request */ |
| mock_cb_data_reset(&cb_out); |
| mock_cb_data_reset(&cb_in); |
| test_request = 0x0; |
| SMP2P_SET_RMT_CMD_TYPE(test_request, 1); |
| SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_ECHO); |
| SMP2P_SET_RMT_DATA(test_request, 0xAA55); |
| ret = msm_smp2p_out_write(handle, test_request); |
| UT_ASSERT_INT(ret, ==, 0); |
| |
| /* Verify inbound reply */ |
| UT_ASSERT_INT( |
| (int)wait_for_completion_timeout( |
| &cb_in.cb_completion, HZ / 2), |
| >, 0); |
| UT_ASSERT_INT(cb_in.cb_count, ==, 1); |
| UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); |
| UT_ASSERT_INT(SMP2P_GET_RMT_DATA( |
| cb_in.entry_data.current_value), ==, 0xAA55); |
| |
| ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response); |
| UT_ASSERT_INT(ret, ==, 0); |
| UT_ASSERT_INT(0, ==, SMP2P_GET_RMT_CMD_TYPE(test_response)); |
| UT_ASSERT_INT(SMP2P_LB_CMD_ECHO, ==, |
| SMP2P_GET_RMT_CMD(test_response)); |
| UT_ASSERT_INT(0xAA55, ==, SMP2P_GET_RMT_DATA(test_response)); |
| |
| /* Write a clear all request */ |
| mock_cb_data_reset(&cb_in); |
| test_request = 0x0; |
| SMP2P_SET_RMT_CMD_TYPE(test_request, 1); |
| SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_CLEARALL); |
| SMP2P_SET_RMT_DATA(test_request, 0xAA55); |
| ret = msm_smp2p_out_write(handle, test_request); |
| UT_ASSERT_INT(ret, ==, 0); |
| |
| /* Verify inbound reply */ |
| UT_ASSERT_INT( |
| (int)wait_for_completion_timeout( |
| &cb_in.cb_completion, HZ / 2), |
| >, 0); |
| UT_ASSERT_INT(cb_in.cb_count, ==, 1); |
| UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); |
| UT_ASSERT_INT(SMP2P_GET_RMT_DATA( |
| cb_in.entry_data.current_value), ==, 0x0000); |
| |
| ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response); |
| UT_ASSERT_INT(ret, ==, 0); |
| UT_ASSERT_INT(0, ==, SMP2P_GET_RMT_CMD_TYPE(test_response)); |
| UT_ASSERT_INT(0x0000, ==, SMP2P_GET_RMT_DATA(test_response)); |
| |
| /* Write a decrement request */ |
| mock_cb_data_reset(&cb_in); |
| test_request = 0x0; |
| SMP2P_SET_RMT_CMD_TYPE(test_request, 1); |
| SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_PINGPONG); |
| SMP2P_SET_RMT_DATA(test_request, 0xAA55); |
| ret = msm_smp2p_out_write(handle, test_request); |
| UT_ASSERT_INT(ret, ==, 0); |
| |
| /* Verify inbound reply */ |
| UT_ASSERT_INT( |
| (int)wait_for_completion_timeout( |
| &cb_in.cb_completion, HZ / 2), |
| >, 0); |
| UT_ASSERT_INT(cb_in.cb_count, ==, 1); |
| UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); |
| UT_ASSERT_INT(SMP2P_GET_RMT_DATA( |
| cb_in.entry_data.current_value), ==, 0xAA54); |
| |
| ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response); |
| UT_ASSERT_INT(ret, ==, 0); |
| UT_ASSERT_INT(0, ==, SMP2P_GET_RMT_CMD_TYPE(test_response)); |
| UT_ASSERT_INT(SMP2P_LB_CMD_PINGPONG, ==, |
| SMP2P_GET_RMT_CMD(test_response)); |
| UT_ASSERT_INT(0xAA54, ==, SMP2P_GET_RMT_DATA(test_response)); |
| |
| /* Test the ignore flag */ |
| mock_cb_data_reset(&cb_in); |
| test_request = 0x0; |
| SMP2P_SET_RMT_CMD_TYPE(test_request, 1); |
| SMP2P_SET_RMT_CMD(test_request, SMP2P_RLPB_IGNORE); |
| SMP2P_SET_RMT_DATA(test_request, 0xAA55); |
| ret = msm_smp2p_out_write(handle, test_request); |
| UT_ASSERT_INT(ret, ==, 0); |
| |
| UT_ASSERT_INT( |
| (int)wait_for_completion_timeout( |
| &cb_in.cb_completion, HZ / 2), |
| ==, 0); |
| UT_ASSERT_INT(cb_in.cb_count, ==, 0); |
| UT_ASSERT_INT(cb_in.event_entry_update, ==, 0); |
| ret = msm_smp2p_in_read(remote_pid, "smp2p", &test_response); |
| UT_ASSERT_INT(ret, ==, 0); |
| UT_ASSERT_INT(0xAA54, ==, SMP2P_GET_RMT_DATA(test_response)); |
| |
| /* Cleanup */ |
| ret = msm_smp2p_out_close(&handle); |
| UT_ASSERT_INT(ret, ==, 0); |
| UT_ASSERT_PTR(handle, ==, 0); |
| ret = msm_smp2p_in_unregister(remote_pid, "smp2p", &cb_in.nb); |
| UT_ASSERT_INT(ret, ==, 0); |
| |
| seq_printf(s, "\tOK\n"); |
| } while (0); |
| |
| if (failed) { |
| if (handle) |
| (void)msm_smp2p_out_close(&handle); |
| (void)msm_smp2p_in_unregister(remote_pid, "smp2p", &cb_in.nb); |
| |
| pr_err("%s: Failed\n", __func__); |
| seq_printf(s, "\tFailed\n"); |
| } |
| } |
| |
| /** |
| * smp2p_ut_remote_inout - Verify inbound/outbound functionality for all. |
| * |
| * @s: pointer to output file |
| * |
| * This test verifies inbound and outbound functionality for all |
| * configured remote processor. |
| */ |
| static void smp2p_ut_remote_inout(struct seq_file *s) |
| { |
| struct smp2p_interrupt_config *int_cfg; |
| int pid; |
| |
| int_cfg = smp2p_get_interrupt_config(); |
| if (!int_cfg) { |
| seq_printf(s, |
| "Remote processor config unavailable\n"); |
| return; |
| } |
| |
| for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) { |
| if (!int_cfg[pid].is_configured) |
| continue; |
| |
| msm_smp2p_deinit_rmt_lpb_proc(pid); |
| smp2p_ut_remote_inout_core(s, pid); |
| msm_smp2p_init_rmt_lpb_proc(pid); |
| } |
| } |
| |
| /** |
| * smp2p_ut_remote_out_max_entries_core - Verify open functionality. |
| * |
| * @s: pointer to output file |
| * @remote_pid: Remote processor for which the test is executed. |
| * |
| * This test verifies open functionality by creating maximum outbound entries. |
| */ |
| static void smp2p_ut_remote_out_max_entries_core(struct seq_file *s, |
| int remote_pid) |
| { |
| int j = 0; |
| int failed = 0; |
| struct msm_smp2p_out *handle[SMP2P_MAX_ENTRY]; |
| int ret; |
| static struct mock_cb_data cb_out[SMP2P_MAX_ENTRY]; |
| char entry_name[SMP2P_MAX_ENTRY_NAME]; |
| int num_created; |
| |
| seq_printf(s, "Running %s for '%s' remote pid %d\n", |
| __func__, smp2p_pid_to_name(remote_pid), remote_pid); |
| |
| for (j = 0; j < SMP2P_MAX_ENTRY; j++) { |
| handle[j] = NULL; |
| mock_cb_data_init(&cb_out[j]); |
| } |
| |
| do { |
| num_created = 0; |
| for (j = 0; j < SMP2P_MAX_ENTRY; j++) { |
| /* Open as many output entries as possible */ |
| scnprintf((char *)entry_name, SMP2P_MAX_ENTRY_NAME, |
| "smp2p%d", j); |
| ret = msm_smp2p_out_open(remote_pid, entry_name, |
| &cb_out[j].nb, &handle[j]); |
| if (ret == -ENOMEM) |
| /* hit max number */ |
| break; |
| UT_ASSERT_INT(ret, ==, 0); |
| ++num_created; |
| } |
| if (failed) |
| break; |
| |
| /* verify we created more than 1 entry */ |
| UT_ASSERT_INT(num_created, <=, SMP2P_MAX_ENTRY); |
| UT_ASSERT_INT(num_created, >, 0); |
| |
| seq_printf(s, "\tOK\n"); |
| } while (0); |
| |
| if (failed) { |
| pr_err("%s: Failed\n", __func__); |
| seq_printf(s, "\tFailed\n"); |
| } |
| |
| /* cleanup */ |
| for (j = 0; j < SMP2P_MAX_ENTRY; j++) |
| ret = msm_smp2p_out_close(&handle[j]); |
| } |
| |
| /** |
| * smp2p_ut_remote_out_max_entries - Verify open for all configured processors. |
| * |
| * @s: pointer to output file |
| * |
| * This test verifies creating max number of entries for |
| * all configured remote processor. |
| */ |
| static void smp2p_ut_remote_out_max_entries(struct seq_file *s) |
| { |
| struct smp2p_interrupt_config *int_cfg; |
| int pid; |
| |
| int_cfg = smp2p_get_interrupt_config(); |
| if (!int_cfg) { |
| seq_printf(s, |
| "Remote processor config unavailable\n"); |
| return; |
| } |
| |
| for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) { |
| if (!int_cfg[pid].is_configured) |
| continue; |
| |
| smp2p_ut_remote_out_max_entries_core(s, pid); |
| } |
| } |
| |
| /** |
| * smp2p_ut_local_in_max_entries - Verify registering and unregistering. |
| * |
| * @s: pointer to output file |
| * |
| * This test verifies registering and unregistering for inbound entries using |
| * the remote mock processor. |
| */ |
| static void smp2p_ut_local_in_max_entries(struct seq_file *s) |
| { |
| int j = 0; |
| int failed = 0; |
| struct msm_smp2p_remote_mock *rmp = NULL; |
| int ret; |
| static struct mock_cb_data cb_in[SMP2P_MAX_ENTRY]; |
| static struct mock_cb_data cb_out; |
| |
| seq_printf(s, "Running %s\n", __func__); |
| |
| for (j = 0; j < SMP2P_MAX_ENTRY; j++) |
| mock_cb_data_init(&cb_in[j]); |
| |
| mock_cb_data_init(&cb_out); |
| |
| do { |
| /* Initialize mock edge */ |
| 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.flags = 0x0; |
| msm_smp2p_set_remote_mock_exists(true); |
| |
| /* Create Max Entries in the remote mock object */ |
| for (j = 0; j < SMP2P_MAX_ENTRY; j++) { |
| scnprintf(rmp->remote_item.entries[j].name, |
| SMP2P_MAX_ENTRY_NAME, "smp2p%d", j); |
| rmp->remote_item.entries[j].entry = 0; |
| rmp->tx_interrupt(); |
| } |
| |
| /* Register for in entries */ |
| for (j = 0; j < SMP2P_MAX_ENTRY; j++) { |
| ret = msm_smp2p_in_register(SMP2P_REMOTE_MOCK_PROC, |
| rmp->remote_item.entries[j].name, |
| &(cb_in[j].nb)); |
| UT_ASSERT_INT(ret, ==, 0); |
| UT_ASSERT_INT( |
| (int)wait_for_completion_timeout( |
| &(cb_in[j].cb_completion), HZ / 2), |
| >, 0); |
| UT_ASSERT_INT(cb_in[j].cb_count, ==, 1); |
| UT_ASSERT_INT(cb_in[j].event_entry_update, ==, 0); |
| } |
| UT_ASSERT_INT(j, ==, SMP2P_MAX_ENTRY); |
| |
| /* Unregister */ |
| for (j = 0; j < SMP2P_MAX_ENTRY; j++) { |
| ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, |
| rmp->remote_item.entries[j].name, |
| &(cb_in[j].nb)); |
| UT_ASSERT_INT(ret, ==, 0); |
| } |
| UT_ASSERT_INT(j, ==, SMP2P_MAX_ENTRY); |
| |
| seq_printf(s, "\tOK\n"); |
| } while (0); |
| |
| if (failed) { |
| pr_err("%s: Failed\n", __func__); |
| seq_printf(s, "\tFailed\n"); |
| |
| for (j = 0; j < SMP2P_MAX_ENTRY; j++) |
| ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, |
| rmp->remote_item.entries[j].name, |
| &(cb_in[j].nb)); |
| } |
| } |
| |
| /** |
| * smp2p_ut_local_in_multiple - Verify Multiple Inbound Registration. |
| * |
| * @s: pointer to output file |
| * |
| * This test verifies multiple clients registering for same inbound entries |
| * using the remote mock processor. |
| */ |
| static void smp2p_ut_local_in_multiple(struct seq_file *s) |
| { |
| int failed = 0; |
| struct msm_smp2p_remote_mock *rmp = NULL; |
| int ret; |
| static struct mock_cb_data cb_in_1; |
| static struct mock_cb_data cb_in_2; |
| static struct mock_cb_data cb_out; |
| |
| seq_printf(s, "Running %s\n", __func__); |
| |
| mock_cb_data_init(&cb_in_1); |
| mock_cb_data_init(&cb_in_2); |
| mock_cb_data_init(&cb_out); |
| |
| do { |
| /* Initialize mock edge */ |
| 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, 1); |
| SMP2P_SET_ENT_VALID( |
| rmp->remote_item.header.valid_total_ent, 0); |
| rmp->remote_item.header.flags = 0x0; |
| msm_smp2p_set_remote_mock_exists(true); |
| |
| /* Create an Entry in the remote mock object */ |
| scnprintf(rmp->remote_item.entries[0].name, |
| SMP2P_MAX_ENTRY_NAME, "smp2p%d", 1); |
| rmp->remote_item.entries[0].entry = 0; |
| rmp->tx_interrupt(); |
| |
| /* Register multiple clients for the inbound entry */ |
| ret = msm_smp2p_in_register(SMP2P_REMOTE_MOCK_PROC, |
| rmp->remote_item.entries[0].name, |
| &cb_in_1.nb); |
| UT_ASSERT_INT(ret, ==, 0); |
| UT_ASSERT_INT( |
| (int)wait_for_completion_timeout( |
| &(cb_in_1.cb_completion), HZ / 2), |
| >, 0); |
| UT_ASSERT_INT(cb_in_1.cb_count, ==, 1); |
| UT_ASSERT_INT(cb_in_1.event_entry_update, ==, 0); |
| |
| ret = msm_smp2p_in_register(SMP2P_REMOTE_MOCK_PROC, |
| rmp->remote_item.entries[0].name, |
| &cb_in_2.nb); |
| UT_ASSERT_INT(ret, ==, 0); |
| UT_ASSERT_INT( |
| (int)wait_for_completion_timeout( |
| &(cb_in_2.cb_completion), HZ / 2), |
| >, 0); |
| UT_ASSERT_INT(cb_in_2.cb_count, ==, 1); |
| UT_ASSERT_INT(cb_in_2.event_entry_update, ==, 0); |
| |
| |
| /* Unregister the clients */ |
| ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, |
| rmp->remote_item.entries[0].name, |
| &(cb_in_1.nb)); |
| UT_ASSERT_INT(ret, ==, 0); |
| |
| ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, |
| rmp->remote_item.entries[0].name, |
| &(cb_in_2.nb)); |
| UT_ASSERT_INT(ret, ==, 0); |
| |
| seq_printf(s, "\tOK\n"); |
| } while (0); |
| |
| if (failed) { |
| pr_err("%s: Failed\n", __func__); |
| seq_printf(s, "\tFailed\n"); |
| |
| ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, |
| rmp->remote_item.entries[0].name, |
| &(cb_in_1.nb)); |
| |
| ret = msm_smp2p_in_unregister(SMP2P_REMOTE_MOCK_PROC, |
| rmp->remote_item.entries[0].name, |
| &(cb_in_2.nb)); |
| } |
| } |
| |
| /** |
| * smp2p_ut_local_ssr_ack - Verify SSR Done/ACK Feature |
| * |
| * @s: pointer to output file |
| */ |
| 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; |
| |
| /* initialize v1 without SMP2P_FEATURE_SSR_ACK enabled */ |
| 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(); |
| |
| /* verify edge is open */ |
| 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); |
| |
| /* verify no response to ack feature */ |
| 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); |
| |
| /* initialize v1 with SMP2P_FEATURE_SSR_ACK enabled */ |
| 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(); |
| |
| /* verify edge is open */ |
| 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); |
| |
| /* verify response to ack feature */ |
| 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_ssr_ack - Verify SSR Done/ACK Feature |
| * |
| * @s: pointer to output file |
| * @rpid: Remote processor ID |
| * @int_cfg: Interrupt config |
| */ |
| 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); |
| |
| /* get initial state of SSR flags */ |
| 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)); |
| |
| /* trigger restart */ |
| seq_printf(s, "Restarting '%s'\n", int_cfg->name); |
| subsystem_restart(int_cfg->name); |
| msleep(10*1000); |
| |
| /* verify ack signaling */ |
| 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); |
| |
| if (failed) { |
| pr_err("%s: Failed\n", __func__); |
| seq_puts(s, "\tFailed\n"); |
| } |
| } |
| |
| /** |
| * smp2p_ut_remote_ssr_ack - Verify SSR Done/ACK Feature |
| * |
| * @s: pointer to output file |
| * |
| * Triggers SSR for each subsystem. |
| */ |
| static void smp2p_ut_remote_ssr_ack(struct seq_file *s) |
| { |
| struct smp2p_interrupt_config *int_cfg; |
| int pid; |
| |
| int_cfg = smp2p_get_interrupt_config(); |
| if (!int_cfg) { |
| seq_puts(s, |
| "Remote processor config unavailable\n"); |
| return; |
| } |
| |
| for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) { |
| if (!int_cfg[pid].is_configured) |
| continue; |
| |
| msm_smp2p_deinit_rmt_lpb_proc(pid); |
| smp2p_ut_remotesubsys_ssr_ack(s, pid, &int_cfg[pid]); |
| msm_smp2p_init_rmt_lpb_proc(pid); |
| } |
| } |
| |
| static struct dentry *dent; |
| |
| static int debugfs_show(struct seq_file *s, void *data) |
| { |
| void (*show)(struct seq_file *) = s->private; |
| |
| show(s); |
| |
| return 0; |
| } |
| |
| static int debug_open(struct inode *inode, struct file *file) |
| { |
| return single_open(file, debugfs_show, inode->i_private); |
| } |
| |
| static const struct file_operations debug_ops = { |
| .open = debug_open, |
| .release = single_release, |
| .read = seq_read, |
| .llseek = seq_lseek, |
| }; |
| |
| void smp2p_debug_create(const char *name, |
| void (*show)(struct seq_file *)) |
| { |
| struct dentry *file; |
| |
| file = debugfs_create_file(name, 0444, dent, show, &debug_ops); |
| if (!file) |
| pr_err("%s: unable to create file '%s'\n", __func__, name); |
| } |
| |
| static int __init smp2p_debugfs_init(void) |
| { |
| dent = debugfs_create_dir("smp2p_test", 0); |
| if (IS_ERR(dent)) |
| return PTR_ERR(dent); |
| |
| /* |
| * Add Unit Test entries. |
| * |
| * The idea with unit tests is that you can run all of them |
| * from ADB shell by doing: |
| * adb shell |
| * cat ut* |
| * |
| * And if particular tests fail, you can then repeatedly run the |
| * failing tests as you debug and resolve the failing test. |
| */ |
| smp2p_debug_create("ut_local_basic", |
| smp2p_ut_local_basic); |
| smp2p_debug_create("ut_local_late_open", |
| smp2p_ut_local_late_open); |
| smp2p_debug_create("ut_local_early_open", |
| smp2p_ut_local_early_open); |
| smp2p_debug_create("ut_mock_loopback", |
| smp2p_ut_mock_loopback); |
| smp2p_debug_create("ut_remote_inout", |
| smp2p_ut_remote_inout); |
| smp2p_debug_create("ut_local_in_max_entries", |
| smp2p_ut_local_in_max_entries); |
| smp2p_debug_create("ut_remote_out_max_entries", |
| smp2p_ut_remote_out_max_entries); |
| smp2p_debug_create("ut_local_in_multiple", |
| smp2p_ut_local_in_multiple); |
| smp2p_debug_create("ut_local_ssr_ack", |
| smp2p_ut_local_ssr_ack); |
| smp2p_debug_create("ut_remote_ssr_ack", |
| smp2p_ut_remote_ssr_ack); |
| |
| return 0; |
| } |
| module_init(smp2p_debugfs_init); |