diff options
| author | Pekka Pessi <ppessi@nvidia.com> | 2018-01-25 09:40:11 -0500 |
|---|---|---|
| committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2018-02-22 17:02:55 -0500 |
| commit | dde5bba2788e93828449019a14201869cd853345 (patch) | |
| tree | c910d2851aed84bbcf5cdce687bc642968a65678 /drivers/platform/tegra/rtcpu | |
| parent | 8c72f20a47e8c25ffbc7ea6f69e2ed1cb140c7ed (diff) | |
tegra: camera: rtcpu: reboot after failed tests
Flush the RTCPU tracer and print out the RTCPU log entries after a
test run.
Reboot rtcpu after a failed test run. An unsuccessful test test may
leave RTCPU in a bad state with references to the soon-to-be-unmapped
memory, which may crash the whole device.
Bug 2036751
Change-Id: I9dbabfbdbb88d9e0afd58451f8d2f25e6d263282
Signed-off-by: Pekka Pessi <ppessi@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1653628
Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Bhanu Murthy V <bmurthyv@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/platform/tegra/rtcpu')
| -rw-r--r-- | drivers/platform/tegra/rtcpu/debug.c | 28 | ||||
| -rw-r--r-- | drivers/platform/tegra/rtcpu/tegra-rtcpu-trace.c | 25 |
2 files changed, 42 insertions, 11 deletions
diff --git a/drivers/platform/tegra/rtcpu/debug.c b/drivers/platform/tegra/rtcpu/debug.c index a3e29cbac..e22e9f47a 100644 --- a/drivers/platform/tegra/rtcpu/debug.c +++ b/drivers/platform/tegra/rtcpu/debug.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2016-2017 NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2016-2018, NVIDIA CORPORATION. All rights reserved. |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
| 5 | * under the terms and conditions of the GNU General Public License, | 5 | * under the terms and conditions of the GNU General Public License, |
| @@ -220,11 +220,11 @@ static int camrtc_ivc_dbg_full_frame_xact( | |||
| 220 | timeout); | 220 | timeout); |
| 221 | if (timeout <= 0) { | 221 | if (timeout <= 0) { |
| 222 | ret = timeout ?: -ETIMEDOUT; | 222 | ret = timeout ?: -ETIMEDOUT; |
| 223 | goto out; | 223 | break; |
| 224 | } | 224 | } |
| 225 | if (tegra_ivc_channel_has_been_reset(ch)) { | 225 | if (tegra_ivc_channel_has_been_reset(ch)) { |
| 226 | ret = -ECONNRESET; | 226 | ret = -ECONNRESET; |
| 227 | goto out; | 227 | break; |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | dev_dbg(&ch->dev, "rx msg\n"); | 230 | dev_dbg(&ch->dev, "rx msg\n"); |
| @@ -232,7 +232,7 @@ static int camrtc_ivc_dbg_full_frame_xact( | |||
| 232 | ret = tegra_ivc_read_peek(&ch->ivc, resp, 0, resp_size); | 232 | ret = tegra_ivc_read_peek(&ch->ivc, resp, 0, resp_size); |
| 233 | if (ret < 0) { | 233 | if (ret < 0) { |
| 234 | dev_err(&ch->dev, "IVC read error: %d\n", ret); | 234 | dev_err(&ch->dev, "IVC read error: %d\n", ret); |
| 235 | goto out; | 235 | break; |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | tegra_ivc_read_advance(&ch->ivc); | 238 | tegra_ivc_read_advance(&ch->ivc); |
| @@ -244,6 +244,7 @@ static int camrtc_ivc_dbg_full_frame_xact( | |||
| 244 | 244 | ||
| 245 | dev_err(&ch->dev, "unexpected response\n"); | 245 | dev_err(&ch->dev, "unexpected response\n"); |
| 246 | } | 246 | } |
| 247 | |||
| 247 | out: | 248 | out: |
| 248 | tegra_ivc_channel_runtime_put(ch); | 249 | tegra_ivc_channel_runtime_put(ch); |
| 249 | unlock: | 250 | unlock: |
| @@ -571,12 +572,24 @@ static int camrtc_test_run_and_show_result(struct seq_file *file, | |||
| 571 | struct camrtc_dbg_request, run_mem_test_data.timeout, | 572 | struct camrtc_dbg_request, run_mem_test_data.timeout, |
| 572 | struct camrtc_dbg_request, run_test_data.timeout); | 573 | struct camrtc_dbg_request, run_test_data.timeout); |
| 573 | 574 | ||
| 575 | ret = tegra_ivc_channel_runtime_get(ch); | ||
| 576 | if (ret < 0) | ||
| 577 | return ret; | ||
| 578 | |||
| 574 | req->data.run_test_data.timeout = ns; | 579 | req->data.run_test_data.timeout = ns; |
| 575 | 580 | ||
| 576 | ret = camrtc_ivc_dbg_full_frame_xact(ch, req, req_size, | 581 | ret = camrtc_ivc_dbg_full_frame_xact(ch, req, req_size, |
| 577 | resp, resp_size, timeout); | 582 | resp, resp_size, timeout); |
| 578 | if (ret < 0) | 583 | |
| 579 | return ret; | 584 | tegra_camrtc_flush_trace(camrtc_get_device(ch)); |
| 585 | |||
| 586 | if (ret < 0) { | ||
| 587 | if (ret != -ECONNRESET) { | ||
| 588 | dev_info(&ch->dev, "rebooting after a failed test run"); | ||
| 589 | (void)tegra_camrtc_reboot(&ch->dev); | ||
| 590 | } | ||
| 591 | goto runtime_put; | ||
| 592 | } | ||
| 580 | 593 | ||
| 581 | BUILD_BUG_ON_MISMATCH( | 594 | BUILD_BUG_ON_MISMATCH( |
| 582 | struct camrtc_dbg_response, run_mem_test_data.timeout, | 595 | struct camrtc_dbg_response, run_mem_test_data.timeout, |
| @@ -593,6 +606,9 @@ static int camrtc_test_run_and_show_result(struct seq_file *file, | |||
| 593 | else | 606 | else |
| 594 | seq_write(file, result, result_size); | 607 | seq_write(file, result, result_size); |
| 595 | 608 | ||
| 609 | runtime_put: | ||
| 610 | tegra_ivc_channel_runtime_put(ch); | ||
| 611 | |||
| 596 | return ret; | 612 | return ret; |
| 597 | } | 613 | } |
| 598 | 614 | ||
diff --git a/drivers/platform/tegra/rtcpu/tegra-rtcpu-trace.c b/drivers/platform/tegra/rtcpu/tegra-rtcpu-trace.c index 614e95bc1..d59abbfe1 100644 --- a/drivers/platform/tegra/rtcpu/tegra-rtcpu-trace.c +++ b/drivers/platform/tegra/rtcpu/tegra-rtcpu-trace.c | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #include "soc/tegra/camrtc-trace.h" | ||
| 18 | |||
| 17 | #include <linux/completion.h> | 19 | #include <linux/completion.h> |
| 18 | #include <linux/debugfs.h> | 20 | #include <linux/debugfs.h> |
| 19 | #include <linux/dma-mapping.h> | 21 | #include <linux/dma-mapping.h> |
| @@ -41,8 +43,6 @@ | |||
| 41 | #include "rtcpu/device-group.h" | 43 | #include "rtcpu/device-group.h" |
| 42 | #endif | 44 | #endif |
| 43 | 45 | ||
| 44 | #include "soc/tegra/camrtc-trace.h" | ||
| 45 | |||
| 46 | #define CREATE_TRACE_POINTS | 46 | #define CREATE_TRACE_POINTS |
| 47 | #include <trace/events/tegra_rtcpu.h> | 47 | #include <trace/events/tegra_rtcpu.h> |
| 48 | #include <trace/events/freertos.h> | 48 | #include <trace/events/freertos.h> |
| @@ -60,6 +60,7 @@ | |||
| 60 | struct tegra_rtcpu_trace { | 60 | struct tegra_rtcpu_trace { |
| 61 | struct device *dev; | 61 | struct device *dev; |
| 62 | struct device_node *of_node; | 62 | struct device_node *of_node; |
| 63 | struct mutex lock; | ||
| 63 | 64 | ||
| 64 | /* memory */ | 65 | /* memory */ |
| 65 | void *trace_memory; | 66 | void *trace_memory; |
| @@ -992,11 +993,12 @@ static inline void rtcpu_trace_events(struct tegra_rtcpu_trace *tracer) | |||
| 992 | tracer->copy_last_event = *last_event; | 993 | tracer->copy_last_event = *last_event; |
| 993 | } | 994 | } |
| 994 | 995 | ||
| 995 | static void rtcpu_trace_worker(struct work_struct *work) | 996 | void tegra_rtcpu_trace_flush(struct tegra_rtcpu_trace *tracer) |
| 996 | { | 997 | { |
| 997 | struct tegra_rtcpu_trace *tracer; | 998 | if (tracer == NULL) |
| 999 | return; | ||
| 998 | 1000 | ||
| 999 | tracer = container_of(work, struct tegra_rtcpu_trace, work.work); | 1001 | mutex_lock(&tracer->lock); |
| 1000 | 1002 | ||
| 1001 | /* invalidate the cache line for the pointers */ | 1003 | /* invalidate the cache line for the pointers */ |
| 1002 | dma_sync_single_for_cpu(tracer->dev, tracer->dma_handle_pointers, | 1004 | dma_sync_single_for_cpu(tracer->dev, tracer->dma_handle_pointers, |
| @@ -1006,6 +1008,18 @@ static void rtcpu_trace_worker(struct work_struct *work) | |||
| 1006 | rtcpu_trace_exceptions(tracer); | 1008 | rtcpu_trace_exceptions(tracer); |
| 1007 | rtcpu_trace_events(tracer); | 1009 | rtcpu_trace_events(tracer); |
| 1008 | 1010 | ||
| 1011 | mutex_unlock(&tracer->lock); | ||
| 1012 | } | ||
| 1013 | EXPORT_SYMBOL(tegra_rtcpu_trace_flush); | ||
| 1014 | |||
| 1015 | static void rtcpu_trace_worker(struct work_struct *work) | ||
| 1016 | { | ||
| 1017 | struct tegra_rtcpu_trace *tracer; | ||
| 1018 | |||
| 1019 | tracer = container_of(work, struct tegra_rtcpu_trace, work.work); | ||
| 1020 | |||
| 1021 | tegra_rtcpu_trace_flush(tracer); | ||
| 1022 | |||
| 1009 | /* reschedule */ | 1023 | /* reschedule */ |
| 1010 | schedule_delayed_work(&tracer->work, tracer->work_interval_jiffies); | 1024 | schedule_delayed_work(&tracer->work, tracer->work_interval_jiffies); |
| 1011 | } | 1025 | } |
| @@ -1149,6 +1163,7 @@ struct tegra_rtcpu_trace *tegra_rtcpu_trace_create(struct device *dev, | |||
| 1149 | return NULL; | 1163 | return NULL; |
| 1150 | 1164 | ||
| 1151 | tracer->dev = dev; | 1165 | tracer->dev = dev; |
| 1166 | mutex_init(&tracer->lock); | ||
| 1152 | 1167 | ||
| 1153 | /* Get the trace memory */ | 1168 | /* Get the trace memory */ |
| 1154 | ret = rtcpu_trace_setup_memory(tracer); | 1169 | ret = rtcpu_trace_setup_memory(tracer); |
