diagfwd_cntl.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. /* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. */
  12. #include <linux/slab.h>
  13. #include <linux/diagchar.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/kmemleak.h>
  16. #include <linux/delay.h>
  17. #include "diagchar.h"
  18. #include "diagfwd.h"
  19. #include "diagfwd_cntl.h"
  20. /* tracks which peripheral is undergoing SSR */
  21. static uint16_t reg_dirty;
  22. #define HDR_SIZ 8
  23. void diag_clean_reg_fn(struct work_struct *work)
  24. {
  25. struct diag_smd_info *smd_info = container_of(work,
  26. struct diag_smd_info,
  27. diag_notify_update_smd_work);
  28. if (!smd_info)
  29. return;
  30. pr_debug("diag: clean registration for peripheral: %d\n",
  31. smd_info->peripheral);
  32. reg_dirty |= smd_info->peripheral_mask;
  33. diag_clear_reg(smd_info->peripheral);
  34. reg_dirty ^= smd_info->peripheral_mask;
  35. /* Reset the feature mask flag */
  36. driver->rcvd_feature_mask[smd_info->peripheral] = 0;
  37. smd_info->notify_context = 0;
  38. }
  39. void diag_cntl_smd_work_fn(struct work_struct *work)
  40. {
  41. struct diag_smd_info *smd_info = container_of(work,
  42. struct diag_smd_info,
  43. diag_general_smd_work);
  44. if (!smd_info || smd_info->type != SMD_CNTL_TYPE)
  45. return;
  46. if (smd_info->general_context == UPDATE_PERIPHERAL_STM_STATE) {
  47. if (driver->peripheral_supports_stm[smd_info->peripheral] ==
  48. ENABLE_STM) {
  49. int status = 0;
  50. int index = smd_info->peripheral;
  51. status = diag_send_stm_state(smd_info,
  52. (uint8_t)(driver->stm_state_requested[index]));
  53. if (status == 1)
  54. driver->stm_state[index] =
  55. driver->stm_state_requested[index];
  56. }
  57. }
  58. smd_info->general_context = 0;
  59. }
  60. void diag_cntl_stm_notify(struct diag_smd_info *smd_info, int action)
  61. {
  62. if (!smd_info || smd_info->type != SMD_CNTL_TYPE)
  63. return;
  64. if (action == CLEAR_PERIPHERAL_STM_STATE)
  65. driver->peripheral_supports_stm[smd_info->peripheral] =
  66. DISABLE_STM;
  67. }
  68. static void process_stm_feature(struct diag_smd_info *smd_info,
  69. uint8_t feature_mask)
  70. {
  71. if (feature_mask & F_DIAG_OVER_STM) {
  72. driver->peripheral_supports_stm[smd_info->peripheral] =
  73. ENABLE_STM;
  74. smd_info->general_context = UPDATE_PERIPHERAL_STM_STATE;
  75. queue_work(driver->diag_cntl_wq,
  76. &(smd_info->diag_general_smd_work));
  77. } else {
  78. driver->peripheral_supports_stm[smd_info->peripheral] =
  79. DISABLE_STM;
  80. }
  81. }
  82. static void process_hdlc_encoding_feature(struct diag_smd_info *smd_info,
  83. uint8_t feature_mask)
  84. {
  85. /*
  86. * Check if apps supports hdlc encoding and the
  87. * peripheral supports apps hdlc encoding
  88. */
  89. if (driver->supports_apps_hdlc_encoding &&
  90. (feature_mask & F_DIAG_HDLC_ENCODE_IN_APPS_MASK)) {
  91. driver->smd_data[smd_info->peripheral].encode_hdlc =
  92. ENABLE_APPS_HDLC_ENCODING;
  93. if (driver->separate_cmdrsp[smd_info->peripheral] &&
  94. smd_info->peripheral < NUM_SMD_CMD_CHANNELS)
  95. driver->smd_cmd[smd_info->peripheral].encode_hdlc =
  96. ENABLE_APPS_HDLC_ENCODING;
  97. } else {
  98. driver->smd_data[smd_info->peripheral].encode_hdlc =
  99. DISABLE_APPS_HDLC_ENCODING;
  100. if (driver->separate_cmdrsp[smd_info->peripheral] &&
  101. smd_info->peripheral < NUM_SMD_CMD_CHANNELS)
  102. driver->smd_cmd[smd_info->peripheral].encode_hdlc =
  103. DISABLE_APPS_HDLC_ENCODING;
  104. }
  105. }
  106. /* Process the data read from the smd control channel */
  107. int diag_process_smd_cntl_read_data(struct diag_smd_info *smd_info, void *buf,
  108. int total_recd)
  109. {
  110. int data_len = 0, type = -1, count_bytes = 0, j, flag = 0;
  111. struct bindpkt_params_per_process *pkt_params =
  112. kzalloc(sizeof(struct bindpkt_params_per_process), GFP_KERNEL);
  113. struct diag_ctrl_msg *msg;
  114. struct cmd_code_range *range;
  115. struct bindpkt_params *temp;
  116. if (pkt_params == NULL) {
  117. pr_alert("diag: In %s, Memory allocation failure\n",
  118. __func__);
  119. return 0;
  120. }
  121. if (!smd_info) {
  122. pr_err("diag: In %s, No smd info. Not able to read.\n",
  123. __func__);
  124. kfree(pkt_params);
  125. return 0;
  126. }
  127. while (count_bytes + HDR_SIZ <= total_recd) {
  128. type = *(uint32_t *)(buf);
  129. data_len = *(uint32_t *)(buf + 4);
  130. if (type < DIAG_CTRL_MSG_REG ||
  131. type > DIAG_CTRL_MSG_LAST) {
  132. pr_alert("diag: In %s, Invalid Msg type %d proc %d",
  133. __func__, type, smd_info->peripheral);
  134. break;
  135. }
  136. if (data_len < 0 || data_len > total_recd) {
  137. pr_alert("diag: In %s, Invalid data len %d, total_recd: %d, proc %d",
  138. __func__, data_len, total_recd,
  139. smd_info->peripheral);
  140. break;
  141. }
  142. count_bytes = count_bytes+HDR_SIZ+data_len;
  143. if (type == DIAG_CTRL_MSG_REG && total_recd >= count_bytes) {
  144. msg = buf+HDR_SIZ;
  145. range = buf+HDR_SIZ+
  146. sizeof(struct diag_ctrl_msg);
  147. if (msg->count_entries == 0) {
  148. pr_debug("diag: In %s, received reg tbl with no entries\n",
  149. __func__);
  150. buf = buf + HDR_SIZ + data_len;
  151. continue;
  152. }
  153. pkt_params->count = msg->count_entries;
  154. pkt_params->params = kzalloc(pkt_params->count *
  155. sizeof(struct bindpkt_params), GFP_KERNEL);
  156. if (!pkt_params->params) {
  157. pr_alert("diag: In %s, Memory alloc fail for cmd_code: %d, subsys: %d\n",
  158. __func__, msg->cmd_code,
  159. msg->subsysid);
  160. buf = buf + HDR_SIZ + data_len;
  161. continue;
  162. }
  163. temp = pkt_params->params;
  164. for (j = 0; j < pkt_params->count; j++) {
  165. temp->cmd_code = msg->cmd_code;
  166. temp->subsys_id = msg->subsysid;
  167. temp->client_id = smd_info->peripheral;
  168. temp->proc_id = NON_APPS_PROC;
  169. temp->cmd_code_lo = range->cmd_code_lo;
  170. temp->cmd_code_hi = range->cmd_code_hi;
  171. range++;
  172. temp++;
  173. }
  174. flag = 1;
  175. /* peripheral undergoing SSR should not
  176. * record new registration
  177. */
  178. if (!(reg_dirty & smd_info->peripheral_mask))
  179. diagchar_ioctl(NULL, DIAG_IOCTL_COMMAND_REG,
  180. (unsigned long)pkt_params);
  181. else
  182. pr_err("diag: drop reg proc %d\n",
  183. smd_info->peripheral);
  184. kfree(pkt_params->params);
  185. } else if (type == DIAG_CTRL_MSG_FEATURE &&
  186. total_recd >= count_bytes) {
  187. uint8_t feature_mask = 0;
  188. int feature_mask_len = *(int *)(buf+8);
  189. if (feature_mask_len > 0) {
  190. int periph = smd_info->peripheral;
  191. driver->rcvd_feature_mask[smd_info->peripheral]
  192. = 1;
  193. feature_mask = *(uint8_t *)(buf+12);
  194. if (periph == MODEM_DATA)
  195. driver->log_on_demand_support =
  196. feature_mask &
  197. F_DIAG_LOG_ON_DEMAND_RSP_ON_MASTER;
  198. /*
  199. * If apps supports separate cmd/rsp channels
  200. * and the peripheral supports separate cmd/rsp
  201. * channels
  202. */
  203. if (driver->supports_separate_cmdrsp &&
  204. (feature_mask & F_DIAG_REQ_RSP_CHANNEL))
  205. driver->separate_cmdrsp[periph] =
  206. ENABLE_SEPARATE_CMDRSP;
  207. else
  208. driver->separate_cmdrsp[periph] =
  209. DISABLE_SEPARATE_CMDRSP;
  210. /*
  211. * Check if apps supports hdlc encoding and the
  212. * peripheral supports apps hdlc encoding
  213. */
  214. process_hdlc_encoding_feature(smd_info,
  215. feature_mask);
  216. if (feature_mask_len > 1) {
  217. feature_mask = *(uint8_t *)(buf+13);
  218. process_stm_feature(smd_info,
  219. feature_mask);
  220. }
  221. }
  222. flag = 1;
  223. } else if (type != DIAG_CTRL_MSG_REG) {
  224. flag = 1;
  225. }
  226. buf = buf + HDR_SIZ + data_len;
  227. }
  228. kfree(pkt_params);
  229. return flag;
  230. }
  231. void diag_update_proc_vote(uint16_t proc, uint8_t vote)
  232. {
  233. mutex_lock(&driver->real_time_mutex);
  234. if (vote)
  235. driver->proc_active_mask |= proc;
  236. else {
  237. driver->proc_active_mask &= ~proc;
  238. driver->proc_rt_vote_mask |= proc;
  239. }
  240. mutex_unlock(&driver->real_time_mutex);
  241. }
  242. void diag_update_real_time_vote(uint16_t proc, uint8_t real_time)
  243. {
  244. mutex_lock(&driver->real_time_mutex);
  245. if (real_time)
  246. driver->proc_rt_vote_mask |= proc;
  247. else
  248. driver->proc_rt_vote_mask &= ~proc;
  249. mutex_unlock(&driver->real_time_mutex);
  250. }
  251. #ifdef CONFIG_DIAG_OVER_USB
  252. void diag_real_time_work_fn(struct work_struct *work)
  253. {
  254. int temp_real_time = MODE_REALTIME, i;
  255. if (driver->proc_active_mask == 0) {
  256. /* There are no DCI or Memory Device processes. Diag should
  257. * be in Real Time mode irrespective of USB connection
  258. */
  259. temp_real_time = MODE_REALTIME;
  260. } else if (driver->proc_rt_vote_mask & driver->proc_active_mask) {
  261. /* Atleast one process is alive and is voting for Real Time
  262. * data - Diag should be in real time mode irrespective of USB
  263. * connection.
  264. */
  265. temp_real_time = MODE_REALTIME;
  266. } else if (driver->usb_connected) {
  267. /* If USB is connected, check individual process. If Memory
  268. * Device Mode is active, set the mode requested by Memory
  269. * Device process. Set to realtime mode otherwise.
  270. */
  271. if ((driver->proc_rt_vote_mask & DIAG_PROC_MEMORY_DEVICE) == 0)
  272. temp_real_time = MODE_NONREALTIME;
  273. else
  274. temp_real_time = MODE_REALTIME;
  275. } else {
  276. /* We come here if USB is not connected and the active
  277. * processes are voting for Non realtime mode.
  278. */
  279. temp_real_time = MODE_NONREALTIME;
  280. }
  281. if (temp_real_time != driver->real_time_mode) {
  282. for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
  283. diag_send_diag_mode_update_by_smd(&driver->smd_cntl[i],
  284. temp_real_time);
  285. } else {
  286. pr_debug("diag: did not update real time mode, already in the req mode %d",
  287. temp_real_time);
  288. }
  289. if (driver->real_time_update_busy > 0)
  290. driver->real_time_update_busy--;
  291. }
  292. #else
  293. void diag_real_time_work_fn(struct work_struct *work)
  294. {
  295. int temp_real_time = MODE_REALTIME, i;
  296. if (driver->proc_active_mask == 0) {
  297. /* There are no DCI or Memory Device processes. Diag should
  298. * be in Real Time mode.
  299. */
  300. temp_real_time = MODE_REALTIME;
  301. } else if (!(driver->proc_rt_vote_mask & driver->proc_active_mask)) {
  302. /* No active process is voting for real time mode */
  303. temp_real_time = MODE_NONREALTIME;
  304. }
  305. if (temp_real_time != driver->real_time_mode) {
  306. for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
  307. diag_send_diag_mode_update_by_smd(&driver->smd_cntl[i],
  308. temp_real_time);
  309. } else {
  310. pr_warn("diag: did not update real time mode, already in the req mode %d",
  311. temp_real_time);
  312. }
  313. if (driver->real_time_update_busy > 0)
  314. driver->real_time_update_busy--;
  315. }
  316. #endif
  317. void diag_send_diag_mode_update_by_smd(struct diag_smd_info *smd_info,
  318. int real_time)
  319. {
  320. struct diag_ctrl_msg_diagmode diagmode;
  321. char buf[sizeof(struct diag_ctrl_msg_diagmode)];
  322. int msg_size = sizeof(struct diag_ctrl_msg_diagmode);
  323. int wr_size = -ENOMEM, retry_count = 0, timer;
  324. struct diag_smd_info *data = NULL;
  325. if (!smd_info || smd_info->type != SMD_CNTL_TYPE) {
  326. pr_err("diag: In %s, invalid channel info, smd_info: %p type: %d\n",
  327. __func__, smd_info,
  328. ((smd_info) ? smd_info->type : -1));
  329. return;
  330. }
  331. if (smd_info->peripheral < MODEM_DATA ||
  332. smd_info->peripheral > WCNSS_DATA) {
  333. pr_err("diag: In %s, invalid peripheral %d\n", __func__,
  334. smd_info->peripheral);
  335. return;
  336. }
  337. data = &driver->smd_data[smd_info->peripheral];
  338. if (!data)
  339. return;
  340. mutex_lock(&driver->diag_cntl_mutex);
  341. diagmode.ctrl_pkt_id = DIAG_CTRL_MSG_DIAGMODE;
  342. diagmode.ctrl_pkt_data_len = 36;
  343. diagmode.version = 1;
  344. diagmode.sleep_vote = real_time ? 1 : 0;
  345. /*
  346. * 0 - Disables real-time logging (to prevent
  347. * frequent APPS wake-ups, etc.).
  348. * 1 - Enable real-time logging
  349. */
  350. diagmode.real_time = real_time;
  351. diagmode.use_nrt_values = 0;
  352. diagmode.commit_threshold = 0;
  353. diagmode.sleep_threshold = 0;
  354. diagmode.sleep_time = 0;
  355. diagmode.drain_timer_val = 0;
  356. diagmode.event_stale_timer_val = 0;
  357. memcpy(buf, &diagmode, msg_size);
  358. if (smd_info->ch) {
  359. while (retry_count < 3) {
  360. mutex_lock(&smd_info->smd_ch_mutex);
  361. wr_size = smd_write(smd_info->ch, buf, msg_size);
  362. mutex_unlock(&smd_info->smd_ch_mutex);
  363. if (wr_size == -ENOMEM) {
  364. /*
  365. * The smd channel is full. Delay while
  366. * smd processes existing data and smd
  367. * has memory become available. The delay
  368. * of 2000 was determined empirically as
  369. * best value to use.
  370. */
  371. retry_count++;
  372. for (timer = 0; timer < 5; timer++)
  373. udelay(2000);
  374. } else {
  375. data =
  376. &driver->smd_data[smd_info->peripheral];
  377. driver->real_time_mode = real_time;
  378. break;
  379. }
  380. }
  381. if (wr_size != msg_size)
  382. pr_err("diag: proc %d fail feature update %d, tried %d",
  383. smd_info->peripheral,
  384. wr_size, msg_size);
  385. } else {
  386. pr_err("diag: ch invalid, feature update on proc %d\n",
  387. smd_info->peripheral);
  388. }
  389. mutex_unlock(&driver->diag_cntl_mutex);
  390. }
  391. int diag_send_stm_state(struct diag_smd_info *smd_info,
  392. uint8_t stm_control_data)
  393. {
  394. struct diag_ctrl_msg_stm stm_msg;
  395. int msg_size = sizeof(struct diag_ctrl_msg_stm);
  396. int retry_count = 0;
  397. int wr_size = 0;
  398. int success = 0;
  399. if (!smd_info || (smd_info->type != SMD_CNTL_TYPE) ||
  400. (driver->peripheral_supports_stm[smd_info->peripheral] ==
  401. DISABLE_STM)) {
  402. return -EINVAL;
  403. }
  404. if (smd_info->ch) {
  405. stm_msg.ctrl_pkt_id = 21;
  406. stm_msg.ctrl_pkt_data_len = 5;
  407. stm_msg.version = 1;
  408. stm_msg.control_data = stm_control_data;
  409. while (retry_count < 3) {
  410. mutex_lock(&smd_info->smd_ch_mutex);
  411. wr_size = smd_write(smd_info->ch, &stm_msg, msg_size);
  412. mutex_unlock(&smd_info->smd_ch_mutex);
  413. if (wr_size == -ENOMEM) {
  414. /*
  415. * The smd channel is full. Delay while
  416. * smd processes existing data and smd
  417. * has memory become available. The delay
  418. * of 10000 was determined empirically as
  419. * best value to use.
  420. */
  421. retry_count++;
  422. usleep_range(10000, 10000);
  423. } else {
  424. success = 1;
  425. break;
  426. }
  427. }
  428. if (wr_size != msg_size) {
  429. pr_err("diag: In %s, proc %d fail STM update %d, tried %d",
  430. __func__, smd_info->peripheral, wr_size,
  431. msg_size);
  432. success = 0;
  433. }
  434. } else {
  435. pr_err("diag: In %s, ch invalid, STM update on proc %d\n",
  436. __func__, smd_info->peripheral);
  437. }
  438. return success;
  439. }
  440. static int diag_smd_cntl_probe(struct platform_device *pdev)
  441. {
  442. int r = 0;
  443. int index = -1;
  444. const char *channel_name = NULL;
  445. /* open control ports only on 8960 & newer targets */
  446. if (chk_apps_only()) {
  447. if (pdev->id == SMD_APPS_MODEM) {
  448. index = MODEM_DATA;
  449. channel_name = "DIAG_CNTL";
  450. }
  451. #if defined(CONFIG_MSM_N_WAY_SMD)
  452. else if (pdev->id == SMD_APPS_QDSP) {
  453. index = LPASS_DATA;
  454. channel_name = "DIAG_CNTL";
  455. }
  456. #endif
  457. else if (pdev->id == SMD_APPS_WCNSS) {
  458. index = WCNSS_DATA;
  459. channel_name = "APPS_RIVA_CTRL";
  460. }
  461. if (index != -1) {
  462. r = smd_named_open_on_edge(channel_name,
  463. pdev->id,
  464. &driver->smd_cntl[index].ch,
  465. &driver->smd_cntl[index],
  466. diag_smd_notify);
  467. driver->smd_cntl[index].ch_save =
  468. driver->smd_cntl[index].ch;
  469. }
  470. pr_debug("diag: In %s, open SMD CNTL port, Id = %d, r = %d\n",
  471. __func__, pdev->id, r);
  472. }
  473. return 0;
  474. }
  475. static int diagfwd_cntl_runtime_suspend(struct device *dev)
  476. {
  477. dev_dbg(dev, "pm_runtime: suspending...\n");
  478. return 0;
  479. }
  480. static int diagfwd_cntl_runtime_resume(struct device *dev)
  481. {
  482. dev_dbg(dev, "pm_runtime: resuming...\n");
  483. return 0;
  484. }
  485. static const struct dev_pm_ops diagfwd_cntl_dev_pm_ops = {
  486. .runtime_suspend = diagfwd_cntl_runtime_suspend,
  487. .runtime_resume = diagfwd_cntl_runtime_resume,
  488. };
  489. static struct platform_driver msm_smd_ch1_cntl_driver = {
  490. .probe = diag_smd_cntl_probe,
  491. .driver = {
  492. .name = "DIAG_CNTL",
  493. .owner = THIS_MODULE,
  494. .pm = &diagfwd_cntl_dev_pm_ops,
  495. },
  496. };
  497. static struct platform_driver diag_smd_lite_cntl_driver = {
  498. .probe = diag_smd_cntl_probe,
  499. .driver = {
  500. .name = "APPS_RIVA_CTRL",
  501. .owner = THIS_MODULE,
  502. .pm = &diagfwd_cntl_dev_pm_ops,
  503. },
  504. };
  505. void diagfwd_cntl_init(void)
  506. {
  507. int success;
  508. int i;
  509. reg_dirty = 0;
  510. driver->polling_reg_flag = 0;
  511. driver->log_on_demand_support = 1;
  512. driver->diag_cntl_wq = create_singlethread_workqueue("diag_cntl_wq");
  513. for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
  514. success = diag_smd_constructor(&driver->smd_cntl[i], i,
  515. SMD_CNTL_TYPE);
  516. if (!success)
  517. goto err;
  518. }
  519. platform_driver_register(&msm_smd_ch1_cntl_driver);
  520. platform_driver_register(&diag_smd_lite_cntl_driver);
  521. return;
  522. err:
  523. pr_err("diag: Could not initialize diag buffers");
  524. for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
  525. diag_smd_destructor(&driver->smd_cntl[i]);
  526. if (driver->diag_cntl_wq)
  527. destroy_workqueue(driver->diag_cntl_wq);
  528. }
  529. void diagfwd_cntl_exit(void)
  530. {
  531. int i;
  532. for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
  533. diag_smd_destructor(&driver->smd_cntl[i]);
  534. destroy_workqueue(driver->diag_cntl_wq);
  535. destroy_workqueue(driver->diag_real_time_wq);
  536. platform_driver_unregister(&msm_smd_ch1_cntl_driver);
  537. platform_driver_unregister(&diag_smd_lite_cntl_driver);
  538. }