/arch/arm/mach-fsm/smd_rpcrouter_xdr.c

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