video: tegra: host: nvdla: fix fw reloading

- Engine hang like issue causes device power reference
  count to go out of sync
- So forcefully put device into idle before firmware reload
- Reset device after firmware reload to make sure engine
  in clean state

Jira DLA-3147

Change-Id: I22c825065cb9157c85b8fd5ad4fcaac764383a9f
Signed-off-by: Shridhar Rasal <srasal@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2329686
Reviewed-by: automaticguardword <automaticguardword@nvidia.com>
Reviewed-by: Ken Adams <kadams@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Shridhar Rasal
2020-04-14 19:21:51 +05:30
committed by Laxman Dewangan
parent e793ebb2f8
commit e5d321cc10

View File

@@ -1,7 +1,7 @@
/*
* NVDLA debug utils
*
* Copyright (c) 2016 - 2018, NVIDIA Corporation. All rights reserved.
* Copyright (c) 2016 - 2020, NVIDIA Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -26,9 +26,11 @@
#include <linux/uaccess.h>
#include <soc/tegra/fuse.h>
#include <soc/tegra/chip-id.h>
#include <linux/delay.h>
#include "nvdla/nvdla.h"
#include "nvdla_debug.h"
#include "nvhost_acm.h"
/*
* Header in ring buffer consist (start, end) two uint32_t values.
@@ -494,6 +496,8 @@ static ssize_t debug_dla_fw_reload_set(struct file *file,
struct nvdla_device *nvdla_dev;
struct platform_device *pdev;
long val;
int ref_cnt;
unsigned long end_jiffies;
if (!p)
return -EFAULT;
@@ -511,12 +515,32 @@ static ssize_t debug_dla_fw_reload_set(struct file *file,
if (!val)
return count; /* "0" does nothing */
nvdla_dbg_info(pdev, "firmware reload requested.\n");
/* check current power ref count and make forced idle to
* suspend.
*/
ref_cnt = atomic_read(&pdev->dev.power.usage_count);
nvhost_module_idle_mult(pdev, ref_cnt);
/* check and wait until module is idle (with a timeout) */
end_jiffies = jiffies + msecs_to_jiffies(2000);
do {
msleep(1);
ref_cnt = atomic_read(&pdev->dev.power.usage_count);
} while (ref_cnt != 0 && time_before(jiffies, end_jiffies));
if (ref_cnt != 0)
return -EBUSY;
nvdla_dbg_info(pdev, "firmware reload requesting..\n");
err = flcn_reload_fw(pdev);
if (err)
return err; /* propagate firmware reload errors */
/* make sure device in clean state by reset */
nvhost_module_reset(pdev, true);
return count;
}