psc: fix oops when rmmod and clean up the driver

This patch fixes kernel Oops due to freeing psc_debug device multiple
times.

bug 4699764

Change-Id: I0a57317b1b064c08d657752a726d855533ec4d3c
Signed-off-by: David Pu <dpu@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3166051
Tested-by: Liang Cheng (SW) <licheng@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
David Pu
2024-06-14 17:04:58 -07:00
committed by mobile promotions
parent edbb5317f8
commit a5b6d4a5b6

View File

@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2020-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. // Copyright (c) 2020-2024, NVIDIA Corporation. All rights reserved.
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/types.h> #include <linux/types.h>
@@ -63,14 +63,19 @@ struct psc_debug_dev {
u8 rx_msg[MBOX_MSG_LEN]; u8 rx_msg[MBOX_MSG_LEN];
struct mbox_controller *mbox; /* our mbox controller */ struct mbox_controller *mbox; /* our mbox controller */
bool is_cfg_inited; /* did we initialize SIDTABLE, etc? */ bool is_cfg_inited; /* did we initialize SIDTABLE, etc? */
}; };
static struct psc_debug_dev psc_debug; enum {
static struct psc_debug_dev oesp_debug; PSC_PSC = 0,
static struct psc_debug_dev sb_debug; PSC_OESP,
static struct dentry *debugfs_root; PSC_SB,
PSC_NUM
};
static struct psc_debug_dev debug_devs[PSC_NUM];
static struct dentry *debugfs[PSC_NUM];
#define NV(x) "nvidia," #x #define NV(x) "nvidia," #x
static int static int
@@ -90,7 +95,6 @@ setup_extcfg(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
dev_info(&pdev->dev, "ext_cfg base:%p\n", base); dev_info(&pdev->dev, "ext_cfg base:%p\n", base);
if (!device_property_read_u8_array(&pdev->dev, NV(sidtable), if (!device_property_read_u8_array(&pdev->dev, NV(sidtable),
(u8 *)&value, sizeof(value))) { (u8 *)&value, sizeof(value))) {
dev_dbg(&pdev->dev, "sidtable:%08x\n", value); dev_dbg(&pdev->dev, "sidtable:%08x\n", value);
@@ -372,22 +376,40 @@ static void psc_chan_rx_callback(struct mbox_client *c, void *msg)
complete(&dbg->rx_complete); complete(&dbg->rx_complete);
} }
int psc_debugfs_create(struct platform_device *pdev, struct mbox_controller *mbox) static const char *to_instance(struct platform_device *pdev, u32 *id)
{ {
struct psc_debug_dev *dbg = &psc_debug;
struct device *dev = &pdev->dev;
const char *psc_name = NULL; const char *psc_name = NULL;
struct device *dev = &pdev->dev;
/* Get the cpu name from dtb and use for debug node*/ /* Get the cpu name from dtb and use for debug node*/
if (device_property_read_string(dev, "nvidia,cpu-name", &psc_name) != 0) { if (device_property_read_string(dev, "nvidia,cpu-name", &psc_name) != 0) {
return NULL;
}
*id = PSC_PSC;
if (strcmp(psc_name, "oesp") == 0)
*id = PSC_OESP;
else if (strcmp(psc_name, "sb") == 0)
*id = PSC_SB;
return psc_name;
}
int psc_debugfs_create(struct platform_device *pdev, struct mbox_controller *mbox)
{
struct device *dev = &pdev->dev;
struct dentry *debugfs_root = NULL;
struct psc_debug_dev *dbg;
u32 id = 0;
const char *psc_name = to_instance(pdev, &id);
if (psc_name == NULL) {
dev_err(dev, "Could not find property nvidia,cpu-name in device tree\n"); dev_err(dev, "Could not find property nvidia,cpu-name in device tree\n");
return -ENODEV; return -ENODEV;
} }
if (strcmp(psc_name, "oesp") == 0) dbg = &debug_devs[id];
dbg = &oesp_debug;
else if (strcmp(psc_name, "sb") == 0)
dbg = &sb_debug;
if (!debugfs_initialized()) { if (!debugfs_initialized()) {
dev_err(dev, "debugfs is not initialized\n"); dev_err(dev, "debugfs is not initialized\n");
@@ -395,6 +417,7 @@ int psc_debugfs_create(struct platform_device *pdev, struct mbox_controller *mbo
} }
debugfs_root = debugfs_create_dir(psc_name, NULL); debugfs_root = debugfs_create_dir(psc_name, NULL);
debugfs[id] = debugfs_root;
if (debugfs_root == NULL) { if (debugfs_root == NULL) {
dev_err(dev, "failed to create psc debugfs\n"); dev_err(dev, "failed to create psc debugfs\n");
@@ -424,8 +447,19 @@ int psc_debugfs_create(struct platform_device *pdev, struct mbox_controller *mbo
void psc_debugfs_remove(struct platform_device *pdev) void psc_debugfs_remove(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev;
struct psc_debug_dev *dbg = NULL;
u32 id = 0;
if (to_instance(pdev, &id) == NULL) {
dev_err(dev, "can not find psc_debug device\n");
return;
}
dbg = &debug_devs[id];
dev_dbg(&pdev->dev, "%s\n", __func__); dev_dbg(&pdev->dev, "%s\n", __func__);
mutex_destroy(&psc_debug.lock); mutex_destroy(&dbg->lock);
debugfs_remove_recursive(debugfs_root); debugfs_remove_recursive(debugfs[id]);
} }