From ad8058fce9c787d2de01e3830f43864fda82a5a0 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 10 May 2022 16:11:19 +0100 Subject: [PATCH] gpu: host1x-nvhost: Fix client unloading After unloading the NVDLA driver and then reloading the NVDLA, the kernel is crashing. The host1x-nvhost driver is missing a call to class_destroy() in nvhost_client_device_release() which gets called when removing the DLA driver and this is preventing the DLA driver from creating the class again when reloading. The crash then occurs because when the driver is reloaded, creating the class for the DLA driver fails and then the host1x-nvhost driver incorrectly calls device_destroy() even though the device has not been created yet. Fix this by ensuring the class_destroy() is called by nvhost_client_device_release() and in the necessary error paths and then remove the call to device_destroy(). Finally, replace request_irq() with devm_request_irq() to ensure that the interrupts are also released as necessary on removal. Bug 3641820 Change-Id: Ia328bf63d528e8c31bff1d7b3ac0d5dddc22f1f5 Signed-off-by: Jon Hunter Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2710546 Reviewed-by: svcacv Reviewed-by: Mikko Perttunen GVS: Gerrit_Virtual_Submit --- drivers/gpu/host1x-nvhost/nvhost.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/host1x-nvhost/nvhost.c b/drivers/gpu/host1x-nvhost/nvhost.c index 609124a4..44c2a289 100644 --- a/drivers/gpu/host1x-nvhost/nvhost.c +++ b/drivers/gpu/host1x-nvhost/nvhost.c @@ -106,6 +106,7 @@ static struct device *nvhost_client_device_create(struct platform_device *pdev, err = cdev_add(cdev, devno, 1); if (err < 0) { dev_err(&pdev->dev, "failed to add cdev\n"); + class_destroy(pdata->nvhost_class); return ERR_PTR(err); } @@ -115,6 +116,7 @@ static struct device *nvhost_client_device_create(struct platform_device *pdev, if (IS_ERR(dev)) { dev_err(&pdev->dev, "failed to create %s device\n", cdev_name); + class_destroy(pdata->nvhost_class); cdev_del(cdev); } @@ -156,19 +158,12 @@ int nvhost_client_device_init(struct platform_device *pdev) pdata->ctrl_node = nvhost_client_device_create(pdev, &pdata->ctrl_cdev, "ctrl-", devno, pdata->ctrl_ops); - if (IS_ERR(pdata->ctrl_node)) { - err = PTR_ERR(pdata->ctrl_node); - goto destroy; - } + if (IS_ERR(pdata->ctrl_node)) + return PTR_ERR(pdata->ctrl_node); pdata->cdev_region = devno; return 0; - -destroy: - device_destroy(pdata->nvhost_class, pdata->ctrl_cdev.dev); - - return err; } EXPORT_SYMBOL(nvhost_client_device_init); @@ -179,6 +174,7 @@ int nvhost_client_device_release(struct platform_device *pdev) if (!IS_ERR_OR_NULL(pdata->ctrl_node)) { device_destroy(pdata->nvhost_class, pdata->ctrl_cdev.dev); cdev_del(&pdata->ctrl_cdev); + class_destroy(pdata->nvhost_class); } unregister_chrdev_region(pdata->cdev_region, NVHOST_NUM_CDEV); @@ -418,7 +414,8 @@ int flcn_intr_init(struct platform_device *pdev) } spin_lock_init(&pdata->mirq_lock); - ret = request_irq(pdata->irq, flcn_isr, 0, dev_name(&pdev->dev), pdev); + ret = devm_request_irq(&pdev->dev, pdata->irq, flcn_isr, 0, + dev_name(&pdev->dev), pdev); if (ret) { dev_err(&pdev->dev, "failed to request irq. err %d\n", ret); return ret;