diagfwd_bridge.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. /* Copyright (c) 2012-2013, 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/delay.h>
  14. #include <linux/diagchar.h>
  15. #include <linux/kmemleak.h>
  16. #include <linux/err.h>
  17. #include <linux/workqueue.h>
  18. #include <linux/ratelimit.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/smux.h>
  21. #ifdef CONFIG_DIAG_OVER_USB
  22. #include <mach/usbdiag.h>
  23. #endif
  24. #include "diagchar.h"
  25. #include "diagmem.h"
  26. #include "diagfwd_cntl.h"
  27. #include "diagfwd_smux.h"
  28. #include "diagfwd_hsic.h"
  29. #include "diag_masks.h"
  30. #include "diagfwd_bridge.h"
  31. struct diag_bridge_dev *diag_bridge;
  32. /* diagfwd_connect_bridge is called when the USB mdm channel is connected */
  33. int diagfwd_connect_bridge(int process_cable)
  34. {
  35. uint8_t i;
  36. pr_debug("diag: in %s\n", __func__);
  37. for (i = 0; i < MAX_BRIDGES; i++)
  38. if (diag_bridge[i].enabled)
  39. connect_bridge(process_cable, i);
  40. return 0;
  41. }
  42. void connect_bridge(int process_cable, uint8_t index)
  43. {
  44. int err;
  45. mutex_lock(&diag_bridge[index].bridge_mutex);
  46. /* If the usb cable is being connected */
  47. if (process_cable) {
  48. err = usb_diag_alloc_req(diag_bridge[index].ch, N_MDM_WRITE,
  49. N_MDM_READ);
  50. if (err)
  51. pr_err("diag: unable to alloc USB req for ch %d err:%d\n",
  52. index, err);
  53. diag_bridge[index].usb_connected = 1;
  54. }
  55. if (index == SMUX) {
  56. if (driver->diag_smux_enabled) {
  57. driver->in_busy_smux = 0;
  58. diagfwd_connect_smux();
  59. }
  60. } else {
  61. if (index >= MAX_HSIC_CH) {
  62. pr_err("diag: Invalid hsic channel index %d in %s\n",
  63. index, __func__);
  64. mutex_unlock(&diag_bridge[index].bridge_mutex);
  65. return;
  66. }
  67. if (diag_hsic[index].hsic_device_enabled &&
  68. (driver->logging_mode != MEMORY_DEVICE_MODE ||
  69. diag_hsic[index].hsic_data_requested)) {
  70. diag_hsic[index].in_busy_hsic_read_on_device = 0;
  71. diag_hsic[index].in_busy_hsic_write = 0;
  72. /* If the HSIC (diag_bridge) platform
  73. * device is not open */
  74. if (!diag_hsic[index].hsic_device_opened) {
  75. hsic_diag_bridge_ops[index].ctxt =
  76. (void *)(int)(index);
  77. err = diag_bridge_open(index,
  78. &hsic_diag_bridge_ops[index]);
  79. if (err) {
  80. pr_err("diag: HSIC channel open error: %d\n",
  81. err);
  82. } else {
  83. pr_debug("diag: opened HSIC channel\n");
  84. diag_hsic[index].hsic_device_opened =
  85. 1;
  86. }
  87. } else {
  88. pr_debug("diag: HSIC channel already open\n");
  89. }
  90. /*
  91. * Turn on communication over usb mdm and HSIC,
  92. * if the HSIC device driver is enabled
  93. * and opened
  94. */
  95. if (diag_hsic[index].hsic_device_opened) {
  96. diag_hsic[index].hsic_ch = 1;
  97. /* Poll USB mdm channel to check for data */
  98. if (driver->logging_mode == USB_MODE)
  99. queue_work(diag_bridge[index].wq,
  100. &diag_bridge[index].
  101. diag_read_work);
  102. /* Poll HSIC channel to check for data */
  103. queue_work(diag_bridge[index].wq,
  104. &diag_hsic[index].
  105. diag_read_hsic_work);
  106. }
  107. }
  108. }
  109. mutex_unlock(&diag_bridge[index].bridge_mutex);
  110. }
  111. /*
  112. * diagfwd_disconnect_bridge is called when the USB mdm channel
  113. * is disconnected. So disconnect should happen for all bridges
  114. */
  115. int diagfwd_disconnect_bridge(int process_cable)
  116. {
  117. int i;
  118. pr_debug("diag: In %s, process_cable: %d\n", __func__, process_cable);
  119. for (i = 0; i < MAX_BRIDGES; i++) {
  120. if (diag_bridge[i].enabled) {
  121. mutex_lock(&diag_bridge[i].bridge_mutex);
  122. /* If the usb cable is being disconnected */
  123. if (process_cable) {
  124. diag_bridge[i].usb_connected = 0;
  125. }
  126. if (i == SMUX) {
  127. if (driver->diag_smux_enabled &&
  128. driver->logging_mode == USB_MODE) {
  129. driver->in_busy_smux = 1;
  130. driver->lcid = LCID_INVALID;
  131. driver->smux_connected = 0;
  132. /*
  133. * Turn off communication over usb
  134. * and smux
  135. */
  136. msm_smux_close(LCID_VALID);
  137. }
  138. } else {
  139. if (diag_hsic[i].hsic_device_enabled &&
  140. (driver->logging_mode != MEMORY_DEVICE_MODE
  141. || !diag_hsic[i].hsic_data_requested)) {
  142. diag_hsic[i].
  143. in_busy_hsic_read_on_device = 1;
  144. diag_hsic[i].in_busy_hsic_write = 1;
  145. /* Turn off communication over usb
  146. * and HSIC */
  147. diag_hsic_close(i);
  148. }
  149. }
  150. mutex_unlock(&diag_bridge[i].bridge_mutex);
  151. }
  152. }
  153. return 0;
  154. }
  155. /* Called after the asychronous usb_diag_read() on mdm channel is complete */
  156. int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr)
  157. {
  158. int index = (int)(diag_read_ptr->context);
  159. /* The read of the usb on the mdm (not HSIC/SMUX) has completed */
  160. diag_bridge[index].read_len = diag_read_ptr->actual;
  161. if (index == SMUX) {
  162. if (driver->diag_smux_enabled) {
  163. diagfwd_read_complete_smux();
  164. return 0;
  165. } else {
  166. pr_warning("diag: incorrect callback for smux\n");
  167. }
  168. }
  169. /* If SMUX not enabled, check for HSIC */
  170. diag_hsic[index].in_busy_hsic_read_on_device = 0;
  171. if (!diag_hsic[index].hsic_ch) {
  172. pr_err("DIAG in %s: hsic_ch == 0, ch %d\n", __func__, index);
  173. return 0;
  174. }
  175. /*
  176. * The read of the usb driver on the mdm channel has completed.
  177. * If there is no write on the HSIC in progress, check if the
  178. * read has data to pass on to the HSIC. If so, pass the usb
  179. * mdm data on to the HSIC.
  180. */
  181. if (!diag_hsic[index].in_busy_hsic_write &&
  182. diag_bridge[index].usb_buf_out &&
  183. (diag_bridge[index].read_len > 0)) {
  184. /*
  185. * Initiate the HSIC write. The HSIC write is
  186. * asynchronous. When complete the write
  187. * complete callback function will be called
  188. */
  189. int err;
  190. diag_hsic[index].in_busy_hsic_write = 1;
  191. err = diag_bridge_write(index, diag_bridge[index].usb_buf_out,
  192. diag_bridge[index].read_len);
  193. if (err) {
  194. pr_err_ratelimited("diag: mdm data on HSIC write err: %d\n",
  195. err);
  196. /*
  197. * If the error is recoverable, then clear
  198. * the write flag, so we will resubmit a
  199. * write on the next frame. Otherwise, don't
  200. * resubmit a write on the next frame.
  201. */
  202. if ((-ENODEV) != err)
  203. diag_hsic[index].in_busy_hsic_write = 0;
  204. }
  205. }
  206. /*
  207. * If there is no write of the usb mdm data on the
  208. * HSIC channel
  209. */
  210. if (!diag_hsic[index].in_busy_hsic_write)
  211. queue_work(diag_bridge[index].wq,
  212. &diag_bridge[index].diag_read_work);
  213. return 0;
  214. }
  215. static void diagfwd_bridge_notifier(void *priv, unsigned event,
  216. struct diag_request *d_req)
  217. {
  218. int index;
  219. switch (event) {
  220. case USB_DIAG_CONNECT:
  221. queue_work(driver->diag_wq,
  222. &driver->diag_connect_work);
  223. break;
  224. case USB_DIAG_DISCONNECT:
  225. queue_work(driver->diag_wq,
  226. &driver->diag_disconnect_work);
  227. break;
  228. case USB_DIAG_READ_DONE:
  229. index = (int)(d_req->context);
  230. queue_work(diag_bridge[index].wq,
  231. &diag_bridge[index].usb_read_complete_work);
  232. break;
  233. case USB_DIAG_WRITE_DONE:
  234. index = (int)(d_req->context);
  235. if (index == SMUX && driver->diag_smux_enabled)
  236. diagfwd_write_complete_smux();
  237. else if (diag_hsic[index].hsic_device_enabled)
  238. diagfwd_write_complete_hsic(d_req, index);
  239. break;
  240. default:
  241. pr_err("diag: in %s: Unknown event from USB diag:%u\n",
  242. __func__, event);
  243. break;
  244. }
  245. }
  246. void diagfwd_bridge_init(int index)
  247. {
  248. int ret;
  249. unsigned char name[20];
  250. if (index == HSIC) {
  251. strlcpy(name, "hsic", sizeof(name));
  252. } else if (index == HSIC_2) {
  253. strlcpy(name, "hsic_2", sizeof(name));
  254. } else if (index == SMUX) {
  255. strlcpy(name, "smux", sizeof(name));
  256. } else {
  257. pr_err("diag: incorrect bridge init, instance: %d\n", index);
  258. return;
  259. }
  260. strlcpy(diag_bridge[index].name, name,
  261. sizeof(diag_bridge[index].name));
  262. strlcat(name, "_diag_wq", sizeof(diag_bridge[index].name));
  263. diag_bridge[index].id = index;
  264. diag_bridge[index].wq = create_singlethread_workqueue(name);
  265. diag_bridge[index].read_len = 0;
  266. diag_bridge[index].write_len = 0;
  267. if (diag_bridge[index].usb_buf_out == NULL)
  268. diag_bridge[index].usb_buf_out =
  269. kzalloc(USB_MAX_OUT_BUF, GFP_KERNEL);
  270. if (diag_bridge[index].usb_buf_out == NULL)
  271. goto err;
  272. if (diag_bridge[index].usb_read_ptr == NULL)
  273. diag_bridge[index].usb_read_ptr =
  274. kzalloc(sizeof(struct diag_request), GFP_KERNEL);
  275. if (diag_bridge[index].usb_read_ptr == NULL)
  276. goto err;
  277. if (diag_bridge[index].usb_read_ptr->context == NULL)
  278. diag_bridge[index].usb_read_ptr->context =
  279. kzalloc(sizeof(int), GFP_KERNEL);
  280. if (diag_bridge[index].usb_read_ptr->context == NULL)
  281. goto err;
  282. mutex_init(&diag_bridge[index].bridge_mutex);
  283. if (index == HSIC || index == HSIC_2) {
  284. INIT_WORK(&(diag_bridge[index].usb_read_complete_work),
  285. diag_usb_read_complete_hsic_fn);
  286. #ifdef CONFIG_DIAG_OVER_USB
  287. INIT_WORK(&(diag_bridge[index].diag_read_work),
  288. diag_read_usb_hsic_work_fn);
  289. if (index == HSIC)
  290. diag_bridge[index].ch = usb_diag_open(DIAG_MDM,
  291. (void *)index, diagfwd_bridge_notifier);
  292. else if (index == HSIC_2)
  293. diag_bridge[index].ch = usb_diag_open(DIAG_MDM2,
  294. (void *)index, diagfwd_bridge_notifier);
  295. if (IS_ERR(diag_bridge[index].ch)) {
  296. pr_err("diag: Unable to open USB MDM ch = %d\n", index);
  297. goto err;
  298. } else
  299. diag_bridge[index].enabled = 1;
  300. #endif
  301. } else if (index == SMUX) {
  302. INIT_WORK(&(diag_bridge[index].usb_read_complete_work),
  303. diag_usb_read_complete_smux_fn);
  304. #ifdef CONFIG_DIAG_OVER_USB
  305. INIT_WORK(&(diag_bridge[index].diag_read_work),
  306. diag_read_usb_smux_work_fn);
  307. diag_bridge[index].ch = usb_diag_open(DIAG_QSC, (void *)index,
  308. diagfwd_bridge_notifier);
  309. if (IS_ERR(diag_bridge[index].ch)) {
  310. pr_err("diag: Unable to open USB diag QSC channel\n");
  311. goto err;
  312. } else
  313. diag_bridge[index].enabled = 1;
  314. #endif
  315. ret = platform_driver_register(&msm_diagfwd_smux_driver);
  316. if (ret)
  317. pr_err("diag: could not register SMUX device, ret: %d\n",
  318. ret);
  319. }
  320. return;
  321. err:
  322. pr_err("diag: Could not initialize for bridge forwarding\n");
  323. kfree(diag_bridge[index].usb_buf_out);
  324. kfree(diag_hsic[index].hsic_buf_tbl);
  325. kfree(driver->write_ptr_mdm);
  326. kfree(diag_bridge[index].usb_read_ptr);
  327. if (diag_bridge[index].wq)
  328. destroy_workqueue(diag_bridge[index].wq);
  329. return;
  330. }
  331. void diagfwd_bridge_exit(void)
  332. {
  333. int i;
  334. pr_debug("diag: in %s\n", __func__);
  335. for (i = 0; i < MAX_HSIC_CH; i++) {
  336. if (diag_hsic[i].hsic_device_enabled) {
  337. diag_hsic_close(i);
  338. diag_hsic[i].hsic_device_enabled = 0;
  339. diag_bridge[i].enabled = 0;
  340. }
  341. diag_hsic[i].hsic_inited = 0;
  342. kfree(diag_hsic[i].hsic_buf_tbl);
  343. }
  344. diagmem_exit(driver, POOL_TYPE_ALL);
  345. if (driver->diag_smux_enabled) {
  346. driver->lcid = LCID_INVALID;
  347. kfree(driver->buf_in_smux);
  348. driver->diag_smux_enabled = 0;
  349. diag_bridge[SMUX].enabled = 0;
  350. }
  351. platform_driver_unregister(&msm_hsic_ch_driver);
  352. platform_driver_unregister(&msm_diagfwd_smux_driver);
  353. /* destroy USB MDM specific variables */
  354. for (i = 0; i < MAX_BRIDGES; i++) {
  355. if (diag_bridge[i].enabled) {
  356. #ifdef CONFIG_DIAG_OVER_USB
  357. usb_diag_close(diag_bridge[i].ch);
  358. #endif
  359. kfree(diag_bridge[i].usb_buf_out);
  360. kfree(diag_bridge[i].usb_read_ptr);
  361. destroy_workqueue(diag_bridge[i].wq);
  362. diag_bridge[i].enabled = 0;
  363. }
  364. }
  365. kfree(driver->write_ptr_mdm);
  366. }