ota_crypto.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. /* Copyright (c) 2010-2017, 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. */
  13. /* Qualcomm Over the Air (OTA) Crypto driver */
  14. #include <linux/types.h>
  15. #include <linux/platform_device.h>
  16. #include <linux/dma-mapping.h>
  17. #include <linux/kernel.h>
  18. #include <linux/dmapool.h>
  19. #include <linux/interrupt.h>
  20. #include <linux/spinlock.h>
  21. #include <linux/init.h>
  22. #include <linux/module.h>
  23. #include <linux/fs.h>
  24. #include <linux/miscdevice.h>
  25. #include <linux/uaccess.h>
  26. #include <linux/debugfs.h>
  27. #include <linux/qcota.h>
  28. #include "qce.h"
  29. #include "qce_ota.h"
  30. enum qce_ota_oper_enum {
  31. QCE_OTA_F8_OPER = 0,
  32. QCE_OTA_MPKT_F8_OPER = 1,
  33. QCE_OTA_F9_OPER = 2,
  34. QCE_OTA_OPER_LAST
  35. };
  36. struct ota_dev_control;
  37. struct ota_async_req {
  38. struct list_head rlist;
  39. struct completion complete;
  40. int err;
  41. enum qce_ota_oper_enum op;
  42. union {
  43. struct qce_f9_req f9_req;
  44. struct qce_f8_req f8_req;
  45. struct qce_f8_multi_pkt_req f8_mp_req;
  46. } req;
  47. struct ota_qce_dev *pqce;
  48. };
  49. /*
  50. * Register ourselves as a misc device to be able to access the ota
  51. * from userspace.
  52. */
  53. #define QCOTA_DEV "qcota"
  54. struct ota_dev_control {
  55. /* misc device */
  56. struct miscdevice miscdevice;
  57. struct list_head ready_commands;
  58. unsigned magic;
  59. struct list_head qce_dev;
  60. spinlock_t lock;
  61. struct mutex register_lock;
  62. bool registered;
  63. uint32_t total_units;
  64. };
  65. struct ota_qce_dev {
  66. struct list_head qlist;
  67. /* qce handle */
  68. void *qce;
  69. /* platform device */
  70. struct platform_device *pdev;
  71. struct ota_async_req *active_command;
  72. struct tasklet_struct done_tasklet;
  73. struct ota_dev_control *podev;
  74. uint32_t unit;
  75. u32 totalReq;
  76. u32 errReq;
  77. };
  78. #define OTA_MAGIC 0x4f544143
  79. static long qcota_ioctl(struct file *file,
  80. unsigned cmd, unsigned long arg);
  81. static int qcota_open(struct inode *inode, struct file *file);
  82. static int qcota_release(struct inode *inode, struct file *file);
  83. static int start_req(struct ota_qce_dev *pqce, struct ota_async_req *areq);
  84. static const struct file_operations qcota_fops = {
  85. .owner = THIS_MODULE,
  86. .unlocked_ioctl = qcota_ioctl,
  87. .open = qcota_open,
  88. .release = qcota_release,
  89. };
  90. static struct ota_dev_control qcota_dev = {
  91. .miscdevice = {
  92. .minor = MISC_DYNAMIC_MINOR,
  93. .name = "qcota0",
  94. .fops = &qcota_fops,
  95. },
  96. .magic = OTA_MAGIC,
  97. };
  98. #define DEBUG_MAX_FNAME 16
  99. #define DEBUG_MAX_RW_BUF 1024
  100. struct qcota_stat {
  101. u32 f8_req;
  102. u32 f8_mp_req;
  103. u32 f9_req;
  104. u32 f8_op_success;
  105. u32 f8_op_fail;
  106. u32 f8_mp_op_success;
  107. u32 f8_mp_op_fail;
  108. u32 f9_op_success;
  109. u32 f9_op_fail;
  110. };
  111. static struct qcota_stat _qcota_stat;
  112. static struct dentry *_debug_dent;
  113. static char _debug_read_buf[DEBUG_MAX_RW_BUF];
  114. static int _debug_qcota;
  115. static struct ota_dev_control *qcota_control(void)
  116. {
  117. return &qcota_dev;
  118. }
  119. static int qcota_open(struct inode *inode, struct file *file)
  120. {
  121. struct ota_dev_control *podev;
  122. podev = qcota_control();
  123. if (podev == NULL) {
  124. pr_err("%s: no such device %d\n", __func__,
  125. MINOR(inode->i_rdev));
  126. return -ENOENT;
  127. }
  128. file->private_data = podev;
  129. return 0;
  130. }
  131. static int qcota_release(struct inode *inode, struct file *file)
  132. {
  133. struct ota_dev_control *podev;
  134. podev = file->private_data;
  135. if (podev != NULL && podev->magic != OTA_MAGIC) {
  136. pr_err("%s: invalid handle %p\n",
  137. __func__, podev);
  138. }
  139. file->private_data = NULL;
  140. return 0;
  141. }
  142. static void req_done(unsigned long data)
  143. {
  144. struct ota_qce_dev *pqce = (struct ota_qce_dev *)data;
  145. struct ota_dev_control *podev = pqce->podev;
  146. struct ota_async_req *areq;
  147. unsigned long flags;
  148. struct ota_async_req *new_req = NULL;
  149. int ret = 0;
  150. spin_lock_irqsave(&podev->lock, flags);
  151. areq = pqce->active_command;
  152. if (unlikely(areq == NULL))
  153. pr_err("ota_crypto: req_done, no active request\n");
  154. pqce->active_command = NULL;
  155. again:
  156. if (!list_empty(&podev->ready_commands)) {
  157. new_req = container_of(podev->ready_commands.next,
  158. struct ota_async_req, rlist);
  159. list_del(&new_req->rlist);
  160. pqce->active_command = new_req;
  161. spin_unlock_irqrestore(&podev->lock, flags);
  162. new_req->err = 0;
  163. ret = start_req(pqce, new_req); /* start a new request */
  164. } else {
  165. spin_unlock_irqrestore(&podev->lock, flags);
  166. };
  167. if (areq) {
  168. complete(&areq->complete);
  169. areq = NULL;
  170. };
  171. /* if error from issuing request */
  172. if (unlikely(new_req && ret)) {
  173. new_req->err = ret;
  174. complete(&new_req->complete);
  175. ret = 0;
  176. new_req = NULL;
  177. spin_lock_irqsave(&podev->lock, flags);
  178. pqce->active_command = NULL;
  179. /* try to get next new request */
  180. goto again;
  181. }
  182. return;
  183. }
  184. static void f9_cb(void *cookie, unsigned char *icv, unsigned char *iv,
  185. int ret)
  186. {
  187. struct ota_async_req *areq = (struct ota_async_req *) cookie;
  188. struct ota_qce_dev *pqce;
  189. pqce = areq->pqce;
  190. areq->req.f9_req.mac_i = (uint32_t) icv;
  191. if (ret) {
  192. pqce->errReq++;
  193. areq->err = -ENXIO;
  194. } else
  195. areq->err = 0;
  196. tasklet_schedule(&pqce->done_tasklet);
  197. }
  198. static void f8_cb(void *cookie, unsigned char *icv, unsigned char *iv,
  199. int ret)
  200. {
  201. struct ota_async_req *areq = (struct ota_async_req *) cookie;
  202. struct ota_qce_dev *pqce;
  203. pqce = areq->pqce;
  204. if (ret) {
  205. pqce->errReq++;
  206. areq->err = -ENXIO;
  207. } else {
  208. areq->err = 0;
  209. }
  210. tasklet_schedule(&pqce->done_tasklet);
  211. }
  212. static int start_req(struct ota_qce_dev *pqce, struct ota_async_req *areq)
  213. {
  214. struct qce_f9_req *pf9;
  215. struct qce_f8_multi_pkt_req *p_mp_f8;
  216. struct qce_f8_req *pf8;
  217. int ret = 0;
  218. /* command should be on the podev->active_command */
  219. areq->pqce = pqce;
  220. switch (areq->op) {
  221. case QCE_OTA_F8_OPER:
  222. pf8 = &areq->req.f8_req;
  223. ret = qce_f8_req(pqce->qce, pf8, areq, f8_cb);
  224. break;
  225. case QCE_OTA_MPKT_F8_OPER:
  226. p_mp_f8 = &areq->req.f8_mp_req;
  227. ret = qce_f8_multi_pkt_req(pqce->qce, p_mp_f8, areq, f8_cb);
  228. break;
  229. case QCE_OTA_F9_OPER:
  230. pf9 = &areq->req.f9_req;
  231. ret = qce_f9_req(pqce->qce, pf9, areq, f9_cb);
  232. break;
  233. default:
  234. ret = -ENOTSUPP;
  235. break;
  236. };
  237. areq->err = ret;
  238. pqce->totalReq++;
  239. if (ret)
  240. pqce->errReq++;
  241. return ret;
  242. }
  243. static struct ota_qce_dev *schedule_qce(struct ota_dev_control *podev)
  244. {
  245. /* do this function with spinlock set */
  246. struct ota_qce_dev *p;
  247. if (unlikely(list_empty(&podev->qce_dev))) {
  248. pr_err("%s: no valid qce to schedule\n", __func__);
  249. return NULL;
  250. }
  251. list_for_each_entry(p, &podev->qce_dev, qlist) {
  252. if (p->active_command == NULL)
  253. return p;
  254. }
  255. return NULL;
  256. }
  257. static int submit_req(struct ota_async_req *areq, struct ota_dev_control *podev)
  258. {
  259. unsigned long flags;
  260. int ret = 0;
  261. struct qcota_stat *pstat;
  262. struct ota_qce_dev *pqce;
  263. areq->err = 0;
  264. spin_lock_irqsave(&podev->lock, flags);
  265. pqce = schedule_qce(podev);
  266. if (pqce) {
  267. pqce->active_command = areq;
  268. spin_unlock_irqrestore(&podev->lock, flags);
  269. ret = start_req(pqce, areq);
  270. if (ret != 0) {
  271. spin_lock_irqsave(&podev->lock, flags);
  272. pqce->active_command = NULL;
  273. spin_unlock_irqrestore(&podev->lock, flags);
  274. }
  275. } else {
  276. list_add_tail(&areq->rlist, &podev->ready_commands);
  277. spin_unlock_irqrestore(&podev->lock, flags);
  278. }
  279. if (ret == 0)
  280. wait_for_completion(&areq->complete);
  281. pstat = &_qcota_stat;
  282. switch (areq->op) {
  283. case QCE_OTA_F8_OPER:
  284. if (areq->err)
  285. pstat->f8_op_fail++;
  286. else
  287. pstat->f8_op_success++;
  288. break;
  289. case QCE_OTA_MPKT_F8_OPER:
  290. if (areq->err)
  291. pstat->f8_mp_op_fail++;
  292. else
  293. pstat->f8_mp_op_success++;
  294. break;
  295. case QCE_OTA_F9_OPER:
  296. default:
  297. if (areq->err)
  298. pstat->f9_op_fail++;
  299. else
  300. pstat->f9_op_success++;
  301. break;
  302. };
  303. return areq->err;
  304. }
  305. static long qcota_ioctl(struct file *file,
  306. unsigned cmd, unsigned long arg)
  307. {
  308. int err = 0;
  309. struct ota_dev_control *podev;
  310. uint8_t *user_src;
  311. uint8_t *user_dst;
  312. uint8_t *k_buf = NULL;
  313. struct ota_async_req areq;
  314. uint32_t total;
  315. struct qcota_stat *pstat;
  316. podev = file->private_data;
  317. if (podev == NULL || podev->magic != OTA_MAGIC) {
  318. pr_err("%s: invalid handle %p\n",
  319. __func__, podev);
  320. return -ENOENT;
  321. }
  322. /* Verify user arguments. */
  323. if (_IOC_TYPE(cmd) != QCOTA_IOC_MAGIC)
  324. return -ENOTTY;
  325. init_completion(&areq.complete);
  326. pstat = &_qcota_stat;
  327. switch (cmd) {
  328. case QCOTA_F9_REQ:
  329. if (!access_ok(VERIFY_WRITE, (void __user *)arg,
  330. sizeof(struct qce_f9_req)))
  331. return -EFAULT;
  332. if (__copy_from_user(&areq.req.f9_req, (void __user *)arg,
  333. sizeof(struct qce_f9_req)))
  334. return -EFAULT;
  335. user_src = areq.req.f9_req.message;
  336. if (!access_ok(VERIFY_READ, (void __user *)user_src,
  337. areq.req.f9_req.msize))
  338. return -EFAULT;
  339. k_buf = kmalloc(areq.req.f9_req.msize, GFP_KERNEL);
  340. if (k_buf == NULL)
  341. return -ENOMEM;
  342. if (__copy_from_user(k_buf, (void __user *)user_src,
  343. areq.req.f9_req.msize)) {
  344. kfree(k_buf);
  345. return -EFAULT;
  346. }
  347. areq.req.f9_req.message = k_buf;
  348. areq.op = QCE_OTA_F9_OPER;
  349. pstat->f9_req++;
  350. err = submit_req(&areq, podev);
  351. areq.req.f9_req.message = user_src;
  352. if (err == 0 && __copy_to_user((void __user *)arg,
  353. &areq.req.f9_req, sizeof(struct qce_f9_req))) {
  354. err = -EFAULT;
  355. }
  356. kfree(k_buf);
  357. break;
  358. case QCOTA_F8_REQ:
  359. if (!access_ok(VERIFY_WRITE, (void __user *)arg,
  360. sizeof(struct qce_f8_req)))
  361. return -EFAULT;
  362. if (__copy_from_user(&areq.req.f8_req, (void __user *)arg,
  363. sizeof(struct qce_f8_req)))
  364. return -EFAULT;
  365. total = areq.req.f8_req.data_len;
  366. user_src = areq.req.f8_req.data_in;
  367. if (user_src != NULL) {
  368. if (!access_ok(VERIFY_READ, (void __user *)
  369. user_src, total))
  370. return -EFAULT;
  371. };
  372. user_dst = areq.req.f8_req.data_out;
  373. if (!access_ok(VERIFY_WRITE, (void __user *)
  374. user_dst, total))
  375. return -EFAULT;
  376. k_buf = kmalloc(total, GFP_KERNEL);
  377. if (k_buf == NULL)
  378. return -ENOMEM;
  379. /* k_buf returned from kmalloc should be cache line aligned */
  380. if (user_src && __copy_from_user(k_buf,
  381. (void __user *)user_src, total)) {
  382. kfree(k_buf);
  383. return -EFAULT;
  384. }
  385. if (user_src)
  386. areq.req.f8_req.data_in = k_buf;
  387. else
  388. areq.req.f8_req.data_in = NULL;
  389. areq.req.f8_req.data_out = k_buf;
  390. areq.op = QCE_OTA_F8_OPER;
  391. pstat->f8_req++;
  392. err = submit_req(&areq, podev);
  393. if (err == 0 && __copy_to_user(user_dst, k_buf, total))
  394. err = -EFAULT;
  395. kfree(k_buf);
  396. break;
  397. case QCOTA_F8_MPKT_REQ:
  398. if (!access_ok(VERIFY_WRITE, (void __user *)arg,
  399. sizeof(struct qce_f8_multi_pkt_req)))
  400. return -EFAULT;
  401. if (__copy_from_user(&areq.req.f8_mp_req, (void __user *)arg,
  402. sizeof(struct qce_f8_multi_pkt_req)))
  403. return -EFAULT;
  404. total = areq.req.f8_mp_req.num_pkt *
  405. areq.req.f8_mp_req.qce_f8_req.data_len;
  406. user_src = areq.req.f8_mp_req.qce_f8_req.data_in;
  407. if (!access_ok(VERIFY_READ, (void __user *)
  408. user_src, total))
  409. return -EFAULT;
  410. user_dst = areq.req.f8_mp_req.qce_f8_req.data_out;
  411. if (!access_ok(VERIFY_WRITE, (void __user *)
  412. user_dst, total))
  413. return -EFAULT;
  414. k_buf = kmalloc(total, GFP_KERNEL);
  415. if (k_buf == NULL)
  416. return -ENOMEM;
  417. /* k_buf returned from kmalloc should be cache line aligned */
  418. if (__copy_from_user(k_buf, (void __user *)user_src, total)) {
  419. kfree(k_buf);
  420. return -EFAULT;
  421. }
  422. areq.req.f8_mp_req.qce_f8_req.data_out = k_buf;
  423. areq.req.f8_mp_req.qce_f8_req.data_in = k_buf;
  424. areq.op = QCE_OTA_MPKT_F8_OPER;
  425. pstat->f8_mp_req++;
  426. err = submit_req(&areq, podev);
  427. if (err == 0 && __copy_to_user(user_dst, k_buf, total))
  428. err = -EFAULT;
  429. kfree(k_buf);
  430. break;
  431. default:
  432. return -ENOTTY;
  433. }
  434. return err;
  435. }
  436. static int qcota_probe(struct platform_device *pdev)
  437. {
  438. void *handle = NULL;
  439. int rc = 0;
  440. struct ota_dev_control *podev;
  441. struct ce_hw_support ce_support;
  442. struct ota_qce_dev *pqce;
  443. unsigned long flags;
  444. podev = &qcota_dev;
  445. pqce = kzalloc(sizeof(*pqce), GFP_KERNEL);
  446. if (!pqce) {
  447. pr_err("qcota_probe: Memory allocation FAIL\n");
  448. return -ENOMEM;
  449. }
  450. pqce->podev = podev;
  451. pqce->active_command = NULL;
  452. tasklet_init(&pqce->done_tasklet, req_done, (unsigned long)pqce);
  453. /* open qce */
  454. handle = qce_open(pdev, &rc);
  455. if (handle == NULL) {
  456. pr_err("%s: device %s, can not open qce\n",
  457. __func__, pdev->name);
  458. goto err;
  459. }
  460. if (qce_hw_support(handle, &ce_support) < 0 ||
  461. ce_support.ota == false) {
  462. pr_err("%s: device %s, qce does not support ota capability\n",
  463. __func__, pdev->name);
  464. rc = -ENODEV;
  465. goto err;
  466. }
  467. pqce->qce = handle;
  468. pqce->pdev = pdev;
  469. pqce->totalReq = 0;
  470. pqce->errReq = 0;
  471. platform_set_drvdata(pdev, pqce);
  472. mutex_lock(&podev->register_lock);
  473. rc = 0;
  474. if (podev->registered == false) {
  475. rc = misc_register(&podev->miscdevice);
  476. if (rc == 0) {
  477. pqce->unit = podev->total_units;
  478. podev->total_units++;
  479. podev->registered = true;
  480. };
  481. } else {
  482. pqce->unit = podev->total_units;
  483. podev->total_units++;
  484. }
  485. mutex_unlock(&podev->register_lock);
  486. if (rc) {
  487. pr_err("ion: failed to register misc device.\n");
  488. goto err;
  489. }
  490. spin_lock_irqsave(&podev->lock, flags);
  491. list_add_tail(&pqce->qlist, &podev->qce_dev);
  492. spin_unlock_irqrestore(&podev->lock, flags);
  493. return 0;
  494. err:
  495. if (handle)
  496. qce_close(handle);
  497. platform_set_drvdata(pdev, NULL);
  498. tasklet_kill(&pqce->done_tasklet);
  499. kfree(pqce);
  500. return rc;
  501. }
  502. static int qcota_remove(struct platform_device *pdev)
  503. {
  504. struct ota_dev_control *podev;
  505. struct ota_qce_dev *pqce;
  506. unsigned long flags;
  507. pqce = platform_get_drvdata(pdev);
  508. if (!pqce)
  509. return 0;
  510. if (pqce->qce)
  511. qce_close(pqce->qce);
  512. podev = pqce->podev;
  513. if (!podev)
  514. goto ret;
  515. spin_lock_irqsave(&podev->lock, flags);
  516. list_del(&pqce->qlist);
  517. spin_unlock_irqrestore(&podev->lock, flags);
  518. mutex_lock(&podev->register_lock);
  519. if (--podev->total_units == 0) {
  520. if (podev->miscdevice.minor != MISC_DYNAMIC_MINOR)
  521. misc_deregister(&podev->miscdevice);
  522. podev->registered = false;
  523. }
  524. mutex_unlock(&podev->register_lock);
  525. ret:
  526. tasklet_kill(&pqce->done_tasklet);
  527. kfree(pqce);
  528. return 0;
  529. }
  530. static struct of_device_id qcota_match[] = {
  531. { .compatible = "qcom,qcota",
  532. },
  533. {}
  534. };
  535. static struct platform_driver qcota_plat_driver = {
  536. .probe = qcota_probe,
  537. .remove = qcota_remove,
  538. .driver = {
  539. .name = "qcota",
  540. .owner = THIS_MODULE,
  541. .of_match_table = qcota_match,
  542. },
  543. };
  544. static int _disp_stats(void)
  545. {
  546. struct qcota_stat *pstat;
  547. int len = 0;
  548. struct ota_dev_control *podev = &qcota_dev;
  549. unsigned long flags;
  550. struct ota_qce_dev *p;
  551. pstat = &_qcota_stat;
  552. len = scnprintf(_debug_read_buf, DEBUG_MAX_RW_BUF - 1,
  553. "\nQualcomm OTA crypto accelerator Statistics:\n");
  554. len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
  555. " F8 request : %d\n",
  556. pstat->f8_req);
  557. len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
  558. " F8 operation success : %d\n",
  559. pstat->f8_op_success);
  560. len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
  561. " F8 operation fail : %d\n",
  562. pstat->f8_op_fail);
  563. len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
  564. " F8 MP request : %d\n",
  565. pstat->f8_mp_req);
  566. len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
  567. " F8 MP operation success: %d\n",
  568. pstat->f8_mp_op_success);
  569. len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
  570. " F8 MP operation fail : %d\n",
  571. pstat->f8_mp_op_fail);
  572. len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
  573. " F9 request : %d\n",
  574. pstat->f9_req);
  575. len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
  576. " F9 operation success : %d\n",
  577. pstat->f9_op_success);
  578. len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
  579. " F9 operation fail : %d\n",
  580. pstat->f9_op_fail);
  581. spin_lock_irqsave(&podev->lock, flags);
  582. list_for_each_entry(p, &podev->qce_dev, qlist) {
  583. len += scnprintf(
  584. _debug_read_buf + len,
  585. DEBUG_MAX_RW_BUF - len - 1,
  586. " Engine %d Req : %d\n",
  587. p->unit,
  588. p->totalReq
  589. );
  590. len += scnprintf(
  591. _debug_read_buf + len,
  592. DEBUG_MAX_RW_BUF - len - 1,
  593. " Engine %d Req Error : %d\n",
  594. p->unit,
  595. p->errReq
  596. );
  597. }
  598. spin_unlock_irqrestore(&podev->lock, flags);
  599. return len;
  600. }
  601. static int _debug_stats_open(struct inode *inode, struct file *file)
  602. {
  603. file->private_data = inode->i_private;
  604. return 0;
  605. }
  606. static ssize_t _debug_stats_read(struct file *file, char __user *buf,
  607. size_t count, loff_t *ppos)
  608. {
  609. int rc = -EINVAL;
  610. int len;
  611. len = _disp_stats();
  612. if (len <= count)
  613. rc = simple_read_from_buffer((void __user *) buf, len,
  614. ppos, (void *) _debug_read_buf, len);
  615. return rc;
  616. }
  617. static ssize_t _debug_stats_write(struct file *file, const char __user *buf,
  618. size_t count, loff_t *ppos)
  619. {
  620. struct ota_dev_control *podev = &qcota_dev;
  621. unsigned long flags;
  622. struct ota_qce_dev *p;
  623. memset((char *)&_qcota_stat, 0, sizeof(struct qcota_stat));
  624. spin_lock_irqsave(&podev->lock, flags);
  625. list_for_each_entry(p, &podev->qce_dev, qlist) {
  626. p->totalReq = 0;
  627. p->errReq = 0;
  628. }
  629. spin_unlock_irqrestore(&podev->lock, flags);
  630. return count;
  631. }
  632. static const struct file_operations _debug_stats_ops = {
  633. .open = _debug_stats_open,
  634. .read = _debug_stats_read,
  635. .write = _debug_stats_write,
  636. };
  637. static int _qcota_debug_init(void)
  638. {
  639. int rc;
  640. char name[DEBUG_MAX_FNAME];
  641. struct dentry *dent;
  642. _debug_dent = debugfs_create_dir("qcota", NULL);
  643. if (IS_ERR(_debug_dent)) {
  644. pr_err("qcota debugfs_create_dir fail, error %ld\n",
  645. PTR_ERR(_debug_dent));
  646. return PTR_ERR(_debug_dent);
  647. }
  648. snprintf(name, DEBUG_MAX_FNAME-1, "stats-0");
  649. _debug_qcota = 0;
  650. dent = debugfs_create_file(name, 0644, _debug_dent,
  651. &_debug_qcota, &_debug_stats_ops);
  652. if (dent == NULL) {
  653. pr_err("qcota debugfs_create_file fail, error %ld\n",
  654. PTR_ERR(dent));
  655. rc = PTR_ERR(dent);
  656. goto err;
  657. }
  658. return 0;
  659. err:
  660. debugfs_remove_recursive(_debug_dent);
  661. return rc;
  662. }
  663. static int __init qcota_init(void)
  664. {
  665. int rc;
  666. struct ota_dev_control *podev;
  667. rc = _qcota_debug_init();
  668. if (rc)
  669. return rc;
  670. podev = &qcota_dev;
  671. INIT_LIST_HEAD(&podev->ready_commands);
  672. INIT_LIST_HEAD(&podev->qce_dev);
  673. spin_lock_init(&podev->lock);
  674. mutex_init(&podev->register_lock);
  675. podev->registered = false;
  676. podev->total_units = 0;
  677. return platform_driver_register(&qcota_plat_driver);
  678. }
  679. static void __exit qcota_exit(void)
  680. {
  681. debugfs_remove_recursive(_debug_dent);
  682. platform_driver_unregister(&qcota_plat_driver);
  683. }
  684. MODULE_LICENSE("GPL v2");
  685. MODULE_AUTHOR("Rohit Vaswani <rvaswani@codeaurora.org>");
  686. MODULE_DESCRIPTION("Qualcomm Ota Crypto driver");
  687. MODULE_VERSION("1.02");
  688. module_init(qcota_init);
  689. module_exit(qcota_exit);