diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index ac55dd34cfcb..7f2acfabf86d 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -121,4 +121,3 @@ obj-$(CONFIG_GPIO_ZEVIO) += gpio-zevio.o obj-$(CONFIG_GPIO_ZYNQ) += gpio-zynq.o obj-$(CONFIG_GPIO_ZX) += gpio-zx.o obj-$(CONFIG_MSM_SMP2P) += gpio-msm-smp2p.o -obj-$(CONFIG_MSM_SMP2P_TEST) += gpio-msm-smp2p-test.o diff --git a/drivers/gpio/gpio-msm-smp2p-test.c b/drivers/gpio/gpio-msm-smp2p-test.c deleted file mode 100644 index 5907513b43c0..000000000000 --- a/drivers/gpio/gpio-msm-smp2p-test.c +++ /dev/null @@ -1,762 +0,0 @@ -/* drivers/gpio/gpio-msm-smp2p-test.c - * - * Copyright (c) 2013-2016, 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include "../soc/qcom/smp2p_private.h" -#include "../soc/qcom/smp2p_test_common.h" - -/* Interrupt callback data */ -struct gpio_info { - int gpio_base_id; - int irq_base_id; - - bool initialized; - struct completion cb_completion; - int cb_count; - DECLARE_BITMAP(triggered_irqs, SMP2P_BITS_PER_ENTRY); -}; - -/* GPIO Inbound/Outbound callback info */ -struct gpio_inout { - struct gpio_info in; - struct gpio_info out; -}; - -static struct gpio_inout gpio_info[SMP2P_NUM_PROCS]; - -/** - * Init/reset the callback data. - * - * @info: Pointer to callback data - */ -static void cb_data_reset(struct gpio_info *info) -{ - int n; - - if (!info) - return; - - if (!info->initialized) { - init_completion(&info->cb_completion); - info->initialized = true; - } - info->cb_count = 0; - - for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) - clear_bit(n, info->triggered_irqs); - - reinit_completion(&info->cb_completion); -} - -static int smp2p_gpio_test_probe(struct platform_device *pdev) -{ - int id; - int cnt; - struct device_node *node = pdev->dev.of_node; - struct gpio_info *gpio_info_ptr = NULL; - - /* - * NOTE: This does a string-lookup of the GPIO pin name and doesn't - * actually directly link to the SMP2P GPIO driver since all - * GPIO/Interrupt access must be through standard - * Linux GPIO / Interrupt APIs. - */ - if (strcmp("qcom,smp2pgpio_test_smp2p_1_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_MODEM_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_1_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_MODEM_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_2_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_AUDIO_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_2_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_AUDIO_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_3_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_SENSOR_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_3_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_SENSOR_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_4_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_4_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_WIRELESS_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_5_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_CDSP_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_TZ_PROC].in; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_7_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_TZ_PROC].out; - } else if (strcmp("qcom,smp2pgpio_test_smp2p_15_in", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in; - } else if ( - strcmp("qcom,smp2pgpio_test_smp2p_15_out", node->name) == 0) { - gpio_info_ptr = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out; - } else { - pr_err("%s: unable to match device type '%s'\n", - __func__, node->name); - return -ENODEV; - } - - /* retrieve the GPIO and interrupt ID's */ - cnt = of_gpio_count(node); - if (cnt && gpio_info_ptr) { - /* - * Instead of looping through all 32-bits, we can just get the - * first pin to get the base IDs. This saves on the verbosity - * of the device tree nodes as well. - */ - id = of_get_gpio(node, 0); - if (id == -EPROBE_DEFER) - return id; - gpio_info_ptr->gpio_base_id = id; - gpio_info_ptr->irq_base_id = gpio_to_irq(id); - } - return 0; -} - -/* - * NOTE: Instead of match table and device driver, you may be able to just - * call of_find_compatible_node() in your init function. - */ -static struct of_device_id msm_smp2p_match_table[] = { - /* modem */ - {.compatible = "qcom,smp2pgpio_test_smp2p_1_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_1_in", }, - - /* audio (adsp) */ - {.compatible = "qcom,smp2pgpio_test_smp2p_2_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_2_in", }, - - /* sensor */ - {.compatible = "qcom,smp2pgpio_test_smp2p_3_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_3_in", }, - - /* wcnss */ - {.compatible = "qcom,smp2pgpio_test_smp2p_4_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_4_in", }, - - /* CDSP */ - {.compatible = "qcom,smp2pgpio_test_smp2p_5_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_5_in", }, - - /* TZ */ - {.compatible = "qcom,smp2pgpio_test_smp2p_7_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_7_in", }, - - /* mock loopback */ - {.compatible = "qcom,smp2pgpio_test_smp2p_15_out", }, - {.compatible = "qcom,smp2pgpio_test_smp2p_15_in", }, - {}, -}; - -static struct platform_driver smp2p_gpio_driver = { - .probe = smp2p_gpio_test_probe, - .driver = { - .name = "smp2pgpio_test", - .owner = THIS_MODULE, - .of_match_table = msm_smp2p_match_table, - }, -}; - -/** - * smp2p_ut_local_gpio_out - Verify outbound functionality. - * - * @s: pointer to output file - */ -static void smp2p_ut_local_gpio_out(struct seq_file *s) -{ - int failed = 0; - struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].out; - int ret; - int id; - struct msm_smp2p_remote_mock *mock; - - seq_printf(s, "Running %s\n", __func__); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - mock = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(mock, !=, NULL); - - mock->rx_interrupt_count = 0; - memset(&mock->remote_item, 0, - sizeof(struct smp2p_smem_item)); - smp2p_init_header((struct smp2p_smem *)&mock->remote_item, - SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC, - 0, 1); - strlcpy(mock->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - SMP2P_SET_ENT_VALID( - mock->remote_item.header.valid_total_ent, 1); - msm_smp2p_set_remote_mock_exists(true); - mock->tx_interrupt(); - - /* open GPIO entry */ - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, true); - - /* verify set/get functions */ - UT_ASSERT_INT(0, <, cb_info->gpio_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - int pin = cb_info->gpio_base_id + id; - - mock->rx_interrupt_count = 0; - gpio_set_value(pin, 1); - UT_ASSERT_INT(1, ==, mock->rx_interrupt_count); - UT_ASSERT_INT(1, ==, gpio_get_value(pin)); - - gpio_set_value(pin, 0); - UT_ASSERT_INT(2, ==, mock->rx_interrupt_count); - UT_ASSERT_INT(0, ==, gpio_get_value(pin)); - } - if (failed) - break; - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, false); -} - -/** - * smp2p_gpio_irq - Interrupt handler for inbound entries. - * - * @irq: Virtual IRQ being triggered - * @data: Cookie data (struct gpio_info * in this case) - * @returns: Number of bytes written - */ -static irqreturn_t smp2p_gpio_irq(int irq, void *data) -{ - struct gpio_info *gpio_ptr = (struct gpio_info *)data; - int offset; - - if (!gpio_ptr) { - pr_err("%s: gpio_ptr is NULL for irq %d\n", __func__, irq); - return IRQ_HANDLED; - } - - offset = irq - gpio_ptr->irq_base_id; - if (offset >= 0 && offset < SMP2P_BITS_PER_ENTRY) - set_bit(offset, gpio_ptr->triggered_irqs); - else - pr_err("%s: invalid irq offset base %d; irq %d\n", - __func__, gpio_ptr->irq_base_id, irq); - - ++gpio_ptr->cb_count; - complete(&gpio_ptr->cb_completion); - return IRQ_HANDLED; -} - -/** - * smp2p_ut_local_gpio_in - Verify inbound functionality. - * - * @s: pointer to output file - */ -static void smp2p_ut_local_gpio_in(struct seq_file *s) -{ - int failed = 0; - struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in; - int id; - int ret; - int virq; - struct msm_smp2p_remote_mock *mock; - - seq_printf(s, "Running %s\n", __func__); - - cb_data_reset(cb_info); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - mock = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(mock, !=, NULL); - - mock->rx_interrupt_count = 0; - memset(&mock->remote_item, 0, - sizeof(struct smp2p_smem_item)); - smp2p_init_header((struct smp2p_smem *)&mock->remote_item, - SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC, - 0, 1); - strlcpy(mock->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - SMP2P_SET_ENT_VALID( - mock->remote_item.header.valid_total_ent, 1); - msm_smp2p_set_remote_mock_exists(true); - mock->tx_interrupt(); - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, true); - - /* verify set/get functions locally */ - UT_ASSERT_INT(0, <, cb_info->gpio_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - int pin; - int current_value; - - /* verify pin value cannot be set */ - pin = cb_info->gpio_base_id + id; - current_value = gpio_get_value(pin); - - gpio_set_value(pin, 0); - UT_ASSERT_INT(current_value, ==, gpio_get_value(pin)); - gpio_set_value(pin, 1); - UT_ASSERT_INT(current_value, ==, gpio_get_value(pin)); - - /* verify no interrupts */ - UT_ASSERT_INT(0, ==, cb_info->cb_count); - } - if (failed) - break; - - /* register for interrupts */ - UT_ASSERT_INT(0, <, cb_info->irq_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq)); - ret = request_irq(virq, - smp2p_gpio_irq, IRQF_TRIGGER_RISING, - "smp2p_test", cb_info); - UT_ASSERT_INT(0, ==, ret); - } - if (failed) - break; - - /* verify both rising and falling edge interrupts */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - irq_set_irq_type(virq, IRQ_TYPE_EDGE_BOTH); - cb_data_reset(cb_info); - - /* verify rising-edge interrupt */ - mock->remote_item.entries[0].entry = 1 << id; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - test_bit(id, cb_info->triggered_irqs); - - /* verify falling-edge interrupt */ - mock->remote_item.entries[0].entry = 0; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 2); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - } - if (failed) - break; - - /* verify rising-edge interrupts */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING); - cb_data_reset(cb_info); - - /* verify only rising-edge interrupt is triggered */ - mock->remote_item.entries[0].entry = 1 << id; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - test_bit(id, cb_info->triggered_irqs); - - mock->remote_item.entries[0].entry = 0; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - } - if (failed) - break; - - /* verify falling-edge interrupts */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - irq_set_irq_type(virq, IRQ_TYPE_EDGE_FALLING); - cb_data_reset(cb_info); - - /* verify only rising-edge interrupt is triggered */ - mock->remote_item.entries[0].entry = 1 << id; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 0); - UT_ASSERT_INT(0, ==, - test_bit(id, cb_info->triggered_irqs)); - - mock->remote_item.entries[0].entry = 0; - mock->tx_interrupt(); - UT_ASSERT_INT(cb_info->cb_count, ==, 1); - UT_ASSERT_INT(0, <, - test_bit(id, cb_info->triggered_irqs)); - } - if (failed) - break; - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - /* unregister for interrupts */ - if (cb_info->irq_base_id) { - for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id) - free_irq(cb_info->irq_base_id + id, cb_info); - } - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, false); -} - -/** - * smp2p_ut_local_gpio_in_update_open - Verify combined open/update. - * - * @s: pointer to output file - * - * If the remote side updates the SMP2P bits and sends before negotiation is - * complete, then the UPDATE event will have to be delayed until negotiation is - * complete. This should result in both the OPEN and UPDATE events coming in - * right after each other and the behavior should be transparent to the clients - * of SMP2P GPIO. - */ -static void smp2p_ut_local_gpio_in_update_open(struct seq_file *s) -{ - int failed = 0; - struct gpio_info *cb_info = &gpio_info[SMP2P_REMOTE_MOCK_PROC].in; - int id; - int ret; - int virq; - struct msm_smp2p_remote_mock *mock; - - seq_printf(s, "Running %s\n", __func__); - - cb_data_reset(cb_info); - do { - /* initialize mock edge */ - ret = smp2p_reset_mock_edge(); - UT_ASSERT_INT(ret, ==, 0); - - mock = msm_smp2p_get_remote_mock(); - UT_ASSERT_PTR(mock, !=, NULL); - - mock->rx_interrupt_count = 0; - memset(&mock->remote_item, 0, - sizeof(struct smp2p_smem_item)); - smp2p_init_header((struct smp2p_smem *)&mock->remote_item, - SMP2P_REMOTE_MOCK_PROC, SMP2P_APPS_PROC, - 0, 1); - strlcpy(mock->remote_item.entries[0].name, "smp2p", - SMP2P_MAX_ENTRY_NAME); - SMP2P_SET_ENT_VALID( - mock->remote_item.header.valid_total_ent, 1); - - /* register for interrupts */ - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, true); - - UT_ASSERT_INT(0, <, cb_info->irq_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq)); - ret = request_irq(virq, - smp2p_gpio_irq, IRQ_TYPE_EDGE_BOTH, - "smp2p_test", cb_info); - UT_ASSERT_INT(0, ==, ret); - } - if (failed) - break; - - /* update the state value and complete negotiation */ - mock->remote_item.entries[0].entry = 0xDEADDEAD; - msm_smp2p_set_remote_mock_exists(true); - mock->tx_interrupt(); - - /* verify delayed state updates were processed */ - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - virq = cb_info->irq_base_id + id; - - UT_ASSERT_INT(cb_info->cb_count, >, 0); - if (0x1 & (0xDEADDEAD >> id)) { - /* rising edge should have been triggered */ - if (!test_bit(id, cb_info->triggered_irqs)) { - seq_printf(s, "%s:%d bit %d clear, ", - __func__, __LINE__, id); - seq_puts(s, "expected set\n"); - failed = 1; - break; - } - } else { - /* edge should not have been triggered */ - if (test_bit(id, cb_info->triggered_irqs)) { - seq_printf(s, "%s:%d bit %d set, ", - __func__, __LINE__, id); - seq_puts(s, "expected clear\n"); - failed = 1; - break; - } - } - } - if (failed) - break; - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } - - /* unregister for interrupts */ - if (cb_info->irq_base_id) { - for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id) - free_irq(cb_info->irq_base_id + id, cb_info); - } - - smp2p_gpio_open_test_entry("smp2p", - SMP2P_REMOTE_MOCK_PROC, false); -} - -/** - * smp2p_gpio_write_bits - writes value to each GPIO pin specified in mask. - * - * @gpio: gpio test structure - * @mask: 1 = write gpio_value to this GPIO pin - * @gpio_value: value to write to GPIO pin - */ -static void smp2p_gpio_write_bits(struct gpio_info *gpio, uint32_t mask, - int gpio_value) -{ - int n; - - for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) { - if (mask & 0x1) - gpio_set_value(gpio->gpio_base_id + n, gpio_value); - mask >>= 1; - } -} - -static void smp2p_gpio_set_bits(struct gpio_info *gpio, uint32_t mask) -{ - smp2p_gpio_write_bits(gpio, mask, 1); -} - -static void smp2p_gpio_clr_bits(struct gpio_info *gpio, uint32_t mask) -{ - smp2p_gpio_write_bits(gpio, mask, 0); -} - -/** - * smp2p_gpio_get_value - reads entire 32-bits of GPIO - * - * @gpio: gpio structure - * @returns: 32 bit value of GPIO pins - */ -static uint32_t smp2p_gpio_get_value(struct gpio_info *gpio) -{ - int n; - uint32_t value = 0; - - for (n = 0; n < SMP2P_BITS_PER_ENTRY; ++n) { - if (gpio_get_value(gpio->gpio_base_id + n)) - value |= 1 << n; - } - return value; -} - -/** - * smp2p_ut_remote_inout_core - Verify inbound/outbound functionality. - * - * @s: pointer to output file - * @remote_pid: Remote processor to test - * @name: Name of the test for reporting - * - * This test verifies inbound/outbound functionality for the remote processor. - */ -static void smp2p_ut_remote_inout_core(struct seq_file *s, int remote_pid, - const char *name) -{ - int failed = 0; - uint32_t request; - uint32_t response; - struct gpio_info *cb_in; - struct gpio_info *cb_out; - int id; - int ret; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - - cb_in = &gpio_info[remote_pid].in; - cb_out = &gpio_info[remote_pid].out; - cb_data_reset(cb_in); - cb_data_reset(cb_out); - do { - /* open test entries */ - msm_smp2p_deinit_rmt_lpb_proc(remote_pid); - smp2p_gpio_open_test_entry("smp2p", remote_pid, true); - - /* register for interrupts */ - UT_ASSERT_INT(0, <, cb_in->gpio_base_id); - UT_ASSERT_INT(0, <, cb_in->irq_base_id); - for (id = 0; id < SMP2P_BITS_PER_ENTRY && !failed; ++id) { - int virq = cb_in->irq_base_id + id; - UT_ASSERT_PTR(NULL, !=, irq_to_desc(virq)); - ret = request_irq(virq, - smp2p_gpio_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "smp2p_test", cb_in); - UT_ASSERT_INT(0, ==, ret); - } - if (failed) - break; - - /* write echo of data value 0 */ - UT_ASSERT_INT(0, <, cb_out->gpio_base_id); - request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(request, 1); - SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO); - SMP2P_SET_RMT_DATA(request, 0x0); - - smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK); - smp2p_gpio_set_bits(cb_out, request); - - UT_ASSERT_INT(cb_in->cb_count, ==, 0); - smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - - /* verify response */ - do { - /* wait for up to 32 changes */ - if (wait_for_completion_timeout( - &cb_in->cb_completion, HZ / 2) == 0) - break; - reinit_completion(&cb_in->cb_completion); - } while (cb_in->cb_count < 32); - UT_ASSERT_INT(cb_in->cb_count, >, 0); - response = smp2p_gpio_get_value(cb_in); - SMP2P_SET_RMT_CMD_TYPE(request, 0); - UT_ASSERT_HEX(request, ==, response); - - /* write echo of data value of all 1's */ - request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(request, 1); - SMP2P_SET_RMT_CMD(request, SMP2P_LB_CMD_ECHO); - SMP2P_SET_RMT_DATA(request, ~0); - - smp2p_gpio_set_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - cb_data_reset(cb_in); - smp2p_gpio_clr_bits(cb_out, ~SMP2P_RMT_IGNORE_MASK); - smp2p_gpio_set_bits(cb_out, request); - - UT_ASSERT_INT(cb_in->cb_count, ==, 0); - smp2p_gpio_clr_bits(cb_out, SMP2P_RMT_IGNORE_MASK); - - /* verify response including 24 interrupts */ - do { - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in->cb_completion, HZ / 2), - >, 0); - reinit_completion(&cb_in->cb_completion); - } while (cb_in->cb_count < 24); - response = smp2p_gpio_get_value(cb_in); - SMP2P_SET_RMT_CMD_TYPE(request, 0); - UT_ASSERT_HEX(request, ==, response); - UT_ASSERT_INT(24, ==, cb_in->cb_count); - - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", name); - seq_puts(s, "\tFailed\n"); - } - - /* unregister for interrupts */ - if (cb_in->irq_base_id) { - for (id = 0; id < SMP2P_BITS_PER_ENTRY; ++id) - free_irq(cb_in->irq_base_id + id, cb_in); - } - - smp2p_gpio_open_test_entry("smp2p", remote_pid, false); - msm_smp2p_init_rmt_lpb_proc(remote_pid); -} - -/** - * 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_puts(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_inout_core(s, pid, __func__); - } -} - -static int __init smp2p_debugfs_init(void) -{ - /* register GPIO pins */ - (void)platform_driver_register(&smp2p_gpio_driver); - - /* - * 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_gpio_out", smp2p_ut_local_gpio_out); - smp2p_debug_create("ut_local_gpio_in", smp2p_ut_local_gpio_in); - smp2p_debug_create("ut_local_gpio_in_update_open", - smp2p_ut_local_gpio_in_update_open); - smp2p_debug_create("ut_remote_gpio_inout", smp2p_ut_remote_inout); - return 0; -} -late_initcall(smp2p_debugfs_init); diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index eeb5cba4325b..a53c15895153 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -15,8 +15,7 @@ obj-$(CONFIG_MSM_GLINK_SPI_XPRT) += glink_spi_xprt.o obj-$(CONFIG_MSM_SMEM_LOGGING) += smem_log.o obj-$(CONFIG_MSM_SYSMON_GLINK_COMM) += sysmon-glink.o sysmon-qmi.o obj-$(CONFIG_ARCH_MSM8996) += kryo-l2-accessors.o -obj-$(CONFIG_MSM_SMP2P) += smp2p.o smp2p_debug.o smp2p_sleepstate.o -obj-$(CONFIG_MSM_SMP2P_TEST) += smp2p_loopback.o smp2p_test.o smp2p_spinlock_test.o +obj-$(CONFIG_MSM_SMP2P) += smp2p.o smp2p_loopback.o smp2p_debug.o smp2p_sleepstate.o obj-$(CONFIG_MSM_QMI_INTERFACE) += qmi_interface.o obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o obj-$(CONFIG_MSM_HVC) += hvc.o diff --git a/drivers/soc/qcom/smp2p_spinlock_test.c b/drivers/soc/qcom/smp2p_spinlock_test.c deleted file mode 100644 index 1fe4411eebde..000000000000 --- a/drivers/soc/qcom/smp2p_spinlock_test.c +++ /dev/null @@ -1,819 +0,0 @@ -/* drivers/soc/qcom/smp2p_spinlock_test.c - * - * Copyright (c) 2013-2017, 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 -#include -#include -#include -#include -#include -#include -#include -#include "smem_private.h" -#include "smp2p_private.h" -#include "smp2p_test_common.h" - -#define RS_END_THIEF_PID_BIT 20 -#define RS_END_THIEF_MASK 0x00f00000 - -/* Spinlock commands used for testing Apps<->RPM spinlocks. */ -enum RPM_SPINLOCK_CMDS { - RPM_CMD_INVALID, - RPM_CMD_START, - RPM_CMD_LOCKED, - RPM_CMD_UNLOCKED, - RPM_CMD_END, -}; - -/* Shared structure for testing Apps<->RPM spinlocks. */ -struct rpm_spinlock_test { - uint32_t apps_cmd; - uint32_t apps_lock_count; - uint32_t rpm_cmd; - uint32_t rpm_lock_count; -}; - -static uint32_t ut_remote_spinlock_run_time = 1; - -/** - * smp2p_ut_remote_spinlock_core - Verify remote spinlock. - * - * @s: Pointer to output file - * @remote_pid: Remote processor to test - * @use_trylock: Use trylock to prevent an Apps deadlock if the - * remote spinlock fails. - */ -static void smp2p_ut_remote_spinlock_core(struct seq_file *s, int remote_pid, - bool use_trylock) -{ - int failed = 0; - unsigned lock_count = 0; - struct msm_smp2p_out *handle = NULL; - int ret; - uint32_t test_request; - uint32_t test_response; - struct mock_cb_data cb_out; - struct mock_cb_data cb_in; - unsigned long flags; - unsigned n; - bool have_lock; - bool timeout; - int failed_tmp; - int spinlock_owner; - remote_spinlock_t *smem_spinlock; - unsigned long end; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - - cb_out.initialized = false; - cb_in.initialized = false; - mock_cb_data_init(&cb_out); - mock_cb_data_init(&cb_in); - do { - smem_spinlock = smem_get_remote_spinlock(); - UT_ASSERT_PTR(smem_spinlock, !=, NULL); - - /* Open output entry */ - ret = msm_smp2p_out_open(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &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_RLPB_ENTRY_NAME, - &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); - - /* Send start */ - mock_cb_data_reset(&cb_in); - mock_cb_data_reset(&cb_out); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE_REQ(test_request); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_START); - SMP2P_SET_RMT_DATA(test_request, 0x0); - 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, ==, 1); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); - ret = msm_smp2p_in_read(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &test_response); - UT_ASSERT_INT(ret, ==, 0); - - test_response = SMP2P_GET_RMT_CMD(test_response); - if (test_response != SMP2P_LB_CMD_RSPIN_LOCKED && - test_response != SMP2P_LB_CMD_RSPIN_UNLOCKED) { - /* invalid response from remote - abort test */ - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, 0x0); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_HEX(SMP2P_LB_CMD_RSPIN_LOCKED, ==, - test_response); - } - - /* Run spinlock test */ - if (use_trylock) - seq_puts(s, "\tUsing remote_spin_trylock\n"); - else - seq_puts(s, "\tUsing remote_spin_lock\n"); - - flags = 0; - have_lock = false; - timeout = false; - spinlock_owner = 0; - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE_REQ(test_request); - end = jiffies + (ut_remote_spinlock_run_time * HZ); - if (ut_remote_spinlock_run_time < 300) { - seq_printf(s, "\tRunning test for %u seconds; ", - ut_remote_spinlock_run_time); - seq_puts(s, - "on physical hardware please run >= 300 seconds by doing 'echo 300 > ut_remote_spinlock_time'\n"); - } - while (time_is_after_jiffies(end)) { - /* try to acquire spinlock */ - if (use_trylock) { - unsigned long j_start = jiffies; - while (!remote_spin_trylock_irqsave( - smem_spinlock, flags)) { - if (jiffies_to_msecs(jiffies - j_start) - > 1000) { - seq_puts(s, - "\tFail: Timeout trying to get the lock\n"); - timeout = true; - break; - } - } - if (timeout) - break; - } else { - remote_spin_lock_irqsave(smem_spinlock, flags); - } - have_lock = true; - ++lock_count; - - /* tell the remote side that we have the lock */ - SMP2P_SET_RMT_DATA(test_request, lock_count); - SMP2P_SET_RMT_CMD(test_request, - SMP2P_LB_CMD_RSPIN_LOCKED); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_INT(ret, ==, 0); - - /* verify the other side doesn't say it has the lock */ - for (n = 0; n < 1000; ++n) { - spinlock_owner = - remote_spin_owner(smem_spinlock); - if (spinlock_owner != SMEM_APPS) { - /* lock stolen by remote side */ - seq_puts(s, "\tFail: Remote side: "); - seq_printf(s, "%d stole lock pid: %d\n", - remote_pid, spinlock_owner); - failed = true; - break; - } - spinlock_owner = 0; - - ret = msm_smp2p_in_read(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &test_response); - UT_ASSERT_INT(ret, ==, 0); - test_response = - SMP2P_GET_RMT_CMD(test_response); - UT_ASSERT_HEX(SMP2P_LB_CMD_RSPIN_UNLOCKED, ==, - test_response); - } - if (failed) - break; - - /* tell remote side we are unlocked and release lock */ - SMP2P_SET_RMT_CMD(test_request, - SMP2P_LB_CMD_RSPIN_UNLOCKED); - (void)msm_smp2p_out_write(handle, test_request); - have_lock = false; - remote_spin_unlock_irqrestore(smem_spinlock, flags); - } - if (have_lock) - remote_spin_unlock_irqrestore(smem_spinlock, flags); - - /* End test */ - mock_cb_data_reset(&cb_in); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, lock_count | - (spinlock_owner << RS_END_THIEF_PID_BIT)); - (void)msm_smp2p_out_write(handle, test_request); - - failed_tmp = failed; - failed = false; - do { - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &cb_in.cb_completion, HZ * 2), - >, 0); - reinit_completion(&cb_in.cb_completion); - ret = msm_smp2p_in_read(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &test_response); - UT_ASSERT_INT(ret, ==, 0); - } while (!failed && - SMP2P_GET_RMT_CMD(test_response) != - SMP2P_LB_CMD_RSPIN_END); - if (failed) - break; - failed = failed_tmp; - - test_response = SMP2P_GET_RMT_DATA(test_response); - seq_puts(s, "\tLocked spinlock "); - seq_printf(s, "local %u times; remote %u times", - lock_count, - test_response & ((1 << RS_END_THIEF_PID_BIT) - 1) - ); - if (test_response & RS_END_THIEF_MASK) { - seq_puts(s, "Remote side reporting lock stolen by "); - seq_printf(s, "pid %d.\n", - SMP2P_GET_BITS(test_response, - RS_END_THIEF_MASK, - RS_END_THIEF_PID_BIT)); - failed = 1; - } - seq_puts(s, "\n"); - - /* Cleanup */ - ret = msm_smp2p_out_close(&handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(handle, ==, NULL); - ret = msm_smp2p_in_unregister(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - - if (!failed && !timeout) - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - if (handle) { - /* send end command */ - test_request = 0; - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, lock_count); - (void)msm_smp2p_out_write(handle, test_request); - (void)msm_smp2p_out_close(&handle); - } - (void)msm_smp2p_in_unregister(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &cb_in.nb); - - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * smp2p_ut_remote_spinlock_pid - Verify remote spinlock for a processor. - * - * @s: Pointer to output file - * @pid: Processor to test - * @use_trylock: Use trylock to prevent an Apps deadlock if the - * remote spinlock fails. - */ -static void smp2p_ut_remote_spinlock_pid(struct seq_file *s, int pid, - bool use_trylock) -{ - struct smp2p_interrupt_config *int_cfg; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, "Remote processor config unavailable\n"); - return; - } - - if (pid >= SMP2P_NUM_PROCS || !int_cfg[pid].is_configured) - return; - - msm_smp2p_deinit_rmt_lpb_proc(pid); - smp2p_ut_remote_spinlock_core(s, pid, use_trylock); - msm_smp2p_init_rmt_lpb_proc(pid); -} - -/** - * smp2p_ut_remote_spinlock - Verify remote spinlock for all processors. - * - * @s: pointer to output file - */ -static void smp2p_ut_remote_spinlock(struct seq_file *s) -{ - int pid; - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) - smp2p_ut_remote_spinlock_pid(s, pid, false); -} - -/** - * smp2p_ut_remote_spin_trylock - Verify remote trylock for all processors. - * - * @s: Pointer to output file - */ -static void smp2p_ut_remote_spin_trylock(struct seq_file *s) -{ - int pid; - - for (pid = 0; pid < SMP2P_NUM_PROCS; ++pid) - smp2p_ut_remote_spinlock_pid(s, pid, true); -} - -/** - * smp2p_ut_remote_spinlock - Verify remote spinlock for all processors. - * - * @s: pointer to output file - * - * This test verifies inbound and outbound functionality for all - * configured remote processor. - */ -static void smp2p_ut_remote_spinlock_modem(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_MODEM_PROC, false); -} - -static void smp2p_ut_remote_spinlock_adsp(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_AUDIO_PROC, false); -} - -static void smp2p_ut_remote_spinlock_dsps(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_SENSOR_PROC, false); -} - -static void smp2p_ut_remote_spinlock_wcnss(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_WIRELESS_PROC, false); -} - -static void smp2p_ut_remote_spinlock_cdsp(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_CDSP_PROC, false); -} - -static void smp2p_ut_remote_spinlock_tz(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_pid(s, SMP2P_TZ_PROC, false); -} - -/** - * smp2p_ut_remote_spinlock_rpm - Verify remote spinlock. - * - * @s: pointer to output file - * @remote_pid: Remote processor to test - */ -static void smp2p_ut_remote_spinlock_rpm(struct seq_file *s) -{ - int failed = 0; - unsigned long flags; - unsigned n; - unsigned test_num; - struct rpm_spinlock_test *data_ptr; - remote_spinlock_t *smem_spinlock; - bool have_lock; - - seq_printf(s, "Running %s for Apps<->RPM Test\n", - __func__); - do { - smem_spinlock = smem_get_remote_spinlock(); - UT_ASSERT_PTR(smem_spinlock, !=, NULL); - - data_ptr = smem_alloc(SMEM_ID_VENDOR0, - sizeof(struct rpm_spinlock_test), 0, - SMEM_ANY_HOST_FLAG); - UT_ASSERT_PTR(0, !=, data_ptr); - - /* Send start */ - writel_relaxed(0, &data_ptr->apps_lock_count); - writel_relaxed(RPM_CMD_START, &data_ptr->apps_cmd); - - seq_puts(s, "\tWaiting for RPM to start test\n"); - for (n = 0; n < 1000; ++n) { - if (readl_relaxed(&data_ptr->rpm_cmd) != - RPM_CMD_INVALID) - break; - usleep_range(1000, 1200); - } - if (readl_relaxed(&data_ptr->rpm_cmd) == RPM_CMD_INVALID) { - /* timeout waiting for RPM */ - writel_relaxed(RPM_CMD_INVALID, &data_ptr->apps_cmd); - UT_ASSERT_INT(RPM_CMD_LOCKED, !=, RPM_CMD_INVALID); - } - - /* Run spinlock test */ - flags = 0; - have_lock = false; - for (test_num = 0; !failed && test_num < 10000; ++test_num) { - /* acquire spinlock */ - remote_spin_lock_irqsave(smem_spinlock, flags); - have_lock = true; - data_ptr->apps_lock_count++; - writel_relaxed(data_ptr->apps_lock_count, - &data_ptr->apps_lock_count); - writel_relaxed(RPM_CMD_LOCKED, &data_ptr->apps_cmd); - /* - * Ensure that the remote side sees our lock has - * been acquired before we start polling their status. - */ - wmb(); - - /* verify the other side doesn't say it has the lock */ - for (n = 0; n < 1000; ++n) { - UT_ASSERT_HEX(RPM_CMD_UNLOCKED, ==, - readl_relaxed(&data_ptr->rpm_cmd)); - } - if (failed) - break; - - /* release spinlock */ - have_lock = false; - writel_relaxed(RPM_CMD_UNLOCKED, &data_ptr->apps_cmd); - /* - * Ensure that our status-update write was committed - * before we unlock the spinlock. - */ - wmb(); - remote_spin_unlock_irqrestore(smem_spinlock, flags); - } - if (have_lock) - remote_spin_unlock_irqrestore(smem_spinlock, flags); - - /* End test */ - writel_relaxed(RPM_CMD_INVALID, &data_ptr->apps_cmd); - seq_printf(s, "\tLocked spinlock local %u remote %u\n", - readl_relaxed(&data_ptr->apps_lock_count), - readl_relaxed(&data_ptr->rpm_lock_count)); - - if (!failed) - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -struct rmt_spinlock_work_item { - struct work_struct work; - struct completion try_lock; - struct completion locked; - bool has_locked; -}; - -static void ut_remote_spinlock_ssr_worker(struct work_struct *work) -{ - remote_spinlock_t *smem_spinlock; - unsigned long flags; - struct rmt_spinlock_work_item *work_item = - container_of(work, struct rmt_spinlock_work_item, work); - - work_item->has_locked = false; - complete(&work_item->try_lock); - smem_spinlock = smem_get_remote_spinlock(); - if (!smem_spinlock) { - pr_err("%s Failed\n", __func__); - return; - } - - remote_spin_lock_irqsave(smem_spinlock, flags); - remote_spin_unlock_irqrestore(smem_spinlock, flags); - work_item->has_locked = true; - complete(&work_item->locked); -} - -/** - * smp2p_ut_remote_spinlock_ssr - Verify remote spinlock. - * - * @s: pointer to output file - */ -static void smp2p_ut_remote_spinlock_ssr(struct seq_file *s) -{ - int failed = 0; - unsigned long flags; - remote_spinlock_t *smem_spinlock; - int spinlock_owner = 0; - - struct workqueue_struct *ws = NULL; - struct rmt_spinlock_work_item work_item = { .has_locked = false }; - - seq_printf(s, " Running %s Test\n", - __func__); - do { - smem_spinlock = smem_get_remote_spinlock(); - UT_ASSERT_PTR(smem_spinlock, !=, NULL); - - ws = create_singlethread_workqueue("ut_remote_spinlock_ssr"); - UT_ASSERT_PTR(ws, !=, NULL); - INIT_WORK(&work_item.work, ut_remote_spinlock_ssr_worker); - init_completion(&work_item.try_lock); - init_completion(&work_item.locked); - - remote_spin_lock_irqsave(smem_spinlock, flags); - /* Unlock local spin lock and hold HW spinlock */ - spin_unlock_irqrestore(&((smem_spinlock)->local), flags); - - queue_work(ws, &work_item.work); - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &work_item.try_lock, HZ * 2), >, 0); - UT_ASSERT_INT((int)work_item.has_locked, ==, 0); - spinlock_owner = remote_spin_owner(smem_spinlock); - UT_ASSERT_INT(spinlock_owner, ==, SMEM_APPS); - remote_spin_release_all(SMEM_APPS); - - UT_ASSERT_INT( - (int)wait_for_completion_timeout( - &work_item.locked, HZ * 2), >, 0); - - if (!failed) - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * smp2p_ut_remote_spinlock_track_core - Verify remote spinlock. - * - * @s: Pointer to output file - * @remote_pid: Remote processor to test - * - * This test has the remote subsystem grab the lock, and then has the local - * subsystem attempt to grab the lock using the trylock() API. It then verifies - * that the ID in the hw_spinlocks array matches the owner of the lock. - */ -static void smp2p_ut_remote_spinlock_track_core(struct seq_file *s, - int remote_pid) -{ - int failed = 0; - struct msm_smp2p_out *handle = NULL; - int ret; - uint32_t test_request; - uint32_t test_response; - struct mock_cb_data cb_out; - struct mock_cb_data cb_in; - unsigned long flags; - int stored_value; - remote_spinlock_t *smem_spinlock; - - seq_printf(s, "Running %s for '%s' remote pid %d\n", - __func__, smp2p_pid_to_name(remote_pid), remote_pid); - - cb_out.initialized = false; - cb_in.initialized = false; - mock_cb_data_init(&cb_out); - mock_cb_data_init(&cb_in); - do { - smem_spinlock = smem_get_remote_spinlock(); - UT_ASSERT_PTR(smem_spinlock, !=, NULL); - - /* Open output entry */ - ret = msm_smp2p_out_open(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &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_RLPB_ENTRY_NAME, - &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); - - /* Send start */ - mock_cb_data_reset(&cb_in); - mock_cb_data_reset(&cb_out); - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE_REQ(test_request); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_START); - SMP2P_SET_RMT_DATA(test_request, 0x0); - 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, ==, 1); - UT_ASSERT_INT(cb_in.event_entry_update, ==, 1); - ret = msm_smp2p_in_read(remote_pid, SMP2P_RLPB_ENTRY_NAME, - &test_response); - UT_ASSERT_INT(ret, ==, 0); - - test_response = SMP2P_GET_RMT_CMD(test_response); - if (test_response != SMP2P_LB_CMD_RSPIN_LOCKED && - test_response != SMP2P_LB_CMD_RSPIN_UNLOCKED) { - /* invalid response from remote - abort test */ - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE(test_request, 1); - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, 0x0); - ret = msm_smp2p_out_write(handle, test_request); - UT_ASSERT_HEX(SMP2P_LB_CMD_RSPIN_LOCKED, ==, - test_response); - } - - /* Run spinlock test */ - flags = 0; - test_request = 0x0; - SMP2P_SET_RMT_CMD_TYPE_REQ(test_request); - - /* try to acquire spinlock */ - remote_spin_trylock_irqsave(smem_spinlock, flags); - /* - * Need to check against the locking token (PID + 1) - * because the remote_spin_owner() API only returns the - * PID. - */ - stored_value = remote_spin_get_hw_spinlocks_element( - smem_spinlock); - UT_ASSERT_INT(stored_value, ==, - remote_spin_owner(smem_spinlock) + 1); - UT_ASSERT_INT(stored_value, ==, remote_pid + 1); - - /* End test */ - test_request = 0x0; - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, 0x0); - (void)msm_smp2p_out_write(handle, test_request); - - /* Cleanup */ - ret = msm_smp2p_out_close(&handle); - UT_ASSERT_INT(ret, ==, 0); - UT_ASSERT_PTR(handle, ==, NULL); - ret = msm_smp2p_in_unregister(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &cb_in.nb); - UT_ASSERT_INT(ret, ==, 0); - - if (!failed) - seq_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - if (handle) { - /* send end command */ - test_request = 0x0; - SMP2P_SET_RMT_CMD(test_request, SMP2P_LB_CMD_RSPIN_END); - SMP2P_SET_RMT_DATA(test_request, 0x0); - (void)msm_smp2p_out_write(handle, test_request); - (void)msm_smp2p_out_close(&handle); - } - (void)msm_smp2p_in_unregister(remote_pid, - SMP2P_RLPB_ENTRY_NAME, &cb_in.nb); - - pr_err("%s: Failed\n", __func__); - seq_puts(s, "\tFailed\n"); - } -} - -/** - * smp2p_ut_remote_spinlock_track - Verify PID tracking for modem. - * - * @s: Pointer to output file - * @pid: The processor to test - */ -static void smp2p_ut_remote_spinlock_track(struct seq_file *s, int pid) -{ - struct smp2p_interrupt_config *int_cfg; - - int_cfg = smp2p_get_interrupt_config(); - if (!int_cfg) { - seq_puts(s, "Remote processor config unavailable\n"); - return; - } - - if (pid >= SMP2P_NUM_PROCS || !int_cfg[pid].is_configured) - return; - - msm_smp2p_deinit_rmt_lpb_proc(pid); - smp2p_ut_remote_spinlock_track_core(s, pid); - msm_smp2p_init_rmt_lpb_proc(pid); -} - -/** - * smp2p_ut_remote_spinlock_track - Verify PID tracking for all processors. - * - * @s: Pointer to output file - * - * This test verifies PID tracking for all configured remote processors. - */ -static void smp2p_ut_remote_spinlock_track_modem(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_MODEM_PROC); -} - -static void smp2p_ut_remote_spinlock_track_adsp(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_AUDIO_PROC); -} - -static void smp2p_ut_remote_spinlock_track_dsps(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_SENSOR_PROC); -} - -static void smp2p_ut_remote_spinlock_track_wcnss(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_WIRELESS_PROC); -} - -static void smp2p_ut_remote_spinlock_track_cdsp(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_CDSP_PROC); -} - -static void smp2p_ut_remote_spinlock_track_tz(struct seq_file *s) -{ - smp2p_ut_remote_spinlock_track(s, SMP2P_TZ_PROC); -} - -static int __init smp2p_debugfs_init(void) -{ - /* - * 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_remote_spinlock", - smp2p_ut_remote_spinlock); - smp2p_debug_create("ut_remote_spin_trylock", - smp2p_ut_remote_spin_trylock); - smp2p_debug_create("ut_remote_spinlock_modem", - smp2p_ut_remote_spinlock_modem); - smp2p_debug_create("ut_remote_spinlock_adsp", - smp2p_ut_remote_spinlock_adsp); - smp2p_debug_create("ut_remote_spinlock_dsps", - smp2p_ut_remote_spinlock_dsps); - smp2p_debug_create("ut_remote_spinlock_wcnss", - smp2p_ut_remote_spinlock_wcnss); - smp2p_debug_create("ut_remote_spinlock_cdsp", - smp2p_ut_remote_spinlock_cdsp); - smp2p_debug_create("ut_remote_spinlock_tz", - smp2p_ut_remote_spinlock_tz); - smp2p_debug_create("ut_remote_spinlock_rpm", - smp2p_ut_remote_spinlock_rpm); - smp2p_debug_create_u32("ut_remote_spinlock_time", - &ut_remote_spinlock_run_time); - smp2p_debug_create("ut_remote_spinlock_ssr", - &smp2p_ut_remote_spinlock_ssr); - smp2p_debug_create("ut_remote_spinlock_track_modem", - &smp2p_ut_remote_spinlock_track_modem); - smp2p_debug_create("ut_remote_spinlock_track_adsp", - &smp2p_ut_remote_spinlock_track_adsp); - smp2p_debug_create("ut_remote_spinlock_track_dsps", - &smp2p_ut_remote_spinlock_track_dsps); - smp2p_debug_create("ut_remote_spinlock_track_wcnss", - &smp2p_ut_remote_spinlock_track_wcnss); - smp2p_debug_create("ut_remote_spinlock_track_cdsp", - &smp2p_ut_remote_spinlock_track_cdsp); - smp2p_debug_create("ut_remote_spinlock_track_tz", - &smp2p_ut_remote_spinlock_track_tz); - return 0; -} -module_init(smp2p_debugfs_init); diff --git a/drivers/soc/qcom/smp2p_test.c b/drivers/soc/qcom/smp2p_test.c deleted file mode 100644 index e81bada0137a..000000000000 --- a/drivers/soc/qcom/smp2p_test.c +++ /dev/null @@ -1,1327 +0,0 @@ -/* drivers/soc/qcom/smp2p_test.c - * - * Copyright (c) 2013-2017, 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 -#include -#include -#include -#include -#include -#include -#include -#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_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(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_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(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_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(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; - reinit_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; - reinit_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; - reinit_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; - reinit_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_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(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_puts(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_puts(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_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_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_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(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_puts(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_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(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_puts(s, "\tOK\n"); - } while (0); - - if (failed) { - pr_err("%s: Failed\n", __func__); - seq_puts(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"); - } -} - -/** - * get_ssr_name_for_proc - Retrieve an SSR name from the provided list - * - * @names: List of possible processor names - * @name_len: The length of @names - * @index: Index into @names - * - * Return: Pointer to the next processor name, NULL in error conditions - */ -static char *get_ssr_name_for_proc(char *names[], size_t name_len, int index) -{ - if (index >= name_len) { - pr_err("%s: SSR failed; check subsys name table\n", - __func__); - return NULL; - } - - return names[index]; -} - -/** - * 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; - int name_index; - int ret; - uint32_t ssr_done_start; - bool ssr_ack_enabled = false; - bool ssr_success = false; - char *name = NULL; - - static char *mpss_names[] = {"modem", "mpss"}; - static char *lpass_names[] = {"adsp", "lpass"}; - static char *sensor_names[] = {"slpi", "dsps"}; - static char *wcnss_names[] = {"wcnss"}; - - 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 */ - name_index = 0; - while (!ssr_success) { - - switch (rpid) { - case SMP2P_MODEM_PROC: - name = get_ssr_name_for_proc(mpss_names, - ARRAY_SIZE(mpss_names), - name_index); - break; - case SMP2P_AUDIO_PROC: - name = get_ssr_name_for_proc(lpass_names, - ARRAY_SIZE(lpass_names), - name_index); - break; - case SMP2P_SENSOR_PROC: - name = get_ssr_name_for_proc(sensor_names, - ARRAY_SIZE(sensor_names), - name_index); - break; - case SMP2P_WIRELESS_PROC: - name = get_ssr_name_for_proc(wcnss_names, - ARRAY_SIZE(wcnss_names), - name_index); - break; - default: - pr_err("%s: Invalid proc ID %d given for ssr\n", - __func__, rpid); - } - - if (!name) { - seq_puts(s, "\tSSR failed; check subsys name table\n"); - failed = true; - break; - } - - seq_printf(s, "Restarting '%s'\n", name); - ret = subsystem_restart(name); - if (ret == -ENODEV) { - seq_puts(s, "\tSSR call failed\n"); - ++name_index; - continue; - } - ssr_success = true; - } - if (failed) - break; - - 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 DEFINE_MUTEX(show_lock); - -static int debugfs_show(struct seq_file *s, void *data) -{ - void (*show)(struct seq_file *) = s->private; - - mutex_lock(&show_lock); - show(s); - mutex_unlock(&show_lock); - - 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); -} - -void smp2p_debug_create_u32(const char *name, uint32_t *value) -{ - struct dentry *file; - - file = debugfs_create_u32(name, S_IRUGO | S_IWUSR, dent, value); - 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); diff --git a/drivers/soc/qcom/smp2p_test_common.h b/drivers/soc/qcom/smp2p_test_common.h deleted file mode 100644 index 3be519bc0c96..000000000000 --- a/drivers/soc/qcom/smp2p_test_common.h +++ /dev/null @@ -1,214 +0,0 @@ -/* drivers/soc/qcom/smp2p_test_common.h - * - * Copyright (c) 2013-2014,2016 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. - */ -#ifndef _SMP2P_TEST_COMMON_H_ -#define _SMP2P_TEST_COMMON_H_ - -#include - -/** - * Unit test assertion for logging test cases. - * - * @a lval - * @b rval - * @cmp comparison operator - * - * Assertion fails if (@a cmp @b) is not true which then - * logs the function and line number where the error occurred - * along with the values of @a and @b. - * - * Assumes that the following local variables exist: - * @s - sequential output file pointer - * @failed - set to true if test fails - */ -#define UT_ASSERT_INT(a, cmp, b) \ - { \ - int a_tmp = (a); \ - int b_tmp = (b); \ - if (!((a_tmp)cmp(b_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%d) " #cmp " " #b "(%d)\n", \ - __func__, __LINE__, \ - a_tmp, b_tmp); \ - failed = 1; \ - break; \ - } \ - } - -#define UT_ASSERT_PTR(a, cmp, b) \ - { \ - void *a_tmp = (a); \ - void *b_tmp = (b); \ - if (!((a_tmp)cmp(b_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%pK) " #cmp \ - " " #b "(%pK)\n", \ - __func__, __LINE__, \ - a_tmp, b_tmp); \ - failed = 1; \ - break; \ - } \ - } - -#define UT_ASSERT_UINT(a, cmp, b) \ - { \ - unsigned a_tmp = (a); \ - unsigned b_tmp = (b); \ - if (!((a_tmp)cmp(b_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%u) " #cmp " " #b "(%u)\n", \ - __func__, __LINE__, \ - a_tmp, b_tmp); \ - failed = 1; \ - break; \ - } \ - } - -#define UT_ASSERT_HEX(a, cmp, b) \ - { \ - unsigned a_tmp = (a); \ - unsigned b_tmp = (b); \ - if (!((a_tmp)cmp(b_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%x) " #cmp " " #b "(%x)\n", \ - __func__, __LINE__, \ - a_tmp, b_tmp); \ - failed = 1; \ - break; \ - } \ - } - -/** - * In-range unit test assertion for test cases. - * - * @a lval - * @minv Minimum value - * @maxv Maximum value - * - * Assertion fails if @a is not on the exclusive range minv, maxv - * ((@a < @minv) or (@a > @maxv)). In the failure case, the macro - * logs the function and line number where the error occurred along - * with the values of @a and @minv, @maxv. - * - * Assumes that the following local variables exist: - * @s - sequential output file pointer - * @failed - set to true if test fails - */ -#define UT_ASSERT_INT_IN_RANGE(a, minv, maxv) \ - { \ - int a_tmp = (a); \ - int minv_tmp = (minv); \ - int maxv_tmp = (maxv); \ - if (((a_tmp) < (minv_tmp)) || ((a_tmp) > (maxv_tmp))) { \ - seq_printf(s, "%s:%d Fail: " #a "(%d) < " #minv "(%d) or " \ - #a "(%d) > " #maxv "(%d)\n", \ - __func__, __LINE__, \ - a_tmp, minv_tmp, a_tmp, maxv_tmp); \ - failed = 1; \ - break; \ - } \ - } - -/* Structure to track state changes for the notifier callback. */ -struct mock_cb_data { - bool initialized; - spinlock_t lock; - struct notifier_block nb; - - /* events */ - struct completion cb_completion; - int cb_count; - int event_open; - int event_entry_update; - struct msm_smp2p_update_notif entry_data; -}; - -void smp2p_debug_create(const char *name, void (*show)(struct seq_file *)); -void smp2p_debug_create_u32(const char *name, uint32_t *value); -static inline int smp2p_test_notify(struct notifier_block *self, - unsigned long event, void *data); - -/** - * Reset mock callback data to default values. - * - * @cb: Mock callback data - */ -static inline void mock_cb_data_reset(struct mock_cb_data *cb) -{ - reinit_completion(&cb->cb_completion); - cb->cb_count = 0; - cb->event_open = 0; - cb->event_entry_update = 0; - memset(&cb->entry_data, 0, - sizeof(struct msm_smp2p_update_notif)); -} - - -/** - * Initialize mock callback data. - * - * @cb: Mock callback data - */ -static inline void mock_cb_data_init(struct mock_cb_data *cb) -{ - if (!cb->initialized) { - init_completion(&cb->cb_completion); - spin_lock_init(&cb->lock); - cb->initialized = true; - cb->nb.notifier_call = smp2p_test_notify; - memset(&cb->entry_data, 0, - sizeof(struct msm_smp2p_update_notif)); - } - mock_cb_data_reset(cb); -} - -/** - * Notifier function passed into SMP2P for testing. - * - * @self: Pointer to calling notifier block - * @event: Event - * @data: Event-specific data - * @returns: 0 - */ -static inline int smp2p_test_notify(struct notifier_block *self, - unsigned long event, void *data) -{ - struct mock_cb_data *cb_data_ptr; - unsigned long flags; - - cb_data_ptr = container_of(self, struct mock_cb_data, nb); - - spin_lock_irqsave(&cb_data_ptr->lock, flags); - - switch (event) { - case SMP2P_OPEN: - ++cb_data_ptr->event_open; - if (data) { - cb_data_ptr->entry_data = - *(struct msm_smp2p_update_notif *)(data); - } - break; - case SMP2P_ENTRY_UPDATE: - ++cb_data_ptr->event_entry_update; - if (data) { - cb_data_ptr->entry_data = - *(struct msm_smp2p_update_notif *)(data); - } - break; - default: - pr_err("%s Unknown event\n", __func__); - break; - } - - ++cb_data_ptr->cb_count; - complete(&cb_data_ptr->cb_completion); - spin_unlock_irqrestore(&cb_data_ptr->lock, flags); - return 0; -} -#endif /* _SMP2P_TEST_COMMON_H_ */