ice_debugfs.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* Copyright (c) 2022, Intel Corporation. */
  3. #include <linux/fs.h>
  4. #include <linux/debugfs.h>
  5. #include <linux/random.h>
  6. #include <linux/vmalloc.h>
  7. #include "ice.h"
  8. static struct dentry *ice_debugfs_root;
  9. /* create a define that has an extra module that doesn't really exist. this
  10. * is so we can add a module 'all' to easily enable/disable all the modules
  11. */
  12. #define ICE_NR_FW_LOG_MODULES (ICE_AQC_FW_LOG_ID_MAX + 1)
  13. /* the ordering in this array is important. it matches the ordering of the
  14. * values in the FW so the index is the same value as in ice_aqc_fw_logging_mod
  15. */
  16. static const char * const ice_fwlog_module_string[] = {
  17. "general",
  18. "ctrl",
  19. "link",
  20. "link_topo",
  21. "dnl",
  22. "i2c",
  23. "sdp",
  24. "mdio",
  25. "adminq",
  26. "hdma",
  27. "lldp",
  28. "dcbx",
  29. "dcb",
  30. "xlr",
  31. "nvm",
  32. "auth",
  33. "vpd",
  34. "iosf",
  35. "parser",
  36. "sw",
  37. "scheduler",
  38. "txq",
  39. "rsvd",
  40. "post",
  41. "watchdog",
  42. "task_dispatch",
  43. "mng",
  44. "synce",
  45. "health",
  46. "tsdrv",
  47. "pfreg",
  48. "mdlver",
  49. "all",
  50. };
  51. /* the ordering in this array is important. it matches the ordering of the
  52. * values in the FW so the index is the same value as in ice_fwlog_level
  53. */
  54. static const char * const ice_fwlog_level_string[] = {
  55. "none",
  56. "error",
  57. "warning",
  58. "normal",
  59. "verbose",
  60. };
  61. static const char * const ice_fwlog_log_size[] = {
  62. "128K",
  63. "256K",
  64. "512K",
  65. "1M",
  66. "2M",
  67. };
  68. /**
  69. * ice_fwlog_print_module_cfg - print current FW logging module configuration
  70. * @hw: pointer to the HW structure
  71. * @module: module to print
  72. * @s: the seq file to put data into
  73. */
  74. static void
  75. ice_fwlog_print_module_cfg(struct ice_hw *hw, int module, struct seq_file *s)
  76. {
  77. struct ice_fwlog_cfg *cfg = &hw->fwlog_cfg;
  78. struct ice_fwlog_module_entry *entry;
  79. if (module != ICE_AQC_FW_LOG_ID_MAX) {
  80. entry = &cfg->module_entries[module];
  81. seq_printf(s, "\tModule: %s, Log Level: %s\n",
  82. ice_fwlog_module_string[entry->module_id],
  83. ice_fwlog_level_string[entry->log_level]);
  84. } else {
  85. int i;
  86. for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++) {
  87. entry = &cfg->module_entries[i];
  88. seq_printf(s, "\tModule: %s, Log Level: %s\n",
  89. ice_fwlog_module_string[entry->module_id],
  90. ice_fwlog_level_string[entry->log_level]);
  91. }
  92. }
  93. }
  94. static int ice_find_module_by_dentry(struct ice_pf *pf, struct dentry *d)
  95. {
  96. int i, module;
  97. module = -1;
  98. /* find the module based on the dentry */
  99. for (i = 0; i < ICE_NR_FW_LOG_MODULES; i++) {
  100. if (d == pf->ice_debugfs_pf_fwlog_modules[i]) {
  101. module = i;
  102. break;
  103. }
  104. }
  105. return module;
  106. }
  107. /**
  108. * ice_debugfs_module_show - read from 'module' file
  109. * @s: the opened file
  110. * @v: pointer to the offset
  111. */
  112. static int ice_debugfs_module_show(struct seq_file *s, void *v)
  113. {
  114. const struct file *filp = s->file;
  115. struct dentry *dentry;
  116. struct ice_pf *pf;
  117. int module;
  118. dentry = file_dentry(filp);
  119. pf = s->private;
  120. module = ice_find_module_by_dentry(pf, dentry);
  121. if (module < 0) {
  122. dev_info(ice_pf_to_dev(pf), "unknown module\n");
  123. return -EINVAL;
  124. }
  125. ice_fwlog_print_module_cfg(&pf->hw, module, s);
  126. return 0;
  127. }
  128. static int ice_debugfs_module_open(struct inode *inode, struct file *filp)
  129. {
  130. return single_open(filp, ice_debugfs_module_show, inode->i_private);
  131. }
  132. /**
  133. * ice_debugfs_module_write - write into 'module' file
  134. * @filp: the opened file
  135. * @buf: where to find the user's data
  136. * @count: the length of the user's data
  137. * @ppos: file position offset
  138. */
  139. static ssize_t
  140. ice_debugfs_module_write(struct file *filp, const char __user *buf,
  141. size_t count, loff_t *ppos)
  142. {
  143. struct ice_pf *pf = file_inode(filp)->i_private;
  144. struct dentry *dentry = file_dentry(filp);
  145. struct device *dev = ice_pf_to_dev(pf);
  146. char user_val[16], *cmd_buf;
  147. int module, log_level, cnt;
  148. /* don't allow partial writes or invalid input */
  149. if (*ppos != 0 || count > 8)
  150. return -EINVAL;
  151. cmd_buf = memdup_user_nul(buf, count);
  152. if (IS_ERR(cmd_buf))
  153. return PTR_ERR(cmd_buf);
  154. module = ice_find_module_by_dentry(pf, dentry);
  155. if (module < 0) {
  156. dev_info(dev, "unknown module\n");
  157. return -EINVAL;
  158. }
  159. cnt = sscanf(cmd_buf, "%s", user_val);
  160. if (cnt != 1)
  161. return -EINVAL;
  162. log_level = sysfs_match_string(ice_fwlog_level_string, user_val);
  163. if (log_level < 0) {
  164. dev_info(dev, "unknown log level '%s'\n", user_val);
  165. return -EINVAL;
  166. }
  167. if (module != ICE_AQC_FW_LOG_ID_MAX) {
  168. ice_pf_fwlog_update_module(pf, log_level, module);
  169. } else {
  170. /* the module 'all' is a shortcut so that we can set
  171. * all of the modules to the same level quickly
  172. */
  173. int i;
  174. for (i = 0; i < ICE_AQC_FW_LOG_ID_MAX; i++)
  175. ice_pf_fwlog_update_module(pf, log_level, i);
  176. }
  177. return count;
  178. }
  179. static const struct file_operations ice_debugfs_module_fops = {
  180. .owner = THIS_MODULE,
  181. .open = ice_debugfs_module_open,
  182. .read = seq_read,
  183. .release = single_release,
  184. .write = ice_debugfs_module_write,
  185. };
  186. /**
  187. * ice_debugfs_nr_messages_read - read from 'nr_messages' file
  188. * @filp: the opened file
  189. * @buffer: where to write the data for the user to read
  190. * @count: the size of the user's buffer
  191. * @ppos: file position offset
  192. */
  193. static ssize_t ice_debugfs_nr_messages_read(struct file *filp,
  194. char __user *buffer, size_t count,
  195. loff_t *ppos)
  196. {
  197. struct ice_pf *pf = filp->private_data;
  198. struct ice_hw *hw = &pf->hw;
  199. char buff[32] = {};
  200. snprintf(buff, sizeof(buff), "%d\n",
  201. hw->fwlog_cfg.log_resolution);
  202. return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff));
  203. }
  204. /**
  205. * ice_debugfs_nr_messages_write - write into 'nr_messages' file
  206. * @filp: the opened file
  207. * @buf: where to find the user's data
  208. * @count: the length of the user's data
  209. * @ppos: file position offset
  210. */
  211. static ssize_t
  212. ice_debugfs_nr_messages_write(struct file *filp, const char __user *buf,
  213. size_t count, loff_t *ppos)
  214. {
  215. struct ice_pf *pf = filp->private_data;
  216. struct device *dev = ice_pf_to_dev(pf);
  217. struct ice_hw *hw = &pf->hw;
  218. char user_val[8], *cmd_buf;
  219. s16 nr_messages;
  220. ssize_t ret;
  221. /* don't allow partial writes or invalid input */
  222. if (*ppos != 0 || count > 4)
  223. return -EINVAL;
  224. cmd_buf = memdup_user_nul(buf, count);
  225. if (IS_ERR(cmd_buf))
  226. return PTR_ERR(cmd_buf);
  227. ret = sscanf(cmd_buf, "%s", user_val);
  228. if (ret != 1)
  229. return -EINVAL;
  230. ret = kstrtos16(user_val, 0, &nr_messages);
  231. if (ret)
  232. return ret;
  233. if (nr_messages < ICE_AQC_FW_LOG_MIN_RESOLUTION ||
  234. nr_messages > ICE_AQC_FW_LOG_MAX_RESOLUTION) {
  235. dev_err(dev, "Invalid FW log number of messages %d, value must be between %d - %d\n",
  236. nr_messages, ICE_AQC_FW_LOG_MIN_RESOLUTION,
  237. ICE_AQC_FW_LOG_MAX_RESOLUTION);
  238. return -EINVAL;
  239. }
  240. hw->fwlog_cfg.log_resolution = nr_messages;
  241. return count;
  242. }
  243. static const struct file_operations ice_debugfs_nr_messages_fops = {
  244. .owner = THIS_MODULE,
  245. .open = simple_open,
  246. .read = ice_debugfs_nr_messages_read,
  247. .write = ice_debugfs_nr_messages_write,
  248. };
  249. /**
  250. * ice_debugfs_enable_read - read from 'enable' file
  251. * @filp: the opened file
  252. * @buffer: where to write the data for the user to read
  253. * @count: the size of the user's buffer
  254. * @ppos: file position offset
  255. */
  256. static ssize_t ice_debugfs_enable_read(struct file *filp,
  257. char __user *buffer, size_t count,
  258. loff_t *ppos)
  259. {
  260. struct ice_pf *pf = filp->private_data;
  261. struct ice_hw *hw = &pf->hw;
  262. char buff[32] = {};
  263. snprintf(buff, sizeof(buff), "%u\n",
  264. (u16)(hw->fwlog_cfg.options &
  265. ICE_FWLOG_OPTION_IS_REGISTERED) >> 3);
  266. return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff));
  267. }
  268. /**
  269. * ice_debugfs_enable_write - write into 'enable' file
  270. * @filp: the opened file
  271. * @buf: where to find the user's data
  272. * @count: the length of the user's data
  273. * @ppos: file position offset
  274. */
  275. static ssize_t
  276. ice_debugfs_enable_write(struct file *filp, const char __user *buf,
  277. size_t count, loff_t *ppos)
  278. {
  279. struct ice_pf *pf = filp->private_data;
  280. struct ice_hw *hw = &pf->hw;
  281. char user_val[8], *cmd_buf;
  282. bool enable;
  283. ssize_t ret;
  284. /* don't allow partial writes or invalid input */
  285. if (*ppos != 0 || count > 2)
  286. return -EINVAL;
  287. cmd_buf = memdup_user_nul(buf, count);
  288. if (IS_ERR(cmd_buf))
  289. return PTR_ERR(cmd_buf);
  290. ret = sscanf(cmd_buf, "%s", user_val);
  291. if (ret != 1)
  292. return -EINVAL;
  293. ret = kstrtobool(user_val, &enable);
  294. if (ret)
  295. goto enable_write_error;
  296. if (enable)
  297. hw->fwlog_cfg.options |= ICE_FWLOG_OPTION_ARQ_ENA;
  298. else
  299. hw->fwlog_cfg.options &= ~ICE_FWLOG_OPTION_ARQ_ENA;
  300. ret = ice_fwlog_set(hw, &hw->fwlog_cfg);
  301. if (ret)
  302. goto enable_write_error;
  303. if (enable)
  304. ret = ice_fwlog_register(hw);
  305. else
  306. ret = ice_fwlog_unregister(hw);
  307. if (ret)
  308. goto enable_write_error;
  309. /* if we get here, nothing went wrong; return count since we didn't
  310. * really write anything
  311. */
  312. ret = (ssize_t)count;
  313. enable_write_error:
  314. /* This function always consumes all of the written input, or produces
  315. * an error. Check and enforce this. Otherwise, the write operation
  316. * won't complete properly.
  317. */
  318. if (WARN_ON(ret != (ssize_t)count && ret >= 0))
  319. ret = -EIO;
  320. return ret;
  321. }
  322. static const struct file_operations ice_debugfs_enable_fops = {
  323. .owner = THIS_MODULE,
  324. .open = simple_open,
  325. .read = ice_debugfs_enable_read,
  326. .write = ice_debugfs_enable_write,
  327. };
  328. /**
  329. * ice_debugfs_log_size_read - read from 'log_size' file
  330. * @filp: the opened file
  331. * @buffer: where to write the data for the user to read
  332. * @count: the size of the user's buffer
  333. * @ppos: file position offset
  334. */
  335. static ssize_t ice_debugfs_log_size_read(struct file *filp,
  336. char __user *buffer, size_t count,
  337. loff_t *ppos)
  338. {
  339. struct ice_pf *pf = filp->private_data;
  340. struct ice_hw *hw = &pf->hw;
  341. char buff[32] = {};
  342. int index;
  343. index = hw->fwlog_ring.index;
  344. snprintf(buff, sizeof(buff), "%s\n", ice_fwlog_log_size[index]);
  345. return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff));
  346. }
  347. /**
  348. * ice_debugfs_log_size_write - write into 'log_size' file
  349. * @filp: the opened file
  350. * @buf: where to find the user's data
  351. * @count: the length of the user's data
  352. * @ppos: file position offset
  353. */
  354. static ssize_t
  355. ice_debugfs_log_size_write(struct file *filp, const char __user *buf,
  356. size_t count, loff_t *ppos)
  357. {
  358. struct ice_pf *pf = filp->private_data;
  359. struct device *dev = ice_pf_to_dev(pf);
  360. struct ice_hw *hw = &pf->hw;
  361. char user_val[8], *cmd_buf;
  362. ssize_t ret;
  363. int index;
  364. /* don't allow partial writes or invalid input */
  365. if (*ppos != 0 || count > 5)
  366. return -EINVAL;
  367. cmd_buf = memdup_user_nul(buf, count);
  368. if (IS_ERR(cmd_buf))
  369. return PTR_ERR(cmd_buf);
  370. ret = sscanf(cmd_buf, "%s", user_val);
  371. if (ret != 1)
  372. return -EINVAL;
  373. index = sysfs_match_string(ice_fwlog_log_size, user_val);
  374. if (index < 0) {
  375. dev_info(dev, "Invalid log size '%s'. The value must be one of 128K, 256K, 512K, 1M, 2M\n",
  376. user_val);
  377. ret = -EINVAL;
  378. goto log_size_write_error;
  379. } else if (hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED) {
  380. dev_info(dev, "FW logging is currently running. Please disable FW logging to change log_size\n");
  381. ret = -EINVAL;
  382. goto log_size_write_error;
  383. }
  384. /* free all the buffers and the tracking info and resize */
  385. ice_fwlog_realloc_rings(hw, index);
  386. /* if we get here, nothing went wrong; return count since we didn't
  387. * really write anything
  388. */
  389. ret = (ssize_t)count;
  390. log_size_write_error:
  391. /* This function always consumes all of the written input, or produces
  392. * an error. Check and enforce this. Otherwise, the write operation
  393. * won't complete properly.
  394. */
  395. if (WARN_ON(ret != (ssize_t)count && ret >= 0))
  396. ret = -EIO;
  397. return ret;
  398. }
  399. static const struct file_operations ice_debugfs_log_size_fops = {
  400. .owner = THIS_MODULE,
  401. .open = simple_open,
  402. .read = ice_debugfs_log_size_read,
  403. .write = ice_debugfs_log_size_write,
  404. };
  405. /**
  406. * ice_debugfs_data_read - read from 'data' file
  407. * @filp: the opened file
  408. * @buffer: where to write the data for the user to read
  409. * @count: the size of the user's buffer
  410. * @ppos: file position offset
  411. */
  412. static ssize_t ice_debugfs_data_read(struct file *filp, char __user *buffer,
  413. size_t count, loff_t *ppos)
  414. {
  415. struct ice_pf *pf = filp->private_data;
  416. struct ice_hw *hw = &pf->hw;
  417. int data_copied = 0;
  418. bool done = false;
  419. if (ice_fwlog_ring_empty(&hw->fwlog_ring))
  420. return 0;
  421. while (!ice_fwlog_ring_empty(&hw->fwlog_ring) && !done) {
  422. struct ice_fwlog_data *log;
  423. u16 cur_buf_len;
  424. log = &hw->fwlog_ring.rings[hw->fwlog_ring.head];
  425. cur_buf_len = log->data_size;
  426. if (cur_buf_len >= count) {
  427. done = true;
  428. continue;
  429. }
  430. if (copy_to_user(buffer, log->data, cur_buf_len)) {
  431. /* if there is an error then bail and return whatever
  432. * the driver has copied so far
  433. */
  434. done = true;
  435. continue;
  436. }
  437. data_copied += cur_buf_len;
  438. buffer += cur_buf_len;
  439. count -= cur_buf_len;
  440. *ppos += cur_buf_len;
  441. ice_fwlog_ring_increment(&hw->fwlog_ring.head,
  442. hw->fwlog_ring.size);
  443. }
  444. return data_copied;
  445. }
  446. /**
  447. * ice_debugfs_data_write - write into 'data' file
  448. * @filp: the opened file
  449. * @buf: where to find the user's data
  450. * @count: the length of the user's data
  451. * @ppos: file position offset
  452. */
  453. static ssize_t
  454. ice_debugfs_data_write(struct file *filp, const char __user *buf, size_t count,
  455. loff_t *ppos)
  456. {
  457. struct ice_pf *pf = filp->private_data;
  458. struct device *dev = ice_pf_to_dev(pf);
  459. struct ice_hw *hw = &pf->hw;
  460. ssize_t ret;
  461. /* don't allow partial writes */
  462. if (*ppos != 0)
  463. return 0;
  464. /* any value is allowed to clear the buffer so no need to even look at
  465. * what the value is
  466. */
  467. if (!(hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED)) {
  468. hw->fwlog_ring.head = 0;
  469. hw->fwlog_ring.tail = 0;
  470. } else {
  471. dev_info(dev, "Can't clear FW log data while FW log running\n");
  472. ret = -EINVAL;
  473. goto nr_buffs_write_error;
  474. }
  475. /* if we get here, nothing went wrong; return count since we didn't
  476. * really write anything
  477. */
  478. ret = (ssize_t)count;
  479. nr_buffs_write_error:
  480. /* This function always consumes all of the written input, or produces
  481. * an error. Check and enforce this. Otherwise, the write operation
  482. * won't complete properly.
  483. */
  484. if (WARN_ON(ret != (ssize_t)count && ret >= 0))
  485. ret = -EIO;
  486. return ret;
  487. }
  488. static const struct file_operations ice_debugfs_data_fops = {
  489. .owner = THIS_MODULE,
  490. .open = simple_open,
  491. .read = ice_debugfs_data_read,
  492. .write = ice_debugfs_data_write,
  493. };
  494. /**
  495. * ice_debugfs_fwlog_init - setup the debugfs directory
  496. * @pf: the ice that is starting up
  497. */
  498. void ice_debugfs_fwlog_init(struct ice_pf *pf)
  499. {
  500. const char *name = pci_name(pf->pdev);
  501. struct dentry *fw_modules_dir;
  502. struct dentry **fw_modules;
  503. int i;
  504. /* only support fw log commands on PF 0 */
  505. if (pf->hw.bus.func)
  506. return;
  507. /* allocate space for this first because if it fails then we don't
  508. * need to unwind
  509. */
  510. fw_modules = kcalloc(ICE_NR_FW_LOG_MODULES, sizeof(*fw_modules),
  511. GFP_KERNEL);
  512. if (!fw_modules)
  513. return;
  514. pf->ice_debugfs_pf = debugfs_create_dir(name, ice_debugfs_root);
  515. if (IS_ERR(pf->ice_debugfs_pf))
  516. goto err_create_module_files;
  517. pf->ice_debugfs_pf_fwlog = debugfs_create_dir("fwlog",
  518. pf->ice_debugfs_pf);
  519. if (IS_ERR(pf->ice_debugfs_pf_fwlog))
  520. goto err_create_module_files;
  521. fw_modules_dir = debugfs_create_dir("modules",
  522. pf->ice_debugfs_pf_fwlog);
  523. if (IS_ERR(fw_modules_dir))
  524. goto err_create_module_files;
  525. for (i = 0; i < ICE_NR_FW_LOG_MODULES; i++) {
  526. fw_modules[i] = debugfs_create_file(ice_fwlog_module_string[i],
  527. 0600, fw_modules_dir, pf,
  528. &ice_debugfs_module_fops);
  529. if (IS_ERR(fw_modules[i]))
  530. goto err_create_module_files;
  531. }
  532. debugfs_create_file("nr_messages", 0600,
  533. pf->ice_debugfs_pf_fwlog, pf,
  534. &ice_debugfs_nr_messages_fops);
  535. pf->ice_debugfs_pf_fwlog_modules = fw_modules;
  536. debugfs_create_file("enable", 0600, pf->ice_debugfs_pf_fwlog,
  537. pf, &ice_debugfs_enable_fops);
  538. debugfs_create_file("log_size", 0600, pf->ice_debugfs_pf_fwlog,
  539. pf, &ice_debugfs_log_size_fops);
  540. debugfs_create_file("data", 0600, pf->ice_debugfs_pf_fwlog,
  541. pf, &ice_debugfs_data_fops);
  542. return;
  543. err_create_module_files:
  544. debugfs_remove_recursive(pf->ice_debugfs_pf_fwlog);
  545. kfree(fw_modules);
  546. }
  547. /**
  548. * ice_debugfs_pf_deinit - cleanup PF's debugfs
  549. * @pf: pointer to the PF struct
  550. */
  551. void ice_debugfs_pf_deinit(struct ice_pf *pf)
  552. {
  553. debugfs_remove_recursive(pf->ice_debugfs_pf);
  554. pf->ice_debugfs_pf = NULL;
  555. }
  556. /**
  557. * ice_debugfs_init - create root directory for debugfs entries
  558. */
  559. void ice_debugfs_init(void)
  560. {
  561. ice_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
  562. if (IS_ERR(ice_debugfs_root))
  563. pr_info("init of debugfs failed\n");
  564. }
  565. /**
  566. * ice_debugfs_exit - remove debugfs entries
  567. */
  568. void ice_debugfs_exit(void)
  569. {
  570. debugfs_remove_recursive(ice_debugfs_root);
  571. ice_debugfs_root = NULL;
  572. }