/arch/arm/mach-msm/7x30-lte/smd_rpcrouter_xdr.c

https://github.com/kcs10dc/htc-kernel-msm7x30 · C · 420 lines · 309 code · 87 blank · 24 comment · 41 complexity · 3cb903ef7a1563d2f598b179beb9e88d MD5 · raw file

  1. /* Copyright (c) 2010, Code Aurora Forum. 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. * You should have received a copy of the GNU General Public License
  13. * along with this program; if not, write to the Free Software
  14. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. * 02110-1301, USA.
  16. *
  17. */
  18. /*
  19. * SMD RPCROUTER XDR module.
  20. */
  21. #include <linux/types.h>
  22. #include <linux/string.h>
  23. #include <linux/kernel.h>
  24. #include <linux/delay.h>
  25. #include <linux/sched.h>
  26. #include <linux/slab.h>
  27. #include <mach/msm_rpcrouter.h>
  28. int xdr_send_uint32(struct msm_rpc_xdr *xdr, const uint32_t *value)
  29. {
  30. if ((xdr->out_index + sizeof(uint32_t)) > xdr->out_size) {
  31. pr_err("%s: xdr out buffer full\n", __func__);
  32. return -1;
  33. }
  34. *(uint32_t *)(xdr->out_buf + xdr->out_index) = cpu_to_be32(*value);
  35. xdr->out_index += sizeof(uint32_t);
  36. return 0;
  37. }
  38. int xdr_send_int8(struct msm_rpc_xdr *xdr, const int8_t *value)
  39. {
  40. return xdr_send_uint32(xdr, (uint32_t *)value);
  41. }
  42. int xdr_send_uint8(struct msm_rpc_xdr *xdr, const uint8_t *value)
  43. {
  44. return xdr_send_uint32(xdr, (uint32_t *)value);
  45. }
  46. int xdr_send_int16(struct msm_rpc_xdr *xdr, const int16_t *value)
  47. {
  48. return xdr_send_uint32(xdr, (uint32_t *)value);
  49. }
  50. int xdr_send_uint16(struct msm_rpc_xdr *xdr, const uint16_t *value)
  51. {
  52. return xdr_send_uint32(xdr, (uint32_t *)value);
  53. }
  54. int xdr_send_int32(struct msm_rpc_xdr *xdr, const int32_t *value)
  55. {
  56. return xdr_send_uint32(xdr, (uint32_t *)value);
  57. }
  58. int xdr_send_bytes(struct msm_rpc_xdr *xdr, const void **data,
  59. uint32_t *size)
  60. {
  61. void *buf = xdr->out_buf + xdr->out_index;
  62. uint32_t temp;
  63. if (!size || !data || !*data)
  64. return -1;
  65. temp = *size;
  66. if (temp & 0x3)
  67. temp += 4 - (temp & 0x3);
  68. temp += sizeof(uint32_t);
  69. if ((xdr->out_index + temp) > xdr->out_size) {
  70. pr_err("%s: xdr out buffer full\n", __func__);
  71. return -1;
  72. }
  73. *((uint32_t *)buf) = cpu_to_be32(*size);
  74. buf += sizeof(uint32_t);
  75. memcpy(buf, *data, *size);
  76. buf += *size;
  77. if (*size & 0x3) {
  78. memset(buf, 0, 4 - (*size & 0x3));
  79. buf += 4 - (*size & 0x3);
  80. }
  81. xdr->out_index = buf - xdr->out_buf;
  82. return 0;
  83. }
  84. int xdr_recv_uint32(struct msm_rpc_xdr *xdr, uint32_t *value)
  85. {
  86. if ((xdr->in_index + sizeof(uint32_t)) > xdr->in_size) {
  87. pr_err("%s: xdr in buffer full\n", __func__);
  88. return -1;
  89. }
  90. *value = be32_to_cpu(*(uint32_t *)(xdr->in_buf + xdr->in_index));
  91. xdr->in_index += sizeof(uint32_t);
  92. return 0;
  93. }
  94. int xdr_recv_int8(struct msm_rpc_xdr *xdr, int8_t *value)
  95. {
  96. return xdr_recv_uint32(xdr, (uint32_t *)value);
  97. }
  98. int xdr_recv_uint8(struct msm_rpc_xdr *xdr, uint8_t *value)
  99. {
  100. return xdr_recv_uint32(xdr, (uint32_t *)value);
  101. }
  102. int xdr_recv_int16(struct msm_rpc_xdr *xdr, int16_t *value)
  103. {
  104. return xdr_recv_uint32(xdr, (uint32_t *)value);
  105. }
  106. int xdr_recv_uint16(struct msm_rpc_xdr *xdr, uint16_t *value)
  107. {
  108. return xdr_recv_uint32(xdr, (uint32_t *)value);
  109. }
  110. int xdr_recv_int32(struct msm_rpc_xdr *xdr, int32_t *value)
  111. {
  112. return xdr_recv_uint32(xdr, (uint32_t *)value);
  113. }
  114. int xdr_recv_bytes(struct msm_rpc_xdr *xdr, void **data,
  115. uint32_t *size)
  116. {
  117. void *buf = xdr->in_buf + xdr->in_index;
  118. uint32_t temp;
  119. if (!size || !data)
  120. return -1;
  121. *size = be32_to_cpu(*(uint32_t *)buf);
  122. buf += sizeof(uint32_t);
  123. temp = *size;
  124. if (temp & 0x3)
  125. temp += 4 - (temp & 0x3);
  126. temp += sizeof(uint32_t);
  127. if ((xdr->in_index + temp) > xdr->in_size) {
  128. pr_err("%s: xdr in buffer full\n", __func__);
  129. return -1;
  130. }
  131. if (*size) {
  132. *data = kmalloc(*size, GFP_KERNEL);
  133. if (!*data)
  134. return -1;
  135. memcpy(*data, buf, *size);
  136. buf += *size;
  137. if (*size & 0x3)
  138. buf += 4 - (*size & 0x3);
  139. } else
  140. *data = NULL;
  141. xdr->in_index = buf - xdr->in_buf;
  142. return 0;
  143. }
  144. int xdr_send_pointer(struct msm_rpc_xdr *xdr, void **obj,
  145. uint32_t obj_size, void *xdr_op)
  146. {
  147. uint32_t ptr_valid, rc;
  148. ptr_valid = (*obj != NULL);
  149. rc = xdr_send_uint32(xdr, &ptr_valid);
  150. if (rc)
  151. return rc;
  152. if (!ptr_valid)
  153. return 0;
  154. return ((int (*) (struct msm_rpc_xdr *, void *))xdr_op)(xdr, *obj);
  155. }
  156. int xdr_recv_pointer(struct msm_rpc_xdr *xdr, void **obj,
  157. uint32_t obj_size, void *xdr_op)
  158. {
  159. uint32_t rc, ptr_valid = 0;
  160. rc = xdr_recv_uint32(xdr, &ptr_valid);
  161. if (rc)
  162. return rc;
  163. if (!ptr_valid) {
  164. *obj = NULL;
  165. return 0;
  166. }
  167. *obj = kmalloc(obj_size, GFP_KERNEL);
  168. if (!*obj)
  169. return -1;
  170. rc = ((int (*) (struct msm_rpc_xdr *, void *))xdr_op)(xdr, *obj);
  171. if (rc)
  172. kfree(*obj);
  173. return rc;
  174. }
  175. int xdr_send_array(struct msm_rpc_xdr *xdr, void **addr, uint32_t *size,
  176. uint32_t maxsize, uint32_t elm_size, void *xdr_op)
  177. {
  178. int i, rc;
  179. void *tmp_addr = *addr;
  180. if (!size || !tmp_addr || (*size > maxsize) || !xdr_op)
  181. return -1;
  182. rc = xdr_send_uint32(xdr, size);
  183. if (rc)
  184. return rc;
  185. for (i = 0; i < *size; i++) {
  186. rc = ((int (*) (struct msm_rpc_xdr *, void *))xdr_op)
  187. (xdr, tmp_addr);
  188. if (rc)
  189. return rc;
  190. tmp_addr += elm_size;
  191. }
  192. return 0;
  193. }
  194. int xdr_recv_array(struct msm_rpc_xdr *xdr, void **addr, uint32_t *size,
  195. uint32_t maxsize, uint32_t elm_size, void *xdr_op)
  196. {
  197. int i, rc;
  198. void *tmp_addr;
  199. if (!size || !xdr_op)
  200. return -1;
  201. rc = xdr_recv_uint32(xdr, size);
  202. if (rc)
  203. return rc;
  204. if (*size > maxsize)
  205. return -1;
  206. tmp_addr = kmalloc((*size * elm_size), GFP_KERNEL);
  207. if (!tmp_addr)
  208. return -1;
  209. *addr = tmp_addr;
  210. for (i = 0; i < *size; i++) {
  211. rc = ((int (*) (struct msm_rpc_xdr *, void *))xdr_op)
  212. (xdr, tmp_addr);
  213. if (rc) {
  214. kfree(*addr);
  215. *addr = NULL;
  216. return rc;
  217. }
  218. tmp_addr += elm_size;
  219. }
  220. return 0;
  221. }
  222. int xdr_recv_req(struct msm_rpc_xdr *xdr, struct rpc_request_hdr *req)
  223. {
  224. int rc = 0;
  225. if (!req)
  226. return -1;
  227. rc |= xdr_recv_uint32(xdr, &req->xid); /* xid */
  228. rc |= xdr_recv_uint32(xdr, &req->type); /* type */
  229. rc |= xdr_recv_uint32(xdr, &req->rpc_vers); /* rpc_vers */
  230. rc |= xdr_recv_uint32(xdr, &req->prog); /* prog */
  231. rc |= xdr_recv_uint32(xdr, &req->vers); /* vers */
  232. rc |= xdr_recv_uint32(xdr, &req->procedure); /* procedure */
  233. rc |= xdr_recv_uint32(xdr, &req->cred_flavor); /* cred_flavor */
  234. rc |= xdr_recv_uint32(xdr, &req->cred_length); /* cred_length */
  235. rc |= xdr_recv_uint32(xdr, &req->verf_flavor); /* verf_flavor */
  236. rc |= xdr_recv_uint32(xdr, &req->verf_length); /* verf_length */
  237. return rc;
  238. }
  239. int xdr_recv_reply(struct msm_rpc_xdr *xdr, struct rpc_reply_hdr *reply)
  240. {
  241. int rc = 0;
  242. if (!reply)
  243. return -1;
  244. rc |= xdr_recv_uint32(xdr, &reply->xid); /* xid */
  245. rc |= xdr_recv_uint32(xdr, &reply->type); /* type */
  246. rc |= xdr_recv_uint32(xdr, &reply->reply_stat); /* reply_stat */
  247. /* acc_hdr */
  248. if (reply->reply_stat == RPCMSG_REPLYSTAT_ACCEPTED) {
  249. rc |= xdr_recv_uint32(xdr, &reply->data.acc_hdr.verf_flavor);
  250. rc |= xdr_recv_uint32(xdr, &reply->data.acc_hdr.verf_length);
  251. rc |= xdr_recv_uint32(xdr, &reply->data.acc_hdr.accept_stat);
  252. }
  253. return rc;
  254. }
  255. int xdr_start_request(struct msm_rpc_xdr *xdr, uint32_t prog,
  256. uint32_t ver, uint32_t proc)
  257. {
  258. mutex_lock(&xdr->out_lock);
  259. /* TODO: replace below function with its implementation */
  260. msm_rpc_setup_req((struct rpc_request_hdr *)xdr->out_buf,
  261. prog, ver, proc);
  262. xdr->out_index = sizeof(struct rpc_request_hdr);
  263. return 0;
  264. }
  265. int xdr_start_accepted_reply(struct msm_rpc_xdr *xdr, uint32_t accept_status)
  266. {
  267. struct rpc_reply_hdr *reply;
  268. mutex_lock(&xdr->out_lock);
  269. /* TODO: err if xdr is not cb xdr */
  270. reply = (struct rpc_reply_hdr *)xdr->out_buf;
  271. /* TODO: use xdr functions instead */
  272. reply->xid = ((struct rpc_request_hdr *)(xdr->in_buf))->xid;
  273. reply->type = cpu_to_be32(1); /* reply */
  274. reply->reply_stat = cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED);
  275. reply->data.acc_hdr.accept_stat = cpu_to_be32(accept_status);
  276. reply->data.acc_hdr.verf_flavor = 0;
  277. reply->data.acc_hdr.verf_length = 0;
  278. xdr->out_index = sizeof(*reply);
  279. return 0;
  280. }
  281. int xdr_send_msg(struct msm_rpc_xdr *xdr)
  282. {
  283. int rc = 0;
  284. rc = msm_rpc_write(xdr->ept, xdr->out_buf,
  285. xdr->out_index);
  286. if (rc > 0)
  287. rc = 0;
  288. mutex_unlock(&xdr->out_lock);
  289. return rc;
  290. }
  291. void xdr_init(struct msm_rpc_xdr *xdr)
  292. {
  293. mutex_init(&xdr->out_lock);
  294. init_waitqueue_head(&xdr->in_buf_wait_q);
  295. xdr->in_buf = NULL;
  296. xdr->in_size = 0;
  297. xdr->in_index = 0;
  298. xdr->out_buf = NULL;
  299. xdr->out_size = 0;
  300. xdr->out_index = 0;
  301. }
  302. void xdr_init_input(struct msm_rpc_xdr *xdr, void *buf, uint32_t size)
  303. {
  304. wait_event(xdr->in_buf_wait_q, !(xdr->in_buf));
  305. xdr->in_buf = buf;
  306. xdr->in_size = size;
  307. xdr->in_index = 0;
  308. }
  309. void xdr_init_output(struct msm_rpc_xdr *xdr, void *buf, uint32_t size)
  310. {
  311. xdr->out_buf = buf;
  312. xdr->out_size = size;
  313. xdr->out_index = 0;
  314. }
  315. void xdr_clean_input(struct msm_rpc_xdr *xdr)
  316. {
  317. kfree(xdr->in_buf);
  318. xdr->in_size = 0;
  319. xdr->in_index = 0;
  320. xdr->in_buf = NULL;
  321. wake_up(&xdr->in_buf_wait_q);
  322. }
  323. void xdr_clean_output(struct msm_rpc_xdr *xdr)
  324. {
  325. kfree(xdr->out_buf);
  326. xdr->out_buf = NULL;
  327. xdr->out_size = 0;
  328. xdr->out_index = 0;
  329. }
  330. uint32_t xdr_read_avail(struct msm_rpc_xdr *xdr)
  331. {
  332. return xdr->in_size;
  333. }