diff options
| author | Arto Merilainen <amerilainen@nvidia.com> | 2017-06-14 09:25:11 -0400 |
|---|---|---|
| committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-06-21 07:35:02 -0400 |
| commit | 2a36ed7bacd91e3bc8e9291da10462704af3003d (patch) | |
| tree | 3d660ec58f2e730aec39a29bd242fa2bc36afb4a | |
| parent | 66245cde287c73bcab0eed57bfc7af2a6c9fb550 (diff) | |
video: tegra: host: Recover engine on abort
Currently PVA cannot be recovered if there is a critical error (i.e.
abort from the engine). This change modifies code to reset the PVA
and abort existing work if:
* PVA issues abort ISR
* Communication through mailbox interface times out
* Communication through CCQ interface times out
JIRA PVA-51
Change-Id: I448d231737a122fe5bf6787e5fa1794c2a7b1a33
Signed-off-by: Arto Merilainen <amerilainen@nvidia.com>
Reviewed-on: http://git-master/r/1502343
GVS: Gerrit_Virtual_Submit
Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com>
Reviewed-by: Vinod Gopalakrishnakurup <vinodg@nvidia.com>
| -rw-r--r-- | drivers/video/tegra/host/nvhost_queue.c | 10 | ||||
| -rw-r--r-- | drivers/video/tegra/host/nvhost_queue.h | 7 | ||||
| -rw-r--r-- | drivers/video/tegra/host/pva/Makefile | 1 | ||||
| -rw-r--r-- | drivers/video/tegra/host/pva/pva-interface.h | 1 | ||||
| -rw-r--r-- | drivers/video/tegra/host/pva/pva.c | 19 | ||||
| -rw-r--r-- | drivers/video/tegra/host/pva/pva.h | 25 | ||||
| -rw-r--r-- | drivers/video/tegra/host/pva/pva_abort.c | 89 | ||||
| -rw-r--r-- | drivers/video/tegra/host/pva/pva_ccq.c | 16 | ||||
| -rw-r--r-- | drivers/video/tegra/host/pva/pva_isr.c | 10 | ||||
| -rw-r--r-- | drivers/video/tegra/host/pva/pva_mailbox.c | 44 | ||||
| -rw-r--r-- | drivers/video/tegra/host/pva/pva_mailbox.h | 14 | ||||
| -rw-r--r-- | drivers/video/tegra/host/pva/pva_queue.c | 93 | ||||
| -rw-r--r-- | drivers/video/tegra/host/pva/pva_queue.h | 3 |
13 files changed, 299 insertions, 33 deletions
diff --git a/drivers/video/tegra/host/nvhost_queue.c b/drivers/video/tegra/host/nvhost_queue.c index c9ba3cf02..03cf795eb 100644 --- a/drivers/video/tegra/host/nvhost_queue.c +++ b/drivers/video/tegra/host/nvhost_queue.c | |||
| @@ -227,6 +227,16 @@ void nvhost_queue_deinit(struct nvhost_queue_pool *pool) | |||
| 227 | pool = NULL; | 227 | pool = NULL; |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | void nvhost_queue_abort_all(struct nvhost_queue_pool *pool) | ||
| 231 | { | ||
| 232 | u32 id; | ||
| 233 | |||
| 234 | mutex_lock(&pool->queue_lock); | ||
| 235 | for_each_set_bit(id, &pool->alloc_table, pool->max_queue_cnt) | ||
| 236 | nvhost_queue_abort(&pool->queues[id]); | ||
| 237 | mutex_unlock(&pool->queue_lock); | ||
| 238 | } | ||
| 239 | |||
| 230 | static void nvhost_queue_release(struct kref *ref) | 240 | static void nvhost_queue_release(struct kref *ref) |
| 231 | { | 241 | { |
| 232 | struct nvhost_queue *queue = container_of(ref, struct nvhost_queue, | 242 | struct nvhost_queue *queue = container_of(ref, struct nvhost_queue, |
diff --git a/drivers/video/tegra/host/nvhost_queue.h b/drivers/video/tegra/host/nvhost_queue.h index 510508d54..73b167ab9 100644 --- a/drivers/video/tegra/host/nvhost_queue.h +++ b/drivers/video/tegra/host/nvhost_queue.h | |||
| @@ -185,6 +185,13 @@ struct nvhost_queue *nvhost_queue_alloc(struct nvhost_queue_pool *pool, | |||
| 185 | bool use_channel); | 185 | bool use_channel); |
| 186 | 186 | ||
| 187 | /** | 187 | /** |
| 188 | * @brief Abort all active queues | ||
| 189 | * | ||
| 190 | * @param pool Pointer to a queue pool table | ||
| 191 | */ | ||
| 192 | void nvhost_queue_abort_all(struct nvhost_queue_pool *pool); | ||
| 193 | |||
| 194 | /** | ||
| 188 | * @brief Abort tasks within a client queue | 195 | * @brief Abort tasks within a client queue |
| 189 | * | 196 | * |
| 190 | * This function aborts all tasks from the given clinet queue. If there is no | 197 | * This function aborts all tasks from the given clinet queue. If there is no |
diff --git a/drivers/video/tegra/host/pva/Makefile b/drivers/video/tegra/host/pva/Makefile index a1503925b..517da1196 100644 --- a/drivers/video/tegra/host/pva/Makefile +++ b/drivers/video/tegra/host/pva/Makefile | |||
| @@ -12,6 +12,7 @@ nvhost-pva-objs = \ | |||
| 12 | pva_queue.o \ | 12 | pva_queue.o \ |
| 13 | pva_debug.o \ | 13 | pva_debug.o \ |
| 14 | pva_trace.o \ | 14 | pva_trace.o \ |
| 15 | pva_abort.o \ | ||
| 15 | pva_ccq.o | 16 | pva_ccq.o |
| 16 | 17 | ||
| 17 | obj-$(CONFIG_TEGRA_GRHOST_PVA) += nvhost-pva.o | 18 | obj-$(CONFIG_TEGRA_GRHOST_PVA) += nvhost-pva.o |
diff --git a/drivers/video/tegra/host/pva/pva-interface.h b/drivers/video/tegra/host/pva/pva-interface.h index 2157ae1e2..d272ce6dc 100644 --- a/drivers/video/tegra/host/pva/pva-interface.h +++ b/drivers/video/tegra/host/pva/pva-interface.h | |||
| @@ -90,6 +90,7 @@ | |||
| 90 | #define PVA_AISR_LOGGING_OVERFLOW PVA_BIT(25) | 90 | #define PVA_AISR_LOGGING_OVERFLOW PVA_BIT(25) |
| 91 | #define PVA_AISR_PRINTF_OVERFLOW PVA_BIT(24) | 91 | #define PVA_AISR_PRINTF_OVERFLOW PVA_BIT(24) |
| 92 | #define PVA_AISR_CRASH_LOG PVA_BIT(23) | 92 | #define PVA_AISR_CRASH_LOG PVA_BIT(23) |
| 93 | #define PVA_AISR_ABORT PVA_BIT(0) | ||
| 93 | 94 | ||
| 94 | #define PVA_GET_ERROR_CODE(_s_) PVA_EXTRACT(_s_, 15, 0, enum pva_errors) | 95 | #define PVA_GET_ERROR_CODE(_s_) PVA_EXTRACT(_s_, 15, 0, enum pva_errors) |
| 95 | 96 | ||
diff --git a/drivers/video/tegra/host/pva/pva.c b/drivers/video/tegra/host/pva/pva.c index 028de9fdd..ddc09ca89 100644 --- a/drivers/video/tegra/host/pva/pva.c +++ b/drivers/video/tegra/host/pva/pva.c | |||
| @@ -86,7 +86,6 @@ static int pva_init_fw(struct platform_device *pdev) | |||
| 86 | struct pva_dma_alloc_info *priv2_buffer; | 86 | struct pva_dma_alloc_info *priv2_buffer; |
| 87 | u32 *ucode_ptr; | 87 | u32 *ucode_ptr; |
| 88 | int err = 0, w; | 88 | int err = 0, w; |
| 89 | int timeout; | ||
| 90 | u64 ucode_useg_addr; | 89 | u64 ucode_useg_addr; |
| 91 | 90 | ||
| 92 | nvhost_dbg_fn(""); | 91 | nvhost_dbg_fn(""); |
| @@ -172,16 +171,7 @@ static int pva_init_fw(struct platform_device *pdev) | |||
| 172 | nvhost_dbg_fn("Waiting for PVA to be READY"); | 171 | nvhost_dbg_fn("Waiting for PVA to be READY"); |
| 173 | 172 | ||
| 174 | /* Wait PVA to report itself as ready */ | 173 | /* Wait PVA to report itself as ready */ |
| 175 | if (tegra_platform_is_silicon()) { | 174 | err = pva_mailbox_wait_event(pva, 60000); |
| 176 | timeout = wait_event_timeout(pva->mailbox_waitqueue, | ||
| 177 | pva->mailbox_status == PVA_MBOX_STATUS_DONE, | ||
| 178 | msecs_to_jiffies(60000)); | ||
| 179 | if (timeout <= 0) | ||
| 180 | err = -ETIMEDOUT; | ||
| 181 | |||
| 182 | } else | ||
| 183 | wait_event(pva->mailbox_waitqueue, | ||
| 184 | pva->mailbox_status == PVA_MBOX_STATUS_DONE); | ||
| 185 | 175 | ||
| 186 | pva->mailbox_status = PVA_MBOX_STATUS_INVALID; | 176 | pva->mailbox_status = PVA_MBOX_STATUS_INVALID; |
| 187 | 177 | ||
| @@ -422,6 +412,8 @@ int pva_finalize_poweron(struct platform_device *pdev) | |||
| 422 | } | 412 | } |
| 423 | } | 413 | } |
| 424 | 414 | ||
| 415 | pva->booted = true; | ||
| 416 | |||
| 425 | return err; | 417 | return err; |
| 426 | 418 | ||
| 427 | err_poweron: | 419 | err_poweron: |
| @@ -434,6 +426,8 @@ int pva_prepare_poweroff(struct platform_device *pdev) | |||
| 434 | struct nvhost_device_data *pdata = platform_get_drvdata(pdev); | 426 | struct nvhost_device_data *pdata = platform_get_drvdata(pdev); |
| 435 | struct pva *pva = pdata->private_data; | 427 | struct pva *pva = pdata->private_data; |
| 436 | 428 | ||
| 429 | pva->booted = false; | ||
| 430 | |||
| 437 | disable_irq(pva->irq); | 431 | disable_irq(pva->irq); |
| 438 | 432 | ||
| 439 | pva_free_fw(pdev, pva); | 433 | pva_free_fw(pdev, pva); |
| @@ -477,6 +471,7 @@ static int pva_probe(struct platform_device *pdev) | |||
| 477 | platform_set_drvdata(pdev, pdata); | 471 | platform_set_drvdata(pdev, pdata); |
| 478 | init_waitqueue_head(&pva->mailbox_waitqueue); | 472 | init_waitqueue_head(&pva->mailbox_waitqueue); |
| 479 | mutex_init(&pva->mailbox_mutex); | 473 | mutex_init(&pva->mailbox_mutex); |
| 474 | mutex_init(&pva->ccq_mutex); | ||
| 480 | pva->submit_mode = PVA_SUBMIT_MODE_MAILBOX; | 475 | pva->submit_mode = PVA_SUBMIT_MODE_MAILBOX; |
| 481 | 476 | ||
| 482 | /* Map MMIO range to kernel space */ | 477 | /* Map MMIO range to kernel space */ |
| @@ -508,6 +503,8 @@ static int pva_probe(struct platform_device *pdev) | |||
| 508 | if (err < 0) | 503 | if (err < 0) |
| 509 | goto err_isr_init; | 504 | goto err_isr_init; |
| 510 | 505 | ||
| 506 | pva_abort_init(pva); | ||
| 507 | |||
| 511 | err = nvhost_syncpt_unit_interface_init(pdev); | 508 | err = nvhost_syncpt_unit_interface_init(pdev); |
| 512 | if (err) | 509 | if (err) |
| 513 | goto err_mss_init; | 510 | goto err_mss_init; |
diff --git a/drivers/video/tegra/host/pva/pva.h b/drivers/video/tegra/host/pva/pva.h index e1bdba1b2..1103513f1 100644 --- a/drivers/video/tegra/host/pva/pva.h +++ b/drivers/video/tegra/host/pva/pva.h | |||
| @@ -154,6 +154,8 @@ struct pva { | |||
| 154 | enum pva_mailbox_status mailbox_status; | 154 | enum pva_mailbox_status mailbox_status; |
| 155 | struct mutex mailbox_mutex; | 155 | struct mutex mailbox_mutex; |
| 156 | 156 | ||
| 157 | struct mutex ccq_mutex; | ||
| 158 | |||
| 157 | struct pva_crashdump_debugfs_entry debugfs_entry_r5; | 159 | struct pva_crashdump_debugfs_entry debugfs_entry_r5; |
| 158 | struct pva_crashdump_debugfs_entry debugfs_entry_vpu0; | 160 | struct pva_crashdump_debugfs_entry debugfs_entry_vpu0; |
| 159 | struct pva_crashdump_debugfs_entry debugfs_entry_vpu1; | 161 | struct pva_crashdump_debugfs_entry debugfs_entry_vpu1; |
| @@ -163,6 +165,9 @@ struct pva { | |||
| 163 | 165 | ||
| 164 | struct pva_trace_log pva_trace; | 166 | struct pva_trace_log pva_trace; |
| 165 | u32 submit_mode; | 167 | u32 submit_mode; |
| 168 | |||
| 169 | struct work_struct pva_abort_handler_work; | ||
| 170 | bool booted; | ||
| 166 | }; | 171 | }; |
| 167 | 172 | ||
| 168 | /** | 173 | /** |
| @@ -215,6 +220,7 @@ int pva_prepare_poweroff(struct platform_device *pdev); | |||
| 215 | * | 220 | * |
| 216 | */ | 221 | */ |
| 217 | int pva_register_isr(struct platform_device *dev); | 222 | int pva_register_isr(struct platform_device *dev); |
| 223 | |||
| 218 | /** | 224 | /** |
