video: rockchip: mpp: Improve the exit process of the av1

Signed-off-by: Yandong Lin <yandong.lin@rock-chips.com>
Change-Id: Idbb73bf2b08dc879a7776180420060b9b740a31e
Signed-off-by: Simon Xue <xxm@rock-chips.com>
This commit is contained in:
Yandong Lin
2022-03-17 09:51:43 +08:00
committed by Tao Huang
parent 554bc72503
commit cbfd698de1
4 changed files with 72 additions and 8 deletions

View File

@@ -7,6 +7,8 @@
*
*/
#define pr_fmt(fmt) "mpp_av1dec: " fmt
#include <asm/cacheflush.h>
#include <linux/clk.h>
#include <linux/clk/clk-conf.h>
@@ -16,8 +18,9 @@
#include <linux/module.h>
#include <linux/types.h>
#include <linux/of_platform.h>
#include <linux/pm_domain.h>
#include <linux/clk/clk-conf.h>
#include <linux/pm_runtime.h>
#include <linux/pm_domain.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/regmap.h>
@@ -28,7 +31,7 @@
#include "mpp_common.h"
#include "mpp_iommu.h"
#define AV1DEC_DRIVER_NAME "mpp_av1dec"
#define AV1DEC_DRIVER_NAME "mpp_av1dec"
#define AV1DEC_SESSION_MAX_BUFFERS 40
@@ -1098,7 +1101,7 @@ static int av1_of_device_add(struct platform_device *ofdev)
return device_add(&ofdev->dev);
}
struct platform_device *av1dec_device_create(void)
static struct platform_device *av1dec_device_create(void)
{
int ret = -ENODEV;
struct device_node *root, *child;
@@ -1134,6 +1137,35 @@ struct platform_device *av1dec_device_create(void)
return ERR_PTR(ret);
}
static void av1dec_device_destory(void)
{
struct platform_device *pdev;
struct device *dev;
dev = bus_find_device_by_name(&av1dec_bus, NULL, "av1d-master");
pdev = dev ? to_platform_device(dev) : NULL;
if (!pdev) {
pr_err("cannot find platform device\n");
return;
}
pr_info("destroy device %s\n", dev_name(&pdev->dev));
platform_device_del(pdev);
platform_device_put(pdev);
}
void av1dec_driver_unregister(struct platform_driver *drv)
{
/* 1. unregister av1 driver */
driver_unregister(&drv->driver);
/* 2. release device */
av1dec_device_destory();
/* 3. unregister iommu driver */
platform_driver_unregister(&rockchip_av1_iommu_driver);
/* 4. unregister bus */
bus_unregister(&av1dec_bus);
}
int av1dec_driver_register(struct platform_driver *drv)
{
int ret;

View File

@@ -837,8 +837,8 @@ extern struct platform_driver rockchip_rkvenc2_driver;
extern struct platform_driver rockchip_av1dec_driver;
extern struct platform_driver rockchip_av1_iommu_driver;
extern struct platform_device *av1dec_device_create(void);
extern int av1dec_driver_register(struct platform_driver *drv);
extern void av1dec_driver_unregister(struct platform_driver *drv);
extern struct bus_type av1dec_bus;
#endif

View File

@@ -713,6 +713,10 @@ static struct iommu_device *av1_iommu_probe_device(struct device *dev)
pr_info("%s,%d, consumer : %s, supplier : %s\n",
__func__, __LINE__, dev_name(dev), dev_name(iommu->dev));
/*
* link will free by platform_device_del(master) via
* BUS_NOTIFY_REMOVED_DEVICE
*/
data->link = device_link_add(dev, iommu->dev,
DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME);
@@ -729,9 +733,10 @@ static struct iommu_device *av1_iommu_probe_device(struct device *dev)
static void av1_iommu_release_device(struct device *dev)
{
struct av1_iommudata *data = dev_iommu_priv_get(dev);
const struct iommu_ops *ops = dev->bus->iommu_ops;
device_link_del(data->link);
/* hack for rmmod */
__module_get(ops->owner);
}
static struct iommu_group *av1_iommu_device_group(struct device *dev)
@@ -765,6 +770,14 @@ static int av1_iommu_of_xlate(struct device *dev,
return 0;
}
static void av1_iommu_probe_finalize(struct device *dev)
{
const struct iommu_ops *ops = dev->bus->iommu_ops;
/* hack for rmmod */
module_put(ops->owner);
}
static struct iommu_ops av1_iommu_ops = {
.domain_alloc = av1_iommu_domain_alloc,
.domain_free = av1_iommu_domain_free,
@@ -780,6 +793,7 @@ static struct iommu_ops av1_iommu_ops = {
.device_group = av1_iommu_device_group,
.pgsize_bitmap = AV1_IOMMU_PGSIZE_BITMAP,
.of_xlate = av1_iommu_of_xlate,
.probe_finalize = av1_iommu_probe_finalize,
};
static const struct of_device_id av1_iommu_dt_ids[] = {
@@ -891,6 +905,17 @@ err_unprepare_clocks:
return err;
}
static int av1_iommu_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct av1_iommu *iommu = platform_get_drvdata(pdev);
iommu_device_unregister(&iommu->iommu);
iommu_device_sysfs_remove(&iommu->iommu);
pm_runtime_disable(dev);
return 0;
}
static void av1_iommu_shutdown(struct platform_device *pdev)
{
struct av1_iommu *iommu = platform_get_drvdata(pdev);
@@ -934,6 +959,7 @@ static const struct dev_pm_ops av1_iommu_pm_ops = {
struct platform_driver rockchip_av1_iommu_driver = {
.probe = av1_iommu_probe,
.remove = av1_iommu_remove,
.shutdown = av1_iommu_shutdown,
.driver = {
.name = "av1_iommu",

View File

@@ -113,8 +113,14 @@ static int mpp_add_driver(struct mpp_service *srv,
static int mpp_remove_driver(struct mpp_service *srv, int i)
{
if (srv && srv->sub_drivers[i]) {
mpp_set_grf(&srv->grf_infos[i]);
platform_driver_unregister(srv->sub_drivers[i]);
if (i != MPP_DRIVER_AV1DEC) {
mpp_set_grf(&srv->grf_infos[i]);
platform_driver_unregister(srv->sub_drivers[i]);
}
#if IS_ENABLED(CONFIG_ROCKCHIP_MPP_AV1DEC)
else
av1dec_driver_unregister(srv->sub_drivers[i]);
#endif
srv->sub_drivers[i] = NULL;
}