debug.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
  3. /* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. */
  4. #include <linux/err.h>
  5. #include <linux/seq_file.h>
  6. #include <linux/debugfs.h>
  7. #include "main.h"
  8. #include "bus.h"
  9. #include "debug.h"
  10. #include "pci.h"
  11. #define MMIO_REG_ACCESS_MEM_TYPE 0xFF
  12. #define MMIO_REG_RAW_ACCESS_MEM_TYPE 0xFE
  13. #define DEFAULT_KERNEL_LOG_LEVEL INFO_LOG
  14. #define DEFAULT_IPC_LOG_LEVEL DEBUG_LOG
  15. enum log_level cnss_kernel_log_level = DEFAULT_KERNEL_LOG_LEVEL;
  16. #if IS_ENABLED(CONFIG_IPC_LOGGING)
  17. void *cnss_ipc_log_context;
  18. void *cnss_ipc_log_long_context;
  19. enum log_level cnss_ipc_log_level = DEFAULT_IPC_LOG_LEVEL;
  20. static int cnss_set_ipc_log_level(u32 val)
  21. {
  22. if (val < MAX_LOG) {
  23. cnss_ipc_log_level = val;
  24. return 0;
  25. }
  26. return -EINVAL;
  27. }
  28. static u32 cnss_get_ipc_log_level(void)
  29. {
  30. return cnss_ipc_log_level;
  31. }
  32. #else
  33. static int cnss_set_ipc_log_level(int val) { return -EINVAL; }
  34. static u32 cnss_get_ipc_log_level(void) { return MAX_LOG; }
  35. #endif
  36. static int cnss_pin_connect_show(struct seq_file *s, void *data)
  37. {
  38. struct cnss_plat_data *cnss_priv = s->private;
  39. seq_puts(s, "Pin connect results\n");
  40. seq_printf(s, "FW power pin result: %04x\n",
  41. cnss_priv->pin_result.fw_pwr_pin_result);
  42. seq_printf(s, "FW PHY IO pin result: %04x\n",
  43. cnss_priv->pin_result.fw_phy_io_pin_result);
  44. seq_printf(s, "FW RF pin result: %04x\n",
  45. cnss_priv->pin_result.fw_rf_pin_result);
  46. seq_printf(s, "Host pin result: %04x\n",
  47. cnss_priv->pin_result.host_pin_result);
  48. seq_puts(s, "\n");
  49. return 0;
  50. }
  51. static int cnss_pin_connect_open(struct inode *inode, struct file *file)
  52. {
  53. return single_open(file, cnss_pin_connect_show, inode->i_private);
  54. }
  55. static const struct file_operations cnss_pin_connect_fops = {
  56. .read = seq_read,
  57. .release = single_release,
  58. .open = cnss_pin_connect_open,
  59. .owner = THIS_MODULE,
  60. .llseek = seq_lseek,
  61. };
  62. static int cnss_stats_show_state(struct seq_file *s,
  63. struct cnss_plat_data *plat_priv)
  64. {
  65. enum cnss_driver_state i;
  66. int skip = 0;
  67. unsigned long state;
  68. seq_printf(s, "\nState: 0x%lx(", plat_priv->driver_state);
  69. for (i = 0, state = plat_priv->driver_state; state != 0;
  70. state >>= 1, i++) {
  71. if (!(state & 0x1))
  72. continue;
  73. if (skip++)
  74. seq_puts(s, " | ");
  75. switch (i) {
  76. case CNSS_QMI_WLFW_CONNECTED:
  77. seq_puts(s, "QMI_WLFW_CONNECTED");
  78. continue;
  79. case CNSS_FW_MEM_READY:
  80. seq_puts(s, "FW_MEM_READY");
  81. continue;
  82. case CNSS_FW_READY:
  83. seq_puts(s, "FW_READY");
  84. continue;
  85. case CNSS_IN_COLD_BOOT_CAL:
  86. seq_puts(s, "IN_COLD_BOOT_CAL");
  87. continue;
  88. case CNSS_DRIVER_LOADING:
  89. seq_puts(s, "DRIVER_LOADING");
  90. continue;
  91. case CNSS_DRIVER_UNLOADING:
  92. seq_puts(s, "DRIVER_UNLOADING");
  93. continue;
  94. case CNSS_DRIVER_IDLE_RESTART:
  95. seq_puts(s, "IDLE_RESTART");
  96. continue;
  97. case CNSS_DRIVER_IDLE_SHUTDOWN:
  98. seq_puts(s, "IDLE_SHUTDOWN");
  99. continue;
  100. case CNSS_DRIVER_PROBED:
  101. seq_puts(s, "DRIVER_PROBED");
  102. continue;
  103. case CNSS_DRIVER_RECOVERY:
  104. seq_puts(s, "DRIVER_RECOVERY");
  105. continue;
  106. case CNSS_FW_BOOT_RECOVERY:
  107. seq_puts(s, "FW_BOOT_RECOVERY");
  108. continue;
  109. case CNSS_DEV_ERR_NOTIFY:
  110. seq_puts(s, "DEV_ERR");
  111. continue;
  112. case CNSS_DRIVER_DEBUG:
  113. seq_puts(s, "DRIVER_DEBUG");
  114. continue;
  115. case CNSS_COEX_CONNECTED:
  116. seq_puts(s, "COEX_CONNECTED");
  117. continue;
  118. case CNSS_IMS_CONNECTED:
  119. seq_puts(s, "IMS_CONNECTED");
  120. continue;
  121. case CNSS_IN_SUSPEND_RESUME:
  122. seq_puts(s, "IN_SUSPEND_RESUME");
  123. continue;
  124. case CNSS_IN_REBOOT:
  125. seq_puts(s, "IN_REBOOT");
  126. continue;
  127. case CNSS_COLD_BOOT_CAL_DONE:
  128. seq_puts(s, "COLD_BOOT_CAL_DONE");
  129. continue;
  130. case CNSS_IN_PANIC:
  131. seq_puts(s, "IN_PANIC");
  132. continue;
  133. case CNSS_QMI_DEL_SERVER:
  134. seq_puts(s, "DEL_SERVER_IN_PROGRESS");
  135. continue;
  136. case CNSS_QMI_DMS_CONNECTED:
  137. seq_puts(s, "DMS_CONNECTED");
  138. continue;
  139. case CNSS_DMS_DEL_SERVER:
  140. seq_puts(s, "DMS_DEL_SERVER");
  141. continue;
  142. case CNSS_DAEMON_CONNECTED:
  143. seq_puts(s, "DAEMON_CONNECTED");
  144. continue;
  145. case CNSS_PCI_PROBE_DONE:
  146. seq_puts(s, "PCI PROBE DONE");
  147. continue;
  148. case CNSS_DRIVER_REGISTER:
  149. seq_puts(s, "DRIVER REGISTERED");
  150. continue;
  151. case CNSS_WLAN_HW_DISABLED:
  152. seq_puts(s, "WLAN HW DISABLED");
  153. continue;
  154. case CNSS_FS_READY:
  155. seq_puts(s, "FS READY");
  156. continue;
  157. case CNSS_DRIVER_REGISTERED:
  158. seq_puts(s, "DRIVER REGISTERED");
  159. continue;
  160. case CNSS_POWER_OFF:
  161. seq_puts(s, "POWER OFF");
  162. continue;
  163. }
  164. seq_printf(s, "UNKNOWN-%d", i);
  165. }
  166. seq_puts(s, ")\n");
  167. return 0;
  168. }
  169. static int cnss_stats_show_gpio_state(struct seq_file *s,
  170. struct cnss_plat_data *plat_priv)
  171. {
  172. seq_printf(s, "\nHost SOL: %d", cnss_get_host_sol_value(plat_priv));
  173. seq_printf(s, "\nDev SOL: %d", cnss_get_dev_sol_value(plat_priv));
  174. return 0;
  175. }
  176. static int cnss_stats_show(struct seq_file *s, void *data)
  177. {
  178. struct cnss_plat_data *plat_priv = s->private;
  179. cnss_stats_show_state(s, plat_priv);
  180. cnss_stats_show_gpio_state(s, plat_priv);
  181. return 0;
  182. }
  183. static int cnss_stats_open(struct inode *inode, struct file *file)
  184. {
  185. return single_open(file, cnss_stats_show, inode->i_private);
  186. }
  187. static const struct file_operations cnss_stats_fops = {
  188. .read = seq_read,
  189. .release = single_release,
  190. .open = cnss_stats_open,
  191. .owner = THIS_MODULE,
  192. .llseek = seq_lseek,
  193. };
  194. static ssize_t cnss_dev_boot_debug_write(struct file *fp,
  195. const char __user *user_buf,
  196. size_t count, loff_t *off)
  197. {
  198. struct cnss_plat_data *plat_priv =
  199. ((struct seq_file *)fp->private_data)->private;
  200. struct cnss_pci_data *pci_priv;
  201. char buf[64];
  202. char *cmd;
  203. unsigned int len = 0;
  204. char *sptr, *token;
  205. const char *delim = " ";
  206. int ret = 0;
  207. if (!plat_priv)
  208. return -ENODEV;
  209. len = min(count, sizeof(buf) - 1);
  210. if (copy_from_user(buf, user_buf, len))
  211. return -EFAULT;
  212. buf[len] = '\0';
  213. sptr = buf;
  214. token = strsep(&sptr, delim);
  215. if (!token)
  216. return -EINVAL;
  217. cmd = token;
  218. cnss_pr_dbg("Received dev_boot debug command: %s\n", cmd);
  219. if (sysfs_streq(cmd, "on")) {
  220. ret = cnss_power_on_device(plat_priv, false);
  221. } else if (sysfs_streq(cmd, "off")) {
  222. cnss_power_off_device(plat_priv);
  223. } else if (sysfs_streq(cmd, "enumerate")) {
  224. ret = cnss_pci_init(plat_priv);
  225. } else if (sysfs_streq(cmd, "powerup")) {
  226. set_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
  227. ret = cnss_driver_event_post(plat_priv,
  228. CNSS_DRIVER_EVENT_POWER_UP,
  229. CNSS_EVENT_SYNC, NULL);
  230. } else if (sysfs_streq(cmd, "shutdown")) {
  231. ret = cnss_driver_event_post(plat_priv,
  232. CNSS_DRIVER_EVENT_POWER_DOWN,
  233. 0, NULL);
  234. clear_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
  235. } else if (sysfs_streq(cmd, "assert_host_sol")) {
  236. pci_priv = plat_priv->bus_priv;
  237. cnss_auto_resume(&pci_priv->pci_dev->dev);
  238. ret = cnss_set_host_sol_value(plat_priv, 1);
  239. } else if (sysfs_streq(cmd, "deassert_host_sol")) {
  240. ret = cnss_set_host_sol_value(plat_priv, 0);
  241. } else if (sysfs_streq(cmd, "pdc_update")) {
  242. if (!sptr)
  243. return -EINVAL;
  244. ret = cnss_aop_send_msg(plat_priv, sptr);
  245. } else if (sysfs_streq(cmd, "dev_check")) {
  246. cnss_wlan_hw_disable_check(plat_priv);
  247. } else if (sysfs_streq(cmd, "dev_enable")) {
  248. cnss_wlan_hw_enable();
  249. } else {
  250. pci_priv = plat_priv->bus_priv;
  251. if (!pci_priv)
  252. return -ENODEV;
  253. if (sysfs_streq(cmd, "download")) {
  254. set_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
  255. ret = cnss_pci_start_mhi(pci_priv);
  256. } else if (sysfs_streq(cmd, "linkup")) {
  257. ret = cnss_resume_pci_link(pci_priv);
  258. } else if (sysfs_streq(cmd, "linkdown")) {
  259. ret = cnss_suspend_pci_link(pci_priv);
  260. } else if (sysfs_streq(cmd, "assert")) {
  261. cnss_pr_info("FW Assert triggered for debug\n");
  262. ret = cnss_force_fw_assert(&pci_priv->pci_dev->dev);
  263. } else if (sysfs_streq(cmd, "set_cbc_done")) {
  264. cnss_pr_dbg("Force set cold boot cal done status\n");
  265. set_bit(CNSS_COLD_BOOT_CAL_DONE,
  266. &plat_priv->driver_state);
  267. } else {
  268. cnss_pr_err("Device boot debugfs command is invalid\n");
  269. ret = -EINVAL;
  270. }
  271. }
  272. if (ret < 0)
  273. return ret;
  274. return count;
  275. }
  276. static int cnss_dev_boot_debug_show(struct seq_file *s, void *data)
  277. {
  278. seq_puts(s, "\nUsage: echo <action> > <debugfs_path>/cnss/dev_boot\n");
  279. seq_puts(s, "<action> can be one of below:\n");
  280. seq_puts(s, "on: turn on device power, assert WLAN_EN\n");
  281. seq_puts(s, "off: de-assert WLAN_EN, turn off device power\n");
  282. seq_puts(s, "enumerate: de-assert PERST, enumerate PCIe\n");
  283. seq_puts(s, "download: download FW and do QMI handshake with FW\n");
  284. seq_puts(s, "linkup: bring up PCIe link\n");
  285. seq_puts(s, "linkdown: bring down PCIe link\n");
  286. seq_puts(s, "powerup: full power on sequence to boot device, download FW and do QMI handshake with FW\n");
  287. seq_puts(s, "shutdown: full power off sequence to shutdown device\n");
  288. seq_puts(s, "assert: trigger firmware assert\n");
  289. seq_puts(s, "set_cbc_done: Set cold boot calibration done status\n");
  290. seq_puts(s, "\npdc_update usage:");
  291. seq_puts(s, "1. echo pdc_update {class: wlan_pdc ss: <pdc_ss>, res: <vreg>.<mode>, <seq>: <val>} > <debugfs_path>/cnss/dev_boot\n");
  292. seq_puts(s, "2. echo pdc_update {class: wlan_pdc ss: <pdc_ss>, res: pdc, enable: <val>} > <debugfs_path>/cnss/dev_boot\n");
  293. seq_puts(s, "assert_host_sol: Assert host sol\n");
  294. seq_puts(s, "deassert_host_sol: Deassert host sol\n");
  295. seq_puts(s, "dev_check: Check whether HW is disabled or not\n");
  296. seq_puts(s, "dev_enable: Enable HW\n");
  297. return 0;
  298. }
  299. static int cnss_dev_boot_debug_open(struct inode *inode, struct file *file)
  300. {
  301. return single_open(file, cnss_dev_boot_debug_show, inode->i_private);
  302. }
  303. static const struct file_operations cnss_dev_boot_debug_fops = {
  304. .read = seq_read,
  305. .write = cnss_dev_boot_debug_write,
  306. .release = single_release,
  307. .open = cnss_dev_boot_debug_open,
  308. .owner = THIS_MODULE,
  309. .llseek = seq_lseek,
  310. };
  311. static int cnss_reg_read_debug_show(struct seq_file *s, void *data)
  312. {
  313. struct cnss_plat_data *plat_priv = s->private;
  314. mutex_lock(&plat_priv->dev_lock);
  315. if (!plat_priv->diag_reg_read_buf) {
  316. seq_puts(s, "\nUsage: echo <mem_type> <offset> <data_len> > <debugfs_path>/cnss/reg_read\n");
  317. seq_puts(s, "Use mem_type = 0xff for register read by IO access, data_len will be ignored\n");
  318. seq_puts(s, "Use mem_type = 0xfe for register read by raw IO access which skips sanity checks, data_len will be ignored\n");
  319. seq_puts(s, "Use other mem_type for register read by QMI\n");
  320. mutex_unlock(&plat_priv->dev_lock);
  321. return 0;
  322. }
  323. seq_printf(s, "\nRegister read, address: 0x%x memory type: 0x%x length: 0x%x\n\n",
  324. plat_priv->diag_reg_read_addr,
  325. plat_priv->diag_reg_read_mem_type,
  326. plat_priv->diag_reg_read_len);
  327. seq_hex_dump(s, "", DUMP_PREFIX_OFFSET, 32, 4,
  328. plat_priv->diag_reg_read_buf,
  329. plat_priv->diag_reg_read_len, false);
  330. plat_priv->diag_reg_read_len = 0;
  331. kfree(plat_priv->diag_reg_read_buf);
  332. plat_priv->diag_reg_read_buf = NULL;
  333. mutex_unlock(&plat_priv->dev_lock);
  334. return 0;
  335. }
  336. static ssize_t cnss_reg_read_debug_write(struct file *fp,
  337. const char __user *user_buf,
  338. size_t count, loff_t *off)
  339. {
  340. struct cnss_plat_data *plat_priv =
  341. ((struct seq_file *)fp->private_data)->private;
  342. char buf[64];
  343. char *sptr, *token;
  344. unsigned int len = 0;
  345. u32 reg_offset, mem_type;
  346. u32 data_len = 0, reg_val = 0;
  347. u8 *reg_buf = NULL;
  348. const char *delim = " ";
  349. int ret = 0;
  350. len = min(count, sizeof(buf) - 1);
  351. if (copy_from_user(buf, user_buf, len))
  352. return -EFAULT;
  353. buf[len] = '\0';
  354. sptr = buf;
  355. token = strsep(&sptr, delim);
  356. if (!token)
  357. return -EINVAL;
  358. if (!sptr)
  359. return -EINVAL;
  360. if (kstrtou32(token, 0, &mem_type))
  361. return -EINVAL;
  362. token = strsep(&sptr, delim);
  363. if (!token)
  364. return -EINVAL;
  365. if (!sptr)
  366. return -EINVAL;
  367. if (kstrtou32(token, 0, &reg_offset))
  368. return -EINVAL;
  369. token = strsep(&sptr, delim);
  370. if (!token)
  371. return -EINVAL;
  372. if (kstrtou32(token, 0, &data_len))
  373. return -EINVAL;
  374. if (mem_type == MMIO_REG_ACCESS_MEM_TYPE ||
  375. mem_type == MMIO_REG_RAW_ACCESS_MEM_TYPE) {
  376. ret = cnss_bus_debug_reg_read(plat_priv, reg_offset, &reg_val,
  377. mem_type ==
  378. MMIO_REG_RAW_ACCESS_MEM_TYPE);
  379. if (ret)
  380. return ret;
  381. cnss_pr_dbg("Read 0x%x from register offset 0x%x\n", reg_val,
  382. reg_offset);
  383. return count;
  384. }
  385. if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
  386. cnss_pr_err("Firmware is not ready yet\n");
  387. return -EINVAL;
  388. }
  389. mutex_lock(&plat_priv->dev_lock);
  390. kfree(plat_priv->diag_reg_read_buf);
  391. plat_priv->diag_reg_read_buf = NULL;
  392. reg_buf = kzalloc(data_len, GFP_KERNEL);
  393. if (!reg_buf) {
  394. mutex_unlock(&plat_priv->dev_lock);
  395. return -ENOMEM;
  396. }
  397. ret = cnss_wlfw_athdiag_read_send_sync(plat_priv, reg_offset,
  398. mem_type, data_len,
  399. reg_buf);
  400. if (ret) {
  401. kfree(reg_buf);
  402. mutex_unlock(&plat_priv->dev_lock);
  403. return ret;
  404. }
  405. plat_priv->diag_reg_read_addr = reg_offset;
  406. plat_priv->diag_reg_read_mem_type = mem_type;
  407. plat_priv->diag_reg_read_len = data_len;
  408. plat_priv->diag_reg_read_buf = reg_buf;
  409. mutex_unlock(&plat_priv->dev_lock);
  410. return count;
  411. }
  412. static int cnss_reg_read_debug_open(struct inode *inode, struct file *file)
  413. {
  414. return single_open(file, cnss_reg_read_debug_show, inode->i_private);
  415. }
  416. static const struct file_operations cnss_reg_read_debug_fops = {
  417. .read = seq_read,
  418. .write = cnss_reg_read_debug_write,
  419. .open = cnss_reg_read_debug_open,
  420. .owner = THIS_MODULE,
  421. .llseek = seq_lseek,
  422. };
  423. static int cnss_reg_write_debug_show(struct seq_file *s, void *data)
  424. {
  425. seq_puts(s, "\nUsage: echo <mem_type> <offset> <reg_val> > <debugfs_path>/cnss/reg_write\n");
  426. seq_puts(s, "Use mem_type = 0xff for register write by IO access\n");
  427. seq_puts(s, "Use mem_type = 0xfe for register write by raw IO access which skips sanity checks\n");
  428. seq_puts(s, "Use other mem_type for register write by QMI\n");
  429. return 0;
  430. }
  431. static ssize_t cnss_reg_write_debug_write(struct file *fp,
  432. const char __user *user_buf,
  433. size_t count, loff_t *off)
  434. {
  435. struct cnss_plat_data *plat_priv =
  436. ((struct seq_file *)fp->private_data)->private;
  437. char buf[64];
  438. char *sptr, *token;
  439. unsigned int len = 0;
  440. u32 reg_offset, mem_type, reg_val;
  441. const char *delim = " ";
  442. int ret = 0;
  443. len = min(count, sizeof(buf) - 1);
  444. if (copy_from_user(buf, user_buf, len))
  445. return -EFAULT;
  446. buf[len] = '\0';
  447. sptr = buf;
  448. token = strsep(&sptr, delim);
  449. if (!token)
  450. return -EINVAL;
  451. if (!sptr)
  452. return -EINVAL;
  453. if (kstrtou32(token, 0, &mem_type))
  454. return -EINVAL;
  455. token = strsep(&sptr, delim);
  456. if (!token)
  457. return -EINVAL;
  458. if (!sptr)
  459. return -EINVAL;
  460. if (kstrtou32(token, 0, &reg_offset))
  461. return -EINVAL;
  462. token = strsep(&sptr, delim);
  463. if (!token)
  464. return -EINVAL;
  465. if (kstrtou32(token, 0, &reg_val))
  466. return -EINVAL;
  467. if (mem_type == MMIO_REG_ACCESS_MEM_TYPE ||
  468. mem_type == MMIO_REG_RAW_ACCESS_MEM_TYPE) {
  469. ret = cnss_bus_debug_reg_write(plat_priv, reg_offset, reg_val,
  470. mem_type ==
  471. MMIO_REG_RAW_ACCESS_MEM_TYPE);
  472. if (ret)
  473. return ret;
  474. cnss_pr_dbg("Wrote 0x%x to register offset 0x%x\n", reg_val,
  475. reg_offset);
  476. return count;
  477. }
  478. if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
  479. cnss_pr_err("Firmware is not ready yet\n");
  480. return -EINVAL;
  481. }
  482. ret = cnss_wlfw_athdiag_write_send_sync(plat_priv, reg_offset, mem_type,
  483. sizeof(u32),
  484. (u8 *)&reg_val);
  485. if (ret)
  486. return ret;
  487. return count;
  488. }
  489. static int cnss_reg_write_debug_open(struct inode *inode, struct file *file)
  490. {
  491. return single_open(file, cnss_reg_write_debug_show, inode->i_private);
  492. }
  493. static const struct file_operations cnss_reg_write_debug_fops = {
  494. .read = seq_read,
  495. .write = cnss_reg_write_debug_write,
  496. .open = cnss_reg_write_debug_open,
  497. .owner = THIS_MODULE,
  498. .llseek = seq_lseek,
  499. };
  500. static ssize_t cnss_runtime_pm_debug_write(struct file *fp,
  501. const char __user *user_buf,
  502. size_t count, loff_t *off)
  503. {
  504. struct cnss_plat_data *plat_priv =
  505. ((struct seq_file *)fp->private_data)->private;
  506. struct cnss_pci_data *pci_priv;
  507. char buf[64];
  508. char *cmd;
  509. unsigned int len = 0;
  510. int ret = 0;
  511. if (!plat_priv)
  512. return -ENODEV;
  513. pci_priv = plat_priv->bus_priv;
  514. if (!pci_priv)
  515. return -ENODEV;
  516. len = min(count, sizeof(buf) - 1);
  517. if (copy_from_user(buf, user_buf, len))
  518. return -EFAULT;
  519. buf[len] = '\0';
  520. cmd = buf;
  521. cnss_pr_dbg("Received runtime_pm debug command: %s\n", cmd);
  522. if (sysfs_streq(cmd, "usage_count")) {
  523. cnss_pci_pm_runtime_show_usage_count(pci_priv);
  524. } else if (sysfs_streq(cmd, "request_resume")) {
  525. ret = cnss_pci_pm_request_resume(pci_priv);
  526. } else if (sysfs_streq(cmd, "resume")) {
  527. ret = cnss_pci_pm_runtime_resume(pci_priv);
  528. } else if (sysfs_streq(cmd, "get")) {
  529. ret = cnss_pci_pm_runtime_get(pci_priv, RTPM_ID_CNSS);
  530. } else if (sysfs_streq(cmd, "get_noresume")) {
  531. cnss_pci_pm_runtime_get_noresume(pci_priv, RTPM_ID_CNSS);
  532. } else if (sysfs_streq(cmd, "put_autosuspend")) {
  533. ret = cnss_pci_pm_runtime_put_autosuspend(pci_priv,
  534. RTPM_ID_CNSS);
  535. } else if (sysfs_streq(cmd, "put_noidle")) {
  536. cnss_pci_pm_runtime_put_noidle(pci_priv, RTPM_ID_CNSS);
  537. } else if (sysfs_streq(cmd, "mark_last_busy")) {
  538. cnss_pci_pm_runtime_mark_last_busy(pci_priv);
  539. } else if (sysfs_streq(cmd, "resume_bus")) {
  540. cnss_pci_resume_bus(pci_priv);
  541. } else if (sysfs_streq(cmd, "suspend_bus")) {
  542. cnss_pci_suspend_bus(pci_priv);
  543. } else {
  544. cnss_pr_err("Runtime PM debugfs command is invalid\n");
  545. ret = -EINVAL;
  546. }
  547. if (ret < 0)
  548. return ret;
  549. return count;
  550. }
  551. static int cnss_runtime_pm_debug_show(struct seq_file *s, void *data)
  552. {
  553. struct cnss_plat_data *plat_priv = s->private;
  554. struct cnss_pci_data *pci_priv;
  555. int i;
  556. if (!plat_priv)
  557. return -ENODEV;
  558. pci_priv = plat_priv->bus_priv;
  559. if (!pci_priv)
  560. return -ENODEV;
  561. seq_puts(s, "\nUsage: echo <action> > <debugfs_path>/cnss/runtime_pm\n");
  562. seq_puts(s, "<action> can be one of below:\n");
  563. seq_puts(s, "usage_count: get runtime PM usage count\n");
  564. seq_puts(s, "reques_resume: do async runtime PM resume\n");
  565. seq_puts(s, "resume: do sync runtime PM resume\n");
  566. seq_puts(s, "get: do runtime PM get\n");
  567. seq_puts(s, "get_noresume: do runtime PM get noresume\n");
  568. seq_puts(s, "put_noidle: do runtime PM put noidle\n");
  569. seq_puts(s, "put_autosuspend: do runtime PM put autosuspend\n");
  570. seq_puts(s, "mark_last_busy: do runtime PM mark last busy\n");
  571. seq_puts(s, "resume_bus: do bus resume only\n");
  572. seq_puts(s, "suspend_bus: do bus suspend only\n");
  573. seq_puts(s, "\nStats:\n");
  574. seq_printf(s, "%s: %u\n", "get count",
  575. atomic_read(&pci_priv->pm_stats.runtime_get));
  576. seq_printf(s, "%s: %u\n", "put count",
  577. atomic_read(&pci_priv->pm_stats.runtime_put));
  578. seq_printf(s, "%-10s%-10s%-10s%-15s%-15s\n",
  579. "id:", "get", "put", "get time(us)", "put time(us)");
  580. for (i = 0; i < RTPM_ID_MAX; i++) {
  581. seq_printf(s, "%d%-9s", i, ":");
  582. seq_printf(s, "%-10d",
  583. atomic_read(&pci_priv->pm_stats.runtime_get_id[i]));
  584. seq_printf(s, "%-10d",
  585. atomic_read(&pci_priv->pm_stats.runtime_put_id[i]));
  586. seq_printf(s, "%-15llu",
  587. pci_priv->pm_stats.runtime_get_timestamp_id[i]);
  588. seq_printf(s, "%-15llu\n",
  589. pci_priv->pm_stats.runtime_put_timestamp_id[i]);
  590. }
  591. return 0;
  592. }
  593. static int cnss_runtime_pm_debug_open(struct inode *inode, struct file *file)
  594. {
  595. return single_open(file, cnss_runtime_pm_debug_show, inode->i_private);
  596. }
  597. static const struct file_operations cnss_runtime_pm_debug_fops = {
  598. .read = seq_read,
  599. .write = cnss_runtime_pm_debug_write,
  600. .open = cnss_runtime_pm_debug_open,
  601. .owner = THIS_MODULE,
  602. .llseek = seq_lseek,
  603. };
  604. static int process_drv(struct cnss_plat_data *plat_priv, bool enabled)
  605. {
  606. if (test_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state)) {
  607. cnss_pr_err("DRV cmd must be used before QMI ready\n");
  608. return -EINVAL;
  609. }
  610. enabled ? cnss_set_feature_list(plat_priv, CNSS_DRV_SUPPORT_V01) :
  611. cnss_clear_feature_list(plat_priv, CNSS_DRV_SUPPORT_V01);
  612. cnss_pr_info("%s DRV suspend\n", enabled ? "enable" : "disable");
  613. return 0;
  614. }
  615. static int process_quirks(struct cnss_plat_data *plat_priv, u32 val)
  616. {
  617. enum cnss_debug_quirks i;
  618. int ret = 0;
  619. unsigned long state;
  620. unsigned long quirks = 0;
  621. for (i = 0, state = val; i < QUIRK_MAX_VALUE; state >>= 1, i++) {
  622. switch (i) {
  623. case DISABLE_DRV:
  624. ret = process_drv(plat_priv, !(state & 0x1));
  625. if (!ret)
  626. quirks |= (state & 0x1) << i;
  627. continue;
  628. default:
  629. quirks |= (state & 0x1) << i;
  630. continue;
  631. }
  632. }
  633. plat_priv->ctrl_params.quirks = quirks;
  634. return 0;
  635. }
  636. static ssize_t cnss_control_params_debug_write(struct file *fp,
  637. const char __user *user_buf,
  638. size_t count, loff_t *off)
  639. {
  640. struct cnss_plat_data *plat_priv =
  641. ((struct seq_file *)fp->private_data)->private;
  642. char buf[64];
  643. char *sptr, *token;
  644. char *cmd;
  645. u32 val;
  646. unsigned int len = 0;
  647. const char *delim = " ";
  648. if (!plat_priv)
  649. return -ENODEV;
  650. len = min(count, sizeof(buf) - 1);
  651. if (copy_from_user(buf, user_buf, len))
  652. return -EFAULT;
  653. buf[len] = '\0';
  654. sptr = buf;
  655. token = strsep(&sptr, delim);
  656. if (!token)
  657. return -EINVAL;
  658. if (!sptr)
  659. return -EINVAL;
  660. cmd = token;
  661. token = strsep(&sptr, delim);
  662. if (!token)
  663. return -EINVAL;
  664. if (kstrtou32(token, 0, &val))
  665. return -EINVAL;
  666. if (strcmp(cmd, "quirks") == 0)
  667. process_quirks(plat_priv, val);
  668. else if (strcmp(cmd, "mhi_timeout") == 0)
  669. plat_priv->ctrl_params.mhi_timeout = val;
  670. else if (strcmp(cmd, "mhi_m2_timeout") == 0)
  671. plat_priv->ctrl_params.mhi_m2_timeout = val;
  672. else if (strcmp(cmd, "qmi_timeout") == 0)
  673. plat_priv->ctrl_params.qmi_timeout = val;
  674. else if (strcmp(cmd, "bdf_type") == 0)
  675. plat_priv->ctrl_params.bdf_type = val;
  676. else if (strcmp(cmd, "time_sync_period") == 0)
  677. plat_priv->ctrl_params.time_sync_period = val;
  678. else if (strcmp(cmd, "kern_log_level") == 0) {
  679. if (val < MAX_LOG)
  680. cnss_kernel_log_level = val;
  681. } else if (strcmp(cmd, "ipc_log_level") == 0) {
  682. return cnss_set_ipc_log_level(val) ? -EINVAL : count;
  683. } else
  684. return -EINVAL;
  685. return count;
  686. }
  687. static int cnss_show_quirks_state(struct seq_file *s,
  688. struct cnss_plat_data *plat_priv)
  689. {
  690. enum cnss_debug_quirks i;
  691. int skip = 0;
  692. unsigned long state;
  693. seq_printf(s, "quirks: 0x%lx (", plat_priv->ctrl_params.quirks);
  694. for (i = 0, state = plat_priv->ctrl_params.quirks;
  695. state != 0; state >>= 1, i++) {
  696. if (!(state & 0x1))
  697. continue;
  698. if (skip++)
  699. seq_puts(s, " | ");
  700. switch (i) {
  701. case LINK_DOWN_SELF_RECOVERY:
  702. seq_puts(s, "LINK_DOWN_SELF_RECOVERY");
  703. continue;
  704. case SKIP_DEVICE_BOOT:
  705. seq_puts(s, "SKIP_DEVICE_BOOT");
  706. continue;
  707. case USE_CORE_ONLY_FW:
  708. seq_puts(s, "USE_CORE_ONLY_FW");
  709. continue;
  710. case SKIP_RECOVERY:
  711. seq_puts(s, "SKIP_RECOVERY");
  712. continue;
  713. case QMI_BYPASS:
  714. seq_puts(s, "QMI_BYPASS");
  715. continue;
  716. case ENABLE_WALTEST:
  717. seq_puts(s, "WALTEST");
  718. continue;
  719. case ENABLE_PCI_LINK_DOWN_PANIC:
  720. seq_puts(s, "PCI_LINK_DOWN_PANIC");
  721. continue;
  722. case FBC_BYPASS:
  723. seq_puts(s, "FBC_BYPASS");
  724. continue;
  725. case ENABLE_DAEMON_SUPPORT:
  726. seq_puts(s, "DAEMON_SUPPORT");
  727. continue;
  728. case DISABLE_DRV:
  729. seq_puts(s, "DISABLE_DRV");
  730. continue;
  731. case DISABLE_IO_COHERENCY:
  732. seq_puts(s, "DISABLE_IO_COHERENCY");
  733. continue;
  734. case IGNORE_PCI_LINK_FAILURE:
  735. seq_puts(s, "IGNORE_PCI_LINK_FAILURE");
  736. continue;
  737. case DISABLE_TIME_SYNC:
  738. seq_puts(s, "DISABLE_TIME_SYNC");
  739. continue;
  740. case FORCE_ONE_MSI:
  741. seq_puts(s, "FORCE_ONE_MSI");
  742. continue;
  743. default:
  744. continue;
  745. }
  746. }
  747. seq_puts(s, ")\n");
  748. return 0;
  749. }
  750. static int cnss_control_params_debug_show(struct seq_file *s, void *data)
  751. {
  752. struct cnss_plat_data *cnss_priv = s->private;
  753. u32 ipc_log_level;
  754. seq_puts(s, "\nUsage: echo <params_name> <value> > <debugfs_path>/cnss/control_params\n");
  755. seq_puts(s, "<params_name> can be one of below:\n");
  756. seq_puts(s, "quirks: Debug quirks for driver\n");
  757. seq_puts(s, "mhi_timeout: Timeout for MHI operation in milliseconds\n");
  758. seq_puts(s, "qmi_timeout: Timeout for QMI message in milliseconds\n");
  759. seq_puts(s, "bdf_type: Type of board data file to be downloaded\n");
  760. seq_puts(s, "time_sync_period: Time period to do time sync with device in milliseconds\n");
  761. seq_puts(s, "\nCurrent value:\n");
  762. cnss_show_quirks_state(s, cnss_priv);
  763. seq_printf(s, "mhi_timeout: %u\n", cnss_priv->ctrl_params.mhi_timeout);
  764. seq_printf(s, "mhi_m2_timeout: %u\n",
  765. cnss_priv->ctrl_params.mhi_m2_timeout);
  766. seq_printf(s, "qmi_timeout: %u\n", cnss_priv->ctrl_params.qmi_timeout);
  767. seq_printf(s, "bdf_type: %u\n", cnss_priv->ctrl_params.bdf_type);
  768. seq_printf(s, "time_sync_period: %u\n",
  769. cnss_priv->ctrl_params.time_sync_period);
  770. seq_printf(s, "kern_log_level: %u\n", cnss_kernel_log_level);
  771. ipc_log_level = cnss_get_ipc_log_level();
  772. if (ipc_log_level != MAX_LOG)
  773. seq_printf(s, "ipc_log_level: %u\n", ipc_log_level);
  774. return 0;
  775. }
  776. static int cnss_control_params_debug_open(struct inode *inode,
  777. struct file *file)
  778. {
  779. return single_open(file, cnss_control_params_debug_show,
  780. inode->i_private);
  781. }
  782. static const struct file_operations cnss_control_params_debug_fops = {
  783. .read = seq_read,
  784. .write = cnss_control_params_debug_write,
  785. .open = cnss_control_params_debug_open,
  786. .owner = THIS_MODULE,
  787. .llseek = seq_lseek,
  788. };
  789. static ssize_t cnss_dynamic_feature_write(struct file *fp,
  790. const char __user *user_buf,
  791. size_t count, loff_t *off)
  792. {
  793. struct cnss_plat_data *plat_priv =
  794. ((struct seq_file *)fp->private_data)->private;
  795. int ret = 0;
  796. u64 val;
  797. ret = kstrtou64_from_user(user_buf, count, 0, &val);
  798. if (ret)
  799. return ret;
  800. plat_priv->dynamic_feature = val;
  801. ret = cnss_wlfw_dynamic_feature_mask_send_sync(plat_priv);
  802. if (ret < 0)
  803. return ret;
  804. return count;
  805. }
  806. static int cnss_dynamic_feature_show(struct seq_file *s, void *data)
  807. {
  808. struct cnss_plat_data *cnss_priv = s->private;
  809. seq_printf(s, "dynamic_feature: 0x%llx\n", cnss_priv->dynamic_feature);
  810. return 0;
  811. }
  812. static int cnss_dynamic_feature_open(struct inode *inode,
  813. struct file *file)
  814. {
  815. return single_open(file, cnss_dynamic_feature_show,
  816. inode->i_private);
  817. }
  818. static const struct file_operations cnss_dynamic_feature_fops = {
  819. .read = seq_read,
  820. .write = cnss_dynamic_feature_write,
  821. .open = cnss_dynamic_feature_open,
  822. .owner = THIS_MODULE,
  823. .llseek = seq_lseek,
  824. };
  825. static int cnss_smmu_fault_timestamp_show(struct seq_file *s, void *data)
  826. {
  827. struct cnss_plat_data *plat_priv = s->private;
  828. struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
  829. if (!pci_priv)
  830. return -ENODEV;
  831. seq_printf(s, "smmu irq cb entry timestamp : %llu ns\n",
  832. pci_priv->smmu_fault_timestamp[SMMU_CB_ENTRY]);
  833. seq_printf(s, "smmu irq cb before doorbell ring timestamp : %llu ns\n",
  834. pci_priv->smmu_fault_timestamp[SMMU_CB_DOORBELL_RING]);
  835. seq_printf(s, "smmu irq cb after doorbell ring timestamp : %llu ns\n",
  836. pci_priv->smmu_fault_timestamp[SMMU_CB_EXIT]);
  837. return 0;
  838. }
  839. static int cnss_smmu_fault_timestamp_open(struct inode *inode,
  840. struct file *file)
  841. {
  842. return single_open(file, cnss_smmu_fault_timestamp_show,
  843. inode->i_private);
  844. }
  845. static const struct file_operations cnss_smmu_fault_timestamp_fops = {
  846. .read = seq_read,
  847. .release = single_release,
  848. .open = cnss_smmu_fault_timestamp_open,
  849. .owner = THIS_MODULE,
  850. .llseek = seq_lseek,
  851. };
  852. #ifdef CONFIG_DEBUG_FS
  853. #ifdef CONFIG_CNSS2_DEBUG
  854. static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv)
  855. {
  856. struct dentry *root_dentry = plat_priv->root_dentry;
  857. debugfs_create_file("dev_boot", 0600, root_dentry, plat_priv,
  858. &cnss_dev_boot_debug_fops);
  859. debugfs_create_file("reg_read", 0600, root_dentry, plat_priv,
  860. &cnss_reg_read_debug_fops);
  861. debugfs_create_file("reg_write", 0600, root_dentry, plat_priv,
  862. &cnss_reg_write_debug_fops);
  863. debugfs_create_file("runtime_pm", 0600, root_dentry, plat_priv,
  864. &cnss_runtime_pm_debug_fops);
  865. debugfs_create_file("control_params", 0600, root_dentry, plat_priv,
  866. &cnss_control_params_debug_fops);
  867. debugfs_create_file("dynamic_feature", 0600, root_dentry, plat_priv,
  868. &cnss_dynamic_feature_fops);
  869. debugfs_create_file("cnss_smmu_fault_timestamp", 0600, root_dentry,
  870. plat_priv, &cnss_smmu_fault_timestamp_fops);
  871. return 0;
  872. }
  873. #else
  874. static int cnss_create_debug_only_node(struct cnss_plat_data *plat_priv)
  875. {
  876. return 0;
  877. }
  878. #endif
  879. int cnss_debugfs_create(struct cnss_plat_data *plat_priv)
  880. {
  881. int ret = 0;
  882. struct dentry *root_dentry;
  883. char name[CNSS_FS_NAME_SIZE];
  884. if (cnss_is_dual_wlan_enabled())
  885. snprintf(name, CNSS_FS_NAME_SIZE, CNSS_FS_NAME "_%d",
  886. plat_priv->plat_idx);
  887. else
  888. snprintf(name, CNSS_FS_NAME_SIZE, CNSS_FS_NAME);
  889. root_dentry = debugfs_create_dir(name, 0);
  890. if (IS_ERR(root_dentry)) {
  891. ret = PTR_ERR(root_dentry);
  892. cnss_pr_err("Unable to create debugfs %d\n", ret);
  893. goto out;
  894. }
  895. plat_priv->root_dentry = root_dentry;
  896. debugfs_create_file("pin_connect_result", 0644, root_dentry, plat_priv,
  897. &cnss_pin_connect_fops);
  898. debugfs_create_file("stats", 0644, root_dentry, plat_priv,
  899. &cnss_stats_fops);
  900. cnss_create_debug_only_node(plat_priv);
  901. out:
  902. return ret;
  903. }
  904. void cnss_debugfs_destroy(struct cnss_plat_data *plat_priv)
  905. {
  906. debugfs_remove_recursive(plat_priv->root_dentry);
  907. }
  908. #else
  909. int cnss_debugfs_create(struct cnss_plat_data *plat_priv)
  910. {
  911. plat_priv->root_dentry = NULL;
  912. return 0;
  913. }
  914. void cnss_debugfs_destroy(struct cnss_plat_data *plat_priv)
  915. {
  916. }
  917. #endif
  918. #if IS_ENABLED(CONFIG_IPC_LOGGING)
  919. void cnss_debug_ipc_log_print(void *log_ctx, char *process, const char *fn,
  920. enum log_level kern_log_level,
  921. enum log_level ipc_log_level, char *fmt, ...)
  922. {
  923. struct va_format vaf;
  924. va_list va_args;
  925. va_start(va_args, fmt);
  926. vaf.fmt = fmt;
  927. vaf.va = &va_args;
  928. if (kern_log_level <= cnss_kernel_log_level) {
  929. switch (kern_log_level) {
  930. case EMERG_LOG:
  931. pr_emerg("cnss: %pV", &vaf);
  932. break;
  933. case ALERT_LOG:
  934. pr_alert("cnss: %pV", &vaf);
  935. break;
  936. case CRIT_LOG:
  937. pr_crit("cnss: %pV", &vaf);
  938. break;
  939. case ERR_LOG:
  940. pr_err("cnss: %pV", &vaf);
  941. break;
  942. case WARNING_LOG:
  943. pr_warn("cnss: %pV", &vaf);
  944. break;
  945. case NOTICE_LOG:
  946. pr_notice("cnss: %pV", &vaf);
  947. break;
  948. case INFO_LOG:
  949. pr_info("cnss: %pV", &vaf);
  950. break;
  951. case DEBUG_LOG:
  952. case DEBUG_HI_LOG:
  953. pr_debug("cnss: %pV", &vaf);
  954. break;
  955. default:
  956. break;
  957. }
  958. }
  959. if (ipc_log_level <= cnss_ipc_log_level)
  960. ipc_log_string(log_ctx, "[%s] %s: %pV", process, fn, &vaf);
  961. va_end(va_args);
  962. }
  963. static int cnss_ipc_logging_init(void)
  964. {
  965. cnss_ipc_log_context = ipc_log_context_create(CNSS_IPC_LOG_PAGES,
  966. "cnss", 0);
  967. if (!cnss_ipc_log_context) {
  968. cnss_pr_err("Unable to create IPC log context\n");
  969. return -EINVAL;
  970. }
  971. cnss_ipc_log_long_context = ipc_log_context_create(CNSS_IPC_LOG_PAGES,
  972. "cnss-long", 0);
  973. if (!cnss_ipc_log_long_context) {
  974. cnss_pr_err("Unable to create IPC long log context\n");
  975. ipc_log_context_destroy(cnss_ipc_log_context);
  976. return -EINVAL;
  977. }
  978. return 0;
  979. }
  980. static void cnss_ipc_logging_deinit(void)
  981. {
  982. if (cnss_ipc_log_long_context) {
  983. ipc_log_context_destroy(cnss_ipc_log_long_context);
  984. cnss_ipc_log_long_context = NULL;
  985. }
  986. if (cnss_ipc_log_context) {
  987. ipc_log_context_destroy(cnss_ipc_log_context);
  988. cnss_ipc_log_context = NULL;
  989. }
  990. }
  991. #else
  992. static int cnss_ipc_logging_init(void) { return 0; }
  993. static void cnss_ipc_logging_deinit(void) {}
  994. void cnss_debug_ipc_log_print(void *log_ctx, char *process, const char *fn,
  995. enum log_level kern_log_level,
  996. enum log_level ipc_log_level, char *fmt, ...)
  997. {
  998. struct va_format vaf;
  999. va_list va_args;
  1000. va_start(va_args, fmt);
  1001. vaf.fmt = fmt;
  1002. vaf.va = &va_args;
  1003. if (kern_log_level <= cnss_kernel_log_level) {
  1004. switch (kern_log_level) {
  1005. case EMERG_LOG:
  1006. pr_emerg("cnss: %pV", &vaf);
  1007. break;
  1008. case ALERT_LOG:
  1009. pr_alert("cnss: %pV", &vaf);
  1010. break;
  1011. case CRIT_LOG:
  1012. pr_crit("cnss: %pV", &vaf);
  1013. break;
  1014. case ERR_LOG:
  1015. pr_err("cnss: %pV", &vaf);
  1016. break;
  1017. case WARNING_LOG:
  1018. pr_warn("cnss: %pV", &vaf);
  1019. break;
  1020. case NOTICE_LOG:
  1021. pr_notice("cnss: %pV", &vaf);
  1022. break;
  1023. case INFO_LOG:
  1024. pr_info("cnss: %pV", &vaf);
  1025. break;
  1026. case DEBUG_LOG:
  1027. case DEBUG_HI_LOG:
  1028. pr_debug("cnss: %pV", &vaf);
  1029. break;
  1030. default:
  1031. break;
  1032. }
  1033. }
  1034. va_end(va_args);
  1035. }
  1036. #endif
  1037. int cnss_debug_init(void)
  1038. {
  1039. return cnss_ipc_logging_init();
  1040. }
  1041. void cnss_debug_deinit(void)
  1042. {
  1043. cnss_ipc_logging_deinit();
  1044. }