msm_cvp_debug.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/debugfs.h>
  6. #include "msm_cvp_debug.h"
  7. #include "msm_cvp_common.h"
  8. #include "cvp_core_hfi.h"
  9. #include "cvp_hfi_api.h"
  10. #include "msm_cvp_dsp.h"
  11. #define CREATE_TRACE_POINTS
  12. #define MAX_SSR_STRING_LEN 10
  13. int msm_cvp_debug = CVP_ERR | CVP_WARN | CVP_FW;
  14. EXPORT_SYMBOL(msm_cvp_debug);
  15. int msm_cvp_debug_out = CVP_OUT_PRINTK;
  16. EXPORT_SYMBOL(msm_cvp_debug_out);
  17. int msm_cvp_fw_debug = 0x18;
  18. int msm_cvp_fw_debug_mode = 1;
  19. int msm_cvp_fw_low_power_mode = 1;
  20. bool msm_cvp_fw_coverage = !true;
  21. bool msm_cvp_cacheop_enabled = true;
  22. bool msm_cvp_thermal_mitigation_disabled = !true;
  23. bool msm_cvp_cacheop_disabled = !true;
  24. int msm_cvp_clock_voting = !1;
  25. bool msm_cvp_syscache_disable = !true;
  26. bool msm_cvp_dsp_disable = !true;
  27. #ifdef CVP_MMRM_ENABLED
  28. bool msm_cvp_mmrm_enabled = true;
  29. #else
  30. bool msm_cvp_mmrm_enabled = !true;
  31. #endif
  32. bool msm_cvp_dcvs_disable = !true;
  33. int msm_cvp_minidump_enable = !1;
  34. #define MAX_DBG_BUF_SIZE 4096
  35. struct cvp_core_inst_pair {
  36. struct msm_cvp_core *core;
  37. struct msm_cvp_inst *inst;
  38. };
  39. static int core_info_open(struct inode *inode, struct file *file)
  40. {
  41. file->private_data = inode->i_private;
  42. dprintk(CVP_INFO, "%s: Enter\n", __func__);
  43. return 0;
  44. }
  45. static u32 write_str(char *buffer,
  46. size_t size, const char *fmt, ...)
  47. {
  48. va_list args;
  49. u32 len;
  50. va_start(args, fmt);
  51. len = vscnprintf(buffer, size, fmt, args);
  52. va_end(args);
  53. return len;
  54. }
  55. static ssize_t core_info_read(struct file *file, char __user *buf,
  56. size_t count, loff_t *ppos)
  57. {
  58. struct msm_cvp_core *core = file->private_data;
  59. struct cvp_hfi_device *hdev;
  60. struct cvp_hal_fw_info fw_info = { {0} };
  61. char *dbuf, *cur, *end;
  62. int i = 0, rc = 0;
  63. ssize_t len = 0;
  64. if (!core || !core->device) {
  65. dprintk(CVP_ERR, "Invalid params, core: %pK\n", core);
  66. return 0;
  67. }
  68. dbuf = kzalloc(MAX_DBG_BUF_SIZE, GFP_KERNEL);
  69. if (!dbuf) {
  70. dprintk(CVP_ERR, "%s: Allocation failed!\n", __func__);
  71. return -ENOMEM;
  72. }
  73. cur = dbuf;
  74. end = cur + MAX_DBG_BUF_SIZE;
  75. hdev = core->device;
  76. cur += write_str(cur, end - cur, "===============================\n");
  77. cur += write_str(cur, end - cur, "CORE %d: %pK\n", core->id, core);
  78. cur += write_str(cur, end - cur, "===============================\n");
  79. cur += write_str(cur, end - cur, "Core state: %d\n", core->state);
  80. rc = call_hfi_op(hdev, get_fw_info, hdev->hfi_device_data, &fw_info);
  81. if (rc) {
  82. dprintk(CVP_WARN, "Failed to read FW info\n");
  83. goto err_fw_info;
  84. }
  85. cur += write_str(cur, end - cur,
  86. "FW version : %s\n", &fw_info.version);
  87. cur += write_str(cur, end - cur,
  88. "base addr: 0x%x\n", fw_info.base_addr);
  89. cur += write_str(cur, end - cur,
  90. "register_base: 0x%x\n", fw_info.register_base);
  91. cur += write_str(cur, end - cur,
  92. "register_size: %u\n", fw_info.register_size);
  93. cur += write_str(cur, end - cur, "irq: %u\n", fw_info.irq);
  94. err_fw_info:
  95. for (i = SYS_MSG_START; i < SYS_MSG_END; i++) {
  96. cur += write_str(cur, end - cur, "completions[%d]: %s\n", i,
  97. completion_done(&core->completions[SYS_MSG_INDEX(i)]) ?
  98. "pending" : "done");
  99. }
  100. len = simple_read_from_buffer(buf, count, ppos,
  101. dbuf, cur - dbuf);
  102. kfree(dbuf);
  103. return len;
  104. }
  105. static const struct file_operations core_info_fops = {
  106. .open = core_info_open,
  107. .read = core_info_read,
  108. };
  109. static int trigger_ssr_open(struct inode *inode, struct file *file)
  110. {
  111. file->private_data = inode->i_private;
  112. dprintk(CVP_INFO, "%s: Enter\n", __func__);
  113. return 0;
  114. }
  115. static ssize_t trigger_ssr_write(struct file *filp, const char __user *buf,
  116. size_t count, loff_t *ppos)
  117. {
  118. unsigned long ssr_trigger_val = 0;
  119. int rc = 0;
  120. struct msm_cvp_core *core = filp->private_data;
  121. size_t size = MAX_SSR_STRING_LEN;
  122. char kbuf[MAX_SSR_STRING_LEN + 1] = {0};
  123. if (!buf)
  124. return -EINVAL;
  125. if (!count)
  126. goto exit;
  127. if (count < size)
  128. size = count;
  129. if (copy_from_user(kbuf, buf, size)) {
  130. dprintk(CVP_WARN, "%s User memory fault\n", __func__);
  131. rc = -EFAULT;
  132. goto exit;
  133. }
  134. rc = kstrtoul(kbuf, 0, &ssr_trigger_val);
  135. if (rc) {
  136. dprintk(CVP_WARN, "returning error err %d\n", rc);
  137. rc = -EINVAL;
  138. } else {
  139. msm_cvp_trigger_ssr(core, ssr_trigger_val);
  140. rc = count;
  141. }
  142. exit:
  143. return rc;
  144. }
  145. static const struct file_operations ssr_fops = {
  146. .open = trigger_ssr_open,
  147. .write = trigger_ssr_write,
  148. };
  149. static int cvp_power_get(void *data, u64 *val)
  150. {
  151. struct cvp_hfi_device *hfi_ops;
  152. struct msm_cvp_core *core;
  153. struct iris_hfi_device *hfi_device;
  154. core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
  155. if (!core)
  156. return 0;
  157. hfi_ops = core->device;
  158. if (!hfi_ops)
  159. return 0;
  160. hfi_device = hfi_ops->hfi_device_data;
  161. if (!hfi_device)
  162. return 0;
  163. *val = hfi_device->power_enabled;
  164. return 0;
  165. }
  166. #define MIN_PC_INTERVAL 1000
  167. #define MAX_PC_INTERVAL 1000000
  168. static int cvp_power_set(void *data, u64 val)
  169. {
  170. struct cvp_hfi_device *hfi_ops;
  171. struct msm_cvp_core *core;
  172. struct iris_hfi_device *hfi_device;
  173. int rc = 0;
  174. core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
  175. if (!core)
  176. return -EINVAL;
  177. hfi_ops = core->device;
  178. if (!hfi_ops)
  179. return -EINVAL;
  180. hfi_device = hfi_ops->hfi_device_data;
  181. if (!hfi_device)
  182. return -EINVAL;
  183. if (val >= MAX_PC_INTERVAL) {
  184. hfi_device->res->sw_power_collapsible = 0;
  185. } else if (val > MIN_PC_INTERVAL) {
  186. hfi_device->res->sw_power_collapsible = 1;
  187. hfi_device->res->msm_cvp_pwr_collapse_delay =
  188. (unsigned int)val;
  189. }
  190. if (core->state == CVP_CORE_UNINIT)
  191. return -EINVAL;
  192. if (val > 0) {
  193. rc = call_hfi_op(hfi_ops, resume, hfi_ops->hfi_device_data);
  194. if (rc)
  195. dprintk(CVP_ERR, "debugfs fail to power on cvp\n");
  196. }
  197. return rc;
  198. }
  199. DEFINE_DEBUGFS_ATTRIBUTE(cvp_pwr_fops, cvp_power_get, cvp_power_set, "%llu\n");
  200. struct dentry *msm_cvp_debugfs_init_drv(void)
  201. {
  202. struct dentry *dir = NULL;
  203. dir = debugfs_create_dir("msm_cvp", NULL);
  204. if (IS_ERR_OR_NULL(dir)) {
  205. dir = NULL;
  206. goto failed_create_dir;
  207. }
  208. debugfs_create_x32("debug_level", 0644, dir, &msm_cvp_debug);
  209. debugfs_create_x32("fw_level", 0644, dir, &msm_cvp_fw_debug);
  210. debugfs_create_u32("fw_debug_mode", 0644, dir, &msm_cvp_fw_debug_mode);
  211. debugfs_create_u32("fw_low_power_mode", 0644, dir,
  212. &msm_cvp_fw_low_power_mode);
  213. debugfs_create_u32("debug_output", 0644, dir, &msm_cvp_debug_out);
  214. debugfs_create_u32("minidump_enable", 0644, dir,
  215. &msm_cvp_minidump_enable);
  216. debugfs_create_bool("fw_coverage", 0644, dir, &msm_cvp_fw_coverage);
  217. debugfs_create_bool("disable_thermal_mitigation", 0644, dir,
  218. &msm_cvp_thermal_mitigation_disabled);
  219. debugfs_create_bool("enable_cacheop", 0644, dir,
  220. &msm_cvp_cacheop_enabled);
  221. debugfs_create_bool("disable_cvp_syscache", 0644, dir,
  222. &msm_cvp_syscache_disable);
  223. debugfs_create_bool("disable_dcvs", 0644, dir,
  224. &msm_cvp_dcvs_disable);
  225. debugfs_create_file("cvp_power", 0644, dir, NULL, &cvp_pwr_fops);
  226. return dir;
  227. failed_create_dir:
  228. if (dir)
  229. debugfs_remove_recursive(cvp_driver->debugfs_root);
  230. dprintk(CVP_WARN, "Failed to create debugfs\n");
  231. return NULL;
  232. }
  233. static int _clk_rate_set(void *data, u64 val)
  234. {
  235. struct msm_cvp_core *core;
  236. struct cvp_hfi_device *dev;
  237. struct allowed_clock_rates_table *tbl = NULL;
  238. unsigned int tbl_size, i;
  239. core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
  240. dev = core->device;
  241. tbl = core->resources.allowed_clks_tbl;
  242. tbl_size = core->resources.allowed_clks_tbl_size;
  243. if (val == 0) {
  244. struct iris_hfi_device *hdev = dev->hfi_device_data;
  245. msm_cvp_clock_voting = 0;
  246. call_hfi_op(dev, scale_clocks, hdev, hdev->clk_freq);
  247. return 0;
  248. }
  249. for (i = 0; i < tbl_size; i++)
  250. if (val <= tbl[i].clock_rate)
  251. break;
  252. if (i == tbl_size)
  253. msm_cvp_clock_voting = tbl[tbl_size-1].clock_rate;
  254. else
  255. msm_cvp_clock_voting = tbl[i].clock_rate;
  256. dprintk(CVP_WARN, "Override cvp_clk_rate with %d\n",
  257. msm_cvp_clock_voting);
  258. call_hfi_op(dev, scale_clocks, dev->hfi_device_data,
  259. msm_cvp_clock_voting);
  260. return 0;
  261. }
  262. static int _clk_rate_get(void *data, u64 *val)
  263. {
  264. struct msm_cvp_core *core;
  265. struct iris_hfi_device *hdev;
  266. core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
  267. hdev = core->device->hfi_device_data;
  268. if (msm_cvp_clock_voting)
  269. *val = msm_cvp_clock_voting;
  270. else
  271. *val = hdev->clk_freq;
  272. return 0;
  273. }
  274. DEFINE_DEBUGFS_ATTRIBUTE(clk_rate_fops, _clk_rate_get, _clk_rate_set, "%llu\n");
  275. static int _dsp_dbg_set(void *data, u64 val)
  276. {
  277. if (val == 0 || val >= (1 << (EVA_MEM_DEBUG_ON + 1))) {
  278. dprintk(CVP_WARN, "DSP debug mask cannot be %llx\n", val);
  279. return 0;
  280. }
  281. gfa_cv.debug_mask = (uint32_t)val;
  282. cvp_dsp_send_debug_mask();
  283. return 0;
  284. }
  285. static int _dsp_dbg_get(void *data, u64 *val)
  286. {
  287. *val = gfa_cv.debug_mask;
  288. return 0;
  289. }
  290. DEFINE_DEBUGFS_ATTRIBUTE(dsp_debug_fops, _dsp_dbg_get, _dsp_dbg_set, "%llu\n");
  291. static int _max_ssr_set(void *data, u64 val)
  292. {
  293. struct msm_cvp_core *core;
  294. core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
  295. if (core) {
  296. if (val < 1) {
  297. dprintk(CVP_WARN,
  298. "Invalid max_ssr_allowed value %llx\n", val);
  299. return 0;
  300. }
  301. core->resources.max_ssr_allowed = (unsigned int)val;
  302. }
  303. return 0;
  304. }
  305. static int _max_ssr_get(void *data, u64 *val)
  306. {
  307. struct msm_cvp_core *core;
  308. core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
  309. if (core)
  310. *val = core->resources.max_ssr_allowed;
  311. return 0;
  312. }
  313. DEFINE_DEBUGFS_ATTRIBUTE(max_ssr_fops, _max_ssr_get, _max_ssr_set, "%llu\n");
  314. static int _ssr_stall_set(void *data, u64 val)
  315. {
  316. struct msm_cvp_core *core;
  317. core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
  318. if (core)
  319. core->resources.fatal_ssr = (val >= 1) ? true : false;
  320. return 0;
  321. }
  322. static int _ssr_stall_get(void *data, u64 *val)
  323. {
  324. struct msm_cvp_core *core;
  325. core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
  326. if (core)
  327. *val = core->resources.fatal_ssr ? 1 : 0;
  328. return 0;
  329. }
  330. DEFINE_DEBUGFS_ATTRIBUTE(ssr_stall_fops, _ssr_stall_get, _ssr_stall_set, "%llu\n");
  331. struct dentry *msm_cvp_debugfs_init_core(struct msm_cvp_core *core,
  332. struct dentry *parent)
  333. {
  334. struct dentry *dir = NULL;
  335. char debugfs_name[MAX_DEBUGFS_NAME];
  336. if (!core) {
  337. dprintk(CVP_ERR, "Invalid params, core: %pK\n", core);
  338. goto failed_create_dir;
  339. }
  340. snprintf(debugfs_name, MAX_DEBUGFS_NAME, "core%d", core->id);
  341. dir = debugfs_create_dir(debugfs_name, parent);
  342. if (IS_ERR_OR_NULL(dir)) {
  343. dir = NULL;
  344. dprintk(CVP_ERR, "Failed to create debugfs for msm_cvp\n");
  345. goto failed_create_dir;
  346. }
  347. if (!debugfs_create_file("info", 0444, dir, core, &core_info_fops)) {
  348. dprintk(CVP_ERR, "debugfs_create_file: fail\n");
  349. goto failed_create_dir;
  350. }
  351. if (!debugfs_create_file("trigger_ssr", 0200,
  352. dir, core, &ssr_fops)) {
  353. dprintk(CVP_ERR, "debugfs_create_file: fail\n");
  354. goto failed_create_dir;
  355. }
  356. if (!debugfs_create_file("clock_rate", 0644, dir,
  357. NULL, &clk_rate_fops)) {
  358. dprintk(CVP_ERR, "debugfs_create_file: clock_rate fail\n");
  359. goto failed_create_dir;
  360. }
  361. if (!debugfs_create_file("dsp_debug_level", 0644, dir,
  362. NULL, &dsp_debug_fops)) {
  363. dprintk(CVP_ERR, "debugfs_create: dsp_debug_level fail\n");
  364. goto failed_create_dir;
  365. }
  366. if (!debugfs_create_file("max_ssr_allowed", 0644, dir,
  367. NULL, &max_ssr_fops)) {
  368. dprintk(CVP_ERR, "debugfs_create: max_ssr_allowed fail\n");
  369. goto failed_create_dir;
  370. }
  371. if (!debugfs_create_file("ssr_stall", 0644, dir,
  372. NULL, &ssr_stall_fops)) {
  373. dprintk(CVP_ERR, "debugfs_create: ssr_stall fail\n");
  374. goto failed_create_dir;
  375. }
  376. failed_create_dir:
  377. return dir;
  378. }
  379. static int inst_info_open(struct inode *inode, struct file *file)
  380. {
  381. dprintk(CVP_INFO, "Open inode ptr: %pK\n", inode->i_private);
  382. file->private_data = inode->i_private;
  383. return 0;
  384. }
  385. static int publish_unreleased_reference(struct msm_cvp_inst *inst,
  386. char **dbuf, char *end)
  387. {
  388. dprintk(CVP_SESS, "%s deprecated function\n", __func__);
  389. return 0;
  390. }
  391. static void put_inst_helper(struct kref *kref)
  392. {
  393. struct msm_cvp_inst *inst = container_of(kref,
  394. struct msm_cvp_inst, kref);
  395. msm_cvp_destroy(inst);
  396. }
  397. static ssize_t inst_info_read(struct file *file, char __user *buf,
  398. size_t count, loff_t *ppos)
  399. {
  400. struct cvp_core_inst_pair *idata = file->private_data;
  401. struct msm_cvp_core *core;
  402. struct msm_cvp_inst *inst, *temp = NULL;
  403. char *dbuf, *cur, *end;
  404. int i;
  405. ssize_t len = 0;
  406. if (!idata || !idata->core || !idata->inst) {
  407. dprintk(CVP_ERR, "%s: Invalid params\n", __func__);
  408. return 0;
  409. }
  410. core = idata->core;
  411. inst = idata->inst;
  412. mutex_lock(&core->lock);
  413. list_for_each_entry(temp, &core->instances, list) {
  414. if (temp == inst)
  415. break;
  416. }
  417. inst = ((temp == inst) && kref_get_unless_zero(&inst->kref)) ?
  418. inst : NULL;
  419. mutex_unlock(&core->lock);
  420. if (!inst) {
  421. dprintk(CVP_ERR, "%s: Instance has become obsolete", __func__);
  422. return 0;
  423. }
  424. dbuf = kzalloc(MAX_DBG_BUF_SIZE, GFP_KERNEL);
  425. if (!dbuf) {
  426. dprintk(CVP_ERR, "%s: Allocation failed!\n", __func__);
  427. len = -ENOMEM;
  428. goto failed_alloc;
  429. }
  430. cur = dbuf;
  431. end = cur + MAX_DBG_BUF_SIZE;
  432. cur += write_str(cur, end - cur, "==============================\n");
  433. cur += write_str(cur, end - cur, "INSTANCE: %pK (%s)\n", inst,
  434. inst->session_type == MSM_CVP_USER ? "User" : "Kernel");
  435. cur += write_str(cur, end - cur, "==============================\n");
  436. cur += write_str(cur, end - cur, "core: %pK\n", inst->core);
  437. cur += write_str(cur, end - cur, "state: %d\n", inst->state);
  438. cur += write_str(cur, end - cur, "secure: %d\n",
  439. !!(inst->flags & CVP_SECURE));
  440. for (i = SESSION_MSG_START; i < SESSION_MSG_END; i++) {
  441. cur += write_str(cur, end - cur, "completions[%d]: %s\n", i,
  442. completion_done(&inst->completions[SESSION_MSG_INDEX(i)]) ?
  443. "pending" : "done");
  444. }
  445. publish_unreleased_reference(inst, &cur, end);
  446. len = simple_read_from_buffer(buf, count, ppos,
  447. dbuf, cur - dbuf);
  448. kfree(dbuf);
  449. failed_alloc:
  450. kref_put(&inst->kref, put_inst_helper);
  451. return len;
  452. }
  453. static int inst_info_release(struct inode *inode, struct file *file)
  454. {
  455. dprintk(CVP_INFO, "Release inode ptr: %pK\n", inode->i_private);
  456. file->private_data = NULL;
  457. return 0;
  458. }
  459. static const struct file_operations inst_info_fops = {
  460. .open = inst_info_open,
  461. .read = inst_info_read,
  462. .release = inst_info_release,
  463. };
  464. struct dentry *msm_cvp_debugfs_init_inst(struct msm_cvp_inst *inst,
  465. struct dentry *parent)
  466. {
  467. struct dentry *dir = NULL, *info = NULL;
  468. char debugfs_name[MAX_DEBUGFS_NAME];
  469. struct cvp_core_inst_pair *idata = NULL;
  470. if (!inst) {
  471. dprintk(CVP_ERR, "Invalid params, inst: %pK\n", inst);
  472. goto exit;
  473. }
  474. snprintf(debugfs_name, MAX_DEBUGFS_NAME, "inst_%pK", inst);
  475. idata = kzalloc(sizeof(*idata), GFP_KERNEL);
  476. if (!idata) {
  477. dprintk(CVP_ERR, "%s: Allocation failed!\n", __func__);
  478. goto exit;
  479. }
  480. idata->core = inst->core;
  481. idata->inst = inst;
  482. dir = debugfs_create_dir(debugfs_name, parent);
  483. if (IS_ERR_OR_NULL(dir)) {
  484. dir = NULL;
  485. dprintk(CVP_ERR, "Failed to create debugfs for msm_cvp\n");
  486. goto failed_create_dir;
  487. }
  488. info = debugfs_create_file("info", 0444, dir,
  489. idata, &inst_info_fops);
  490. if (!info) {
  491. dprintk(CVP_ERR, "debugfs_create_file: info fail\n");
  492. goto failed_create_file;
  493. }
  494. dir->d_inode->i_private = info->d_inode->i_private;
  495. inst->debug.pdata[FRAME_PROCESSING].sampling = true;
  496. return dir;
  497. failed_create_file:
  498. debugfs_remove_recursive(dir);
  499. dir = NULL;
  500. failed_create_dir:
  501. kfree(idata);
  502. exit:
  503. return dir;
  504. }
  505. void msm_cvp_debugfs_deinit_inst(struct msm_cvp_inst *inst)
  506. {
  507. struct dentry *dentry = NULL;
  508. if (!inst || !inst->debugfs_root)
  509. return;
  510. dentry = inst->debugfs_root;
  511. if (dentry->d_inode) {
  512. dprintk(CVP_INFO, "Destroy %pK\n", dentry->d_inode->i_private);
  513. kfree(dentry->d_inode->i_private);
  514. dentry->d_inode->i_private = NULL;
  515. }
  516. debugfs_remove_recursive(dentry);
  517. inst->debugfs_root = NULL;
  518. }