mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
video: rockchip: mpp: Fix panic when mpp service is omit or disabled
[ 4.239358] Unable to handle kernel NULL pointer dereference at virtual address 00000050 [ 4.263110] pgd = (ptrval) [ 4.269464] [00000050] *pgd=00000000 [ 4.285610] Internal error: Oops: 5 [#1] PREEMPT SMP ARM [ 4.291283] Modules linked in: [ 4.294795] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.19.111 #1960 [ 4.301399] Hardware name: Generic DT based system [ 4.306660] PC is at mpp_set_grf+0x8/0x3c [ 4.311054] LR is at mpp_add_driver+0x24/0x44 [ 4.315713] pc : [<b03d7b44>] lr : [<b03d50d8>] psr: 20000153 [ 4.322250] sp : bf039ee8 ip : 00000d8c fp : bf7ffd80 [ 4.327740] r10: b0b3003c r9 : 00000007 r8 : 00000000 [ 4.333260] r7 : b0b15914 r6 : b0f21788 r5 : 00000006 r4 : b1022a2c [ 4.340094] r3 : 00000048 r2 : bf5d1e24 r1 : b0f21788 r0 : 00000048 [ 4.346947] Flags: nzCv IRQs on FIQs off Mode SVC_32 ISA ARM Segment user [ 4.354487] Control: 10c5387d Table: 6000406a DAC: 00000055 Change-Id: Idad72d462da59a8af53fd038ceda973da1f4139d Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com> Signed-off-by: Ding Wei <leo.ding@rock-chips.com>
This commit is contained in:
@@ -768,15 +768,13 @@ static int mpp_attach_service(struct mpp_dev *mpp, struct device *dev)
|
||||
goto err_put_pdev;
|
||||
}
|
||||
|
||||
device_lock(&pdev->dev);
|
||||
/* register current device to mpp service */
|
||||
mpp->srv->sub_devices[mpp->var->device_type] = mpp;
|
||||
/* set taskqueue which set in dtsi */
|
||||
mpp->queue = mpp->srv->task_queues[taskqueue_node];
|
||||
/* set resetgroup which set in dtsi */
|
||||
mpp->reset_group = mpp->srv->reset_groups[reset_group_node];
|
||||
mpp->srv->hw_support |= BIT(mpp->var->device_type);
|
||||
device_unlock(&pdev->dev);
|
||||
set_bit(mpp->var->device_type, &mpp->srv->hw_support);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -342,7 +342,7 @@ struct mpp_service {
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *debugfs;
|
||||
#endif
|
||||
u32 hw_support;
|
||||
unsigned long hw_support;
|
||||
atomic_t shutdown_request;
|
||||
/* follows for device probe */
|
||||
struct mpp_grf_info grf_infos[MPP_DRIVER_BUTT];
|
||||
|
||||
@@ -25,26 +25,18 @@
|
||||
#define MPP_CLASS_NAME "mpp_class"
|
||||
#define MPP_SERVICE_NAME "mpp_service"
|
||||
|
||||
#define MPP_REGISTER_GRF(np, X, x) {\
|
||||
#define MPP_REGISTER_DRIVER(srv, X, x) {\
|
||||
if (IS_ENABLED(CONFIG_ROCKCHIP_MPP_##X))\
|
||||
mpp_init_grf(np, &srv->grf_infos[MPP_DRIVER_##X], x);\
|
||||
}
|
||||
|
||||
#define MPP_REGISTER_DRIVER(X, x) {\
|
||||
if (IS_ENABLED(CONFIG_ROCKCHIP_MPP_##X))\
|
||||
mpp_add_driver(MPP_DRIVER_##X, &rockchip_##x##_driver);\
|
||||
mpp_add_driver(srv, MPP_DRIVER_##X, &rockchip_##x##_driver, "grf_"#x);\
|
||||
}
|
||||
|
||||
unsigned int mpp_dev_debug;
|
||||
module_param(mpp_dev_debug, uint, 0644);
|
||||
MODULE_PARM_DESC(mpp_dev_debug, "bit switch for mpp debug information");
|
||||
|
||||
static struct mpp_grf_info *mpp_grf_infos;
|
||||
static struct platform_driver **mpp_sub_drivers;
|
||||
|
||||
static int mpp_init_grf(struct device_node *np,
|
||||
struct mpp_grf_info *grf_info,
|
||||
const char *name)
|
||||
const char *grf_name)
|
||||
{
|
||||
int ret;
|
||||
int index;
|
||||
@@ -60,7 +52,7 @@ static int mpp_init_grf(struct device_node *np,
|
||||
if (ret)
|
||||
return -ENODATA;
|
||||
|
||||
index = of_property_match_string(np, "rockchip,grf-names", name);
|
||||
index = of_property_match_string(np, "rockchip,grf-names", grf_name);
|
||||
if (index < 0)
|
||||
return -ENODATA;
|
||||
|
||||
@@ -73,6 +65,39 @@ static int mpp_init_grf(struct device_node *np,
|
||||
grf_info->offset = grf_offset;
|
||||
grf_info->val = grf_value;
|
||||
|
||||
mpp_set_grf(grf_info);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpp_add_driver(struct mpp_service *srv,
|
||||
enum MPP_DRIVER_TYPE type,
|
||||
struct platform_driver *driver,
|
||||
const char *grf_name)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mpp_init_grf(srv->dev->of_node,
|
||||
&srv->grf_infos[type],
|
||||
grf_name);
|
||||
|
||||
ret = platform_driver_register(driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
srv->sub_drivers[type] = driver;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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]);
|
||||
srv->sub_drivers[i] = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -208,23 +233,24 @@ static int mpp_service_probe(struct platform_device *pdev)
|
||||
srv->reset_groups[i] = group;
|
||||
}
|
||||
}
|
||||
MPP_REGISTER_GRF(np, RKVDEC, "grf_rkvdec");
|
||||
MPP_REGISTER_GRF(np, RKVENC, "grf_rkvenc");
|
||||
MPP_REGISTER_GRF(np, VEPU1, "grf_vepu1");
|
||||
MPP_REGISTER_GRF(np, VDPU1, "grf_vdpu1");
|
||||
MPP_REGISTER_GRF(np, VEPU2, "grf_vepu2");
|
||||
MPP_REGISTER_GRF(np, VDPU2, "grf_vdpu2");
|
||||
MPP_REGISTER_GRF(np, VEPU22, "grf_vepu22");
|
||||
|
||||
mpp_grf_infos = srv->grf_infos;
|
||||
|
||||
ret = mpp_register_service(srv, MPP_SERVICE_NAME);
|
||||
if (ret) {
|
||||
dev_err(dev, "register %s device\n", MPP_SERVICE_NAME);
|
||||
goto fail_register;
|
||||
}
|
||||
mpp_sub_drivers = srv->sub_drivers;
|
||||
mpp_debugfs_init(srv);
|
||||
|
||||
/* register sub drivers */
|
||||
MPP_REGISTER_DRIVER(srv, RKVDEC, rkvdec);
|
||||
MPP_REGISTER_DRIVER(srv, RKVENC, rkvenc);
|
||||
MPP_REGISTER_DRIVER(srv, VDPU1, vdpu1);
|
||||
MPP_REGISTER_DRIVER(srv, VEPU1, vepu1);
|
||||
MPP_REGISTER_DRIVER(srv, VDPU2, vdpu2);
|
||||
MPP_REGISTER_DRIVER(srv, VEPU2, vepu2);
|
||||
MPP_REGISTER_DRIVER(srv, VEPU22, vepu22);
|
||||
MPP_REGISTER_DRIVER(srv, IEP2, iep2);
|
||||
|
||||
dev_info(dev, "probe success\n");
|
||||
|
||||
return 0;
|
||||
@@ -239,9 +265,14 @@ static int mpp_service_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mpp_service *srv = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
dev_info(dev, "remove device\n");
|
||||
|
||||
/* remove sub drivers */
|
||||
for (i = 0; i < MPP_DRIVER_BUTT; i++)
|
||||
mpp_remove_driver(srv, i);
|
||||
|
||||
mpp_remove_service(srv);
|
||||
class_destroy(srv->cls);
|
||||
mpp_debugfs_remove(srv);
|
||||
@@ -265,65 +296,7 @@ static struct platform_driver mpp_service_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
static int mpp_add_driver(enum MPP_DRIVER_TYPE type,
|
||||
struct platform_driver *driver)
|
||||
{
|
||||
int ret;
|
||||
|
||||
mpp_set_grf(&mpp_grf_infos[type]);
|
||||
|
||||
ret = platform_driver_register(driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mpp_sub_drivers[type] = driver;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpp_remove_driver(int i, struct platform_driver *driver)
|
||||
{
|
||||
if (driver) {
|
||||
mpp_set_grf(&mpp_grf_infos[i]);
|
||||
platform_driver_unregister(driver);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init mpp_service_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = platform_driver_register(&mpp_service_driver);
|
||||
if (ret) {
|
||||
pr_err("Mpp service device register failed (%d).\n", ret);
|
||||
return ret;
|
||||
}
|
||||
MPP_REGISTER_DRIVER(RKVDEC, rkvdec);
|
||||
MPP_REGISTER_DRIVER(RKVENC, rkvenc);
|
||||
MPP_REGISTER_DRIVER(VDPU1, vdpu1);
|
||||
MPP_REGISTER_DRIVER(VEPU1, vepu1);
|
||||
MPP_REGISTER_DRIVER(VDPU2, vdpu2);
|
||||
MPP_REGISTER_DRIVER(VEPU2, vepu2);
|
||||
MPP_REGISTER_DRIVER(VEPU22, vepu22);
|
||||
MPP_REGISTER_DRIVER(IEP2, iep2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit mpp_service_exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MPP_DRIVER_BUTT; i++)
|
||||
mpp_remove_driver(i, mpp_sub_drivers[i]);
|
||||
|
||||
platform_driver_unregister(&mpp_service_driver);
|
||||
}
|
||||
|
||||
module_init(mpp_service_init);
|
||||
module_exit(mpp_service_exit);
|
||||
module_platform_driver(mpp_service_driver);
|
||||
|
||||
MODULE_LICENSE("Dual MIT/GPL");
|
||||
MODULE_VERSION("1.0.build.201911131848");
|
||||
|
||||
@@ -825,7 +825,7 @@ static int vdpu_probe(struct platform_device *pdev)
|
||||
|
||||
if (mpp->var->device_type == MPP_DEVICE_VDPU1) {
|
||||
mpp->srv->sub_devices[MPP_DEVICE_VDPU1_PP] = mpp;
|
||||
mpp->srv->hw_support |= BIT(MPP_DEVICE_VDPU1_PP);
|
||||
set_bit(MPP_DEVICE_VDPU1_PP, &mpp->srv->hw_support);
|
||||
}
|
||||
|
||||
mpp->session_max_buffers = VDPU1_SESSION_MAX_BUFFERS;
|
||||
|
||||
@@ -723,7 +723,7 @@ static int vdpu_probe(struct platform_device *pdev)
|
||||
|
||||
if (mpp->var->device_type == MPP_DEVICE_VDPU2) {
|
||||
mpp->srv->sub_devices[MPP_DEVICE_VDPU2_PP] = mpp;
|
||||
mpp->srv->hw_support |= BIT(MPP_DEVICE_VDPU2_PP);
|
||||
set_bit(MPP_DEVICE_VDPU2_PP, &mpp->srv->hw_support);
|
||||
}
|
||||
|
||||
mpp->session_max_buffers = VDPU2_SESSION_MAX_BUFFERS;
|
||||
|
||||
Reference in New Issue
Block a user