diff --git a/drivers/net/wwan/iosm/iosm_ipc_debugfs.c b/drivers/net/wwan/iosm/iosm_ipc_debugfs.c index f2f57751a7d21..e916139b8cd45 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_debugfs.c +++ b/drivers/net/wwan/iosm/iosm_ipc_debugfs.c @@ -12,10 +12,10 @@ void ipc_debugfs_init(struct iosm_imem *ipc_imem) { - struct dentry *debugfs_pdev = wwan_get_debugfs_dir(ipc_imem->dev); + ipc_imem->debugfs_wwan_dir = wwan_get_debugfs_dir(ipc_imem->dev); ipc_imem->debugfs_dir = debugfs_create_dir(KBUILD_MODNAME, - debugfs_pdev); + ipc_imem->debugfs_wwan_dir); ipc_imem->trace = ipc_trace_init(ipc_imem); if (!ipc_imem->trace) @@ -26,4 +26,5 @@ void ipc_debugfs_deinit(struct iosm_imem *ipc_imem) { ipc_trace_deinit(ipc_imem->trace); debugfs_remove_recursive(ipc_imem->debugfs_dir); + wwan_put_debugfs_dir(ipc_imem->debugfs_wwan_dir); } diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.h b/drivers/net/wwan/iosm/iosm_ipc_imem.h index 5682e8d6be7be..e700dc8bfe0a9 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem.h +++ b/drivers/net/wwan/iosm/iosm_ipc_imem.h @@ -341,6 +341,7 @@ enum ipc_phase { * @ev_mux_net_transmit_pending:0 means inform the IPC tasklet to pass * @reset_det_n: Reset detect flag * @pcie_wake_n: Pcie wake flag + * @debugfs_wwan_dir: WWAN Debug FS directory entry * @debugfs_dir: Debug FS directory for driver-specific entries */ struct iosm_imem { @@ -384,6 +385,7 @@ struct iosm_imem { reset_det_n:1, pcie_wake_n:1; #ifdef CONFIG_WWAN_DEBUGFS + struct dentry *debugfs_wwan_dir; struct dentry *debugfs_dir; #endif }; diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c index 1508dc2a497b2..b8c7843730edf 100644 --- a/drivers/net/wwan/wwan_core.c +++ b/drivers/net/wwan/wwan_core.c @@ -160,6 +160,42 @@ struct dentry *wwan_get_debugfs_dir(struct device *parent) return wwandev->debugfs_dir; } EXPORT_SYMBOL_GPL(wwan_get_debugfs_dir); + +static int wwan_dev_debugfs_match(struct device *dev, const void *dir) +{ + struct wwan_device *wwandev; + + if (dev->type != &wwan_dev_type) + return 0; + + wwandev = to_wwan_dev(dev); + + return wwandev->debugfs_dir == dir; +} + +static struct wwan_device *wwan_dev_get_by_debugfs(struct dentry *dir) +{ + struct device *dev; + + dev = class_find_device(wwan_class, NULL, dir, wwan_dev_debugfs_match); + if (!dev) + return ERR_PTR(-ENODEV); + + return to_wwan_dev(dev); +} + +void wwan_put_debugfs_dir(struct dentry *dir) +{ + struct wwan_device *wwandev = wwan_dev_get_by_debugfs(dir); + + if (WARN_ON(IS_ERR(wwandev))) + return; + + /* wwan_dev_get_by_debugfs() also got a reference */ + put_device(&wwandev->dev); + put_device(&wwandev->dev); +} +EXPORT_SYMBOL_GPL(wwan_put_debugfs_dir); #endif /* This function allocates and registers a new WWAN device OR if a WWAN device diff --git a/include/linux/wwan.h b/include/linux/wwan.h index afb3334ec8c54..5ce2acf444fb3 100644 --- a/include/linux/wwan.h +++ b/include/linux/wwan.h @@ -174,11 +174,13 @@ void wwan_unregister_ops(struct device *parent); #ifdef CONFIG_WWAN_DEBUGFS struct dentry *wwan_get_debugfs_dir(struct device *parent); +void wwan_put_debugfs_dir(struct dentry *dir); #else static inline struct dentry *wwan_get_debugfs_dir(struct device *parent) { return ERR_PTR(-ENODEV); } +static inline void wwan_put_debugfs_dir(struct dentry *dir) {} #endif #endif /* __WWAN_H */