ccmni_pfp.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /*****************************************************************************
  2. *
  3. * Filename:
  4. * ---------
  5. * ccmni_pfp.c
  6. *
  7. * Project:
  8. * --------
  9. * YuSu
  10. *
  11. * Description:
  12. * ------------
  13. * MT6516 Cross Chip Modem Network Interface - Packet Framing Protocol
  14. *
  15. * Author:
  16. * -------
  17. * Stanley Chou (mtk01411)
  18. *
  19. ****************************************************************************/
  20. #include <linux/module.h>
  21. #include <linux/device.h>
  22. #include <linux/vmalloc.h>
  23. #include "ccci_common.h"
  24. #include "ccmni_pfp.h"
  25. struct ccmni_record_t ccmni_dev[MAX_PDP_CONT_NUM];
  26. unsigned char frame_cooked_data[MAX_PFP_LEN_FIELD_VALUE];
  27. unsigned char frame_raw_data[MAX_PFP_LEN_FIELD_VALUE + 4];
  28. unsigned char unframe_raw_data[FREE_RAW_DATA_BUF_SIZE];
  29. unsigned char unframe_cooked_data[FREE_COOKED_DATA_BUF_SIZE];
  30. #ifndef __SUPPORT_DYNAMIC_MULTIPLE_FRAME__
  31. struct complete_ippkt_t complete_ippkt_pool[SUPPORT_PKT_NUM];
  32. #endif
  33. #ifndef __SUPPORT_DYNAMIC_MULTIPLE_FRAME__
  34. struct complete_ippkt_t *get_one_available_complete_ippkt_entry()
  35. {
  36. int i = 0;
  37. for (i = 0; i < SUPPORT_PKT_NUM; i++) {
  38. if (complete_ippkt_pool[i].entry_used == 0) {
  39. complete_ippkt_pool[i].entry_used = 1;
  40. return &complete_ippkt_pool[i];
  41. }
  42. }
  43. BUG_ON(1);
  44. return NULL;
  45. }
  46. void release_one_used_complete_ippkt_entry(struct complete_ippkt_t *entry)
  47. {
  48. entry->pkt_size = 0;
  49. entry->pkt_data = NULL;
  50. entry->entry_used = 0;
  51. entry->next = NULL;
  52. }
  53. #endif
  54. void pfp_reset(int ccmni_inx)
  55. {
  56. ccmni_dev[ccmni_inx].unframe_state = PARSE_PFP_FRAME_START_FLAG_STATE;
  57. ccmni_dev[ccmni_inx].pkt_size = 0;
  58. ccmni_dev[ccmni_inx].last_pkt_node = NULL;
  59. }
  60. struct frame_info_t pfp_frame(unsigned char *raw_data, unsigned char *cooked_data,
  61. int cooked_size, int frame_flag, int ccmni_inx)
  62. {
  63. struct frame_info_t entry;
  64. /* One IP packet will only be packed as one frame */
  65. raw_data[0] = PFP_FRAME_START_FLAG;
  66. raw_data[1] = PFP_FRAME_MAGIC_NUM;
  67. /* Length Field Byte#1: Low Byte */
  68. raw_data[2] = (cooked_size & 0x000000FF);
  69. /* Length Field Byte#2: High Byte */
  70. raw_data[3] = ((cooked_size >> 8) & 0x000000FF);
  71. /* Copy data from the input buffer to output buffer */
  72. memcpy(raw_data + 4, cooked_data, cooked_size);
  73. entry.num_frames = 1;
  74. entry.frame_list[0].frame_size = cooked_size + 4;
  75. entry.frame_list[0].frame_data = raw_data;
  76. entry.pending_data_flag = FRAME_END;
  77. entry.consumed_length = cooked_size;
  78. /* NOTE: CCCI Client must update its passed pointer cooked_data by adding
  79. * the size (i.e., cooked_size) after returning from this API.
  80. *
  81. * NOTE: CCCI Client must update its passed poiniter raw_data by adding the
  82. * frame_list[0].frame_size after returning from this API
  83. */
  84. return entry;
  85. }
  86. struct packet_info_t pfp_unframe(unsigned char *cooked_data, int cooked_data_buf_size,
  87. unsigned char *raw_data, int raw_size, int ccmni_inx)
  88. {
  89. /* If this function is invoked for multiple PDP contexts, each one should
  90. * have its own unframe_state belonged to its packet processing
  91. */
  92. int local_raw_size = raw_size;
  93. int local_cooked_data_buf_free_size = cooked_data_buf_size;
  94. unsigned char *local_raw_data = raw_data;
  95. unsigned char *local_cooked_data = cooked_data;
  96. int consumed_length = 0;
  97. int keep_parsing = 1;
  98. int retrieved_num_ip_pkts = 0;
  99. struct packet_info_t entry = { 0 };
  100. /* Lifecycle of CCMNIDev[ccmni_inx].last_node is same as that of PacketInfo entry */
  101. ccmni_dev[ccmni_inx].last_pkt_node = NULL;
  102. do {
  103. #ifdef __PFP_KERNEL_DEBUG__
  104. CCCI_MSG("CCMNI%d: pfp_unframe_state=%d\n", ccmni_inx,
  105. ccmni_dev[ccmni_inx].unframe_state);
  106. #endif
  107. switch (ccmni_dev[ccmni_inx].unframe_state) {
  108. case PARSE_PFP_FRAME_START_FLAG_STATE:
  109. /* if(((unsigned char)local_raw_data[0]) == PFP_FRAME_START_FLAG) */
  110. #ifdef __PFP_KERNEL_DEBUG__
  111. CCCI_MSG
  112. ("CCMNI%d: check start flag-local_raw_data[0]=0x%02x\n",
  113. ccmni_inx, local_raw_data[0]);
  114. #endif
  115. if (local_raw_data[0] == PFP_FRAME_START_FLAG) {
  116. /*
  117. * If the START_FLAG is not found, it will not change the
  118. * unframe_state - still remain as PFP_FRAME_START_FLAG
  119. */
  120. local_raw_data++;
  121. local_raw_size--;
  122. consumed_length++;
  123. break;
  124. }
  125. /* Fall through to check if it is a magic num */
  126. ccmni_dev[ccmni_inx].unframe_state =
  127. PARSE_PFP_FRAME_MAGIC_NUM_STATE;
  128. case PARSE_PFP_FRAME_MAGIC_NUM_STATE:
  129. /* if(((unsigned char)local_raw_data[0]) != PFP_FRAME_MAGIC_NUM) */
  130. #ifdef __PFP_KERNEL_DEBUG__
  131. CCCI_MSG
  132. ("CCMNI%d: check magic num-local_raw_data[0]=0x%02x\n",
  133. ccmni_inx, local_raw_data[0]);
  134. #endif
  135. if (local_raw_data[0] != PFP_FRAME_MAGIC_NUM) {
  136. /* Something is wrong! MAGIC_NUM must follow the START_FLAG */
  137. ccmni_dev[ccmni_inx].unframe_state =
  138. PARSE_PFP_FRAME_START_FLAG_STATE;
  139. } else {
  140. ccmni_dev[ccmni_inx].unframe_state =
  141. PARSE_PFP_FRAME_LENGTH_FIELD_STATE;
  142. }
  143. local_raw_data++;
  144. local_raw_size--;
  145. consumed_length++;
  146. break;
  147. case PARSE_PFP_FRAME_LENGTH_FIELD_STATE:
  148. /* Check if two bytes Length Field can be obtained from the raw_data[] */
  149. #ifdef __PFP_KERNEL_DEBUG__
  150. CCCI_MSG("CCMNI%d: local_raw_size=%d\n",
  151. ccmni_inx, local_raw_size);
  152. #endif
  153. if (local_raw_size >= 2) {
  154. ccmni_dev[ccmni_inx].pkt_size =
  155. ((local_raw_data[1] << 8) |
  156. local_raw_data[0]);
  157. #ifdef __PFP_KERNEL_DEBUG__
  158. CCCI_MSG
  159. ("CCMNI%d: pkt_size=%d,len[0]=0x%02x,len[1]=0x%02x\n",
  160. ccmni_inx,
  161. ccmni_dev[ccmni_inx].pkt_size,
  162. local_raw_data[0],
  163. local_raw_data[1]);
  164. #endif
  165. /* Parse the Length Field */
  166. local_raw_data += 2;
  167. local_raw_size -= 2;
  168. consumed_length += 2;
  169. /* Check if the value is exceeded the maximum size of one IP Packet: 1510 bytes */
  170. if (ccmni_dev[ccmni_inx].pkt_size <=
  171. MAX_PFP_LEN_FIELD_VALUE) {
  172. ccmni_dev
  173. [ccmni_inx].unframe_state =
  174. PARSE_PFP_FRAME_GET_DATA_STATE;
  175. } else {
  176. /* Change state to PARSE_START_FLAG to find the next frame */
  177. #ifdef __PFP_KERNEL_DEBUG__
  178. CCCI_MSG
  179. ("CCMNI%d: Reset decode state then continue to parse\n",
  180. ccmni_inx);
  181. #endif
  182. ccmni_dev
  183. [ccmni_inx].unframe_state =
  184. PARSE_PFP_FRAME_START_FLAG_STATE;
  185. ccmni_dev[ccmni_inx].pkt_size =
  186. 0;
  187. }
  188. } else {
  189. /*
  190. * Not enough information to parse the Length Field's value:
  191. * Keep the state as the PARSE_PFP_FRAME_LENGTH_FIELD_STATE
  192. */
  193. #ifdef __PFP_KERNEL_DEBUG__
  194. CCCI_MSG
  195. ("CCMNI%d: not enough len bytes\n",
  196. ccmni_inx);
  197. #endif
  198. keep_parsing = 0;
  199. }
  200. break;
  201. case PARSE_PFP_FRAME_GET_DATA_STATE:
  202. if (local_raw_size <
  203. ccmni_dev[ccmni_inx].pkt_size) {
  204. /*
  205. * If only partial data, it will not do anything for it:
  206. * Wait for the data can be retrived as one complete IP Packet
  207. */
  208. #ifdef __PFP_KERNEL_DEBUG__
  209. CCCI_MSG
  210. ("CCMNI%d: not enough pkt bytes\n",
  211. ccmni_inx);
  212. #endif
  213. keep_parsing = 0;
  214. break;
  215. }
  216. /*
  217. * It must check the avaialbe space pointed by cooked_data is
  218. * larger than the size of one packet
  219. */
  220. if (local_cooked_data_buf_free_size >=
  221. ccmni_dev[ccmni_inx].pkt_size) {
  222. struct complete_ippkt_t *current_node =
  223. entry.pkt_list;
  224. struct complete_ippkt_t *previous_node
  225. =
  226. ccmni_dev
  227. [ccmni_inx].last_pkt_node;
  228. /*
  229. * It can retrieve a complete IP Packet: Record the start position
  230. * of memory of this IP Packet
  231. */
  232. if (current_node == NULL) {
  233. #ifdef __PFP_KERNEL_DEBUG__
  234. CCCI_MSG
  235. ("CCMNI%d: malloc for first pkt node\n",
  236. ccmni_inx);
  237. #endif
  238. #ifdef __SUPPORT_DYNAMIC_MULTIPLE_FRAME__
  239. current_node =
  240. (struct complete_ippkt_t *)
  241. vmalloc(sizeof
  242. (struct complete_ippkt_t));
  243. #else
  244. /* Find one available entry */
  245. current_node =
  246. (struct complete_ippkt_t *)
  247. get_one_available_complete_ippkt_entry();
  248. #endif
  249. if (current_node != NULL) {
  250. entry.pkt_list = current_node;
  251. } else {
  252. /* Error Handle */
  253. #ifdef __PFP_KERNEL_DEBUG__
  254. CCCI_MSG
  255. ("CCMNI%d: Can't find one available complete_ippkt entry case1\n",
  256. ccmni_inx);
  257. #endif
  258. entry.try_decode_again = 1;
  259. goto error_handle_return;
  260. }
  261. } else {
  262. #ifdef __SUPPORT_DYNAMIC_MULTIPLE_FRAME__
  263. /* Find the 1st position to insert this new node into the linked list */
  264. current_node = (struct complete_ippkt_t *)
  265. vmalloc(sizeof(struct complete_ippkt_t));
  266. #else
  267. /* Find one available entry */
  268. current_node =
  269. (struct complete_ippkt_t *)
  270. get_one_available_complete_ippkt_entry();
  271. #endif
  272. if (current_node != NULL) {
  273. previous_node->next = current_node;
  274. } else {
  275. /* Error Handle */
  276. #ifdef __PFP_KERNEL_DEBUG__
  277. CCCI_MSG
  278. ("CCMNI%d: Can't find one available complete_ippkt entry case2\n",
  279. ccmni_inx);
  280. #endif
  281. entry.try_decode_again = 1;
  282. goto error_handle_return;
  283. }
  284. }
  285. #ifdef __PFP_KERNEL_DEBUG__
  286. CCCI_MSG
  287. ("CCMNI%d: prepare pkt node\n",
  288. ccmni_inx);
  289. #endif
  290. current_node->pkt_size =
  291. ccmni_dev
  292. [ccmni_inx].pkt_size;
  293. /* Copy data from the input buffer to output buffer */
  294. memcpy(local_cooked_data,
  295. local_raw_data,
  296. ccmni_dev
  297. [ccmni_inx].pkt_size);
  298. current_node->pkt_data =
  299. local_cooked_data;
  300. local_cooked_data +=
  301. ccmni_dev
  302. [ccmni_inx].pkt_size;
  303. current_node->next = NULL;
  304. /*
  305. * Remember the last_node for each CCMNI:
  306. * It can directly access the tail
  307. * one without iterating for inserting a new IP Pkt into this list
  308. */
  309. ccmni_dev
  310. [ccmni_inx].last_pkt_node =
  311. current_node;
  312. local_raw_data +=
  313. ccmni_dev
  314. [ccmni_inx].pkt_size;
  315. local_raw_size -=
  316. ccmni_dev
  317. [ccmni_inx].pkt_size;
  318. local_cooked_data_buf_free_size
  319. -=
  320. ccmni_dev
  321. [ccmni_inx].pkt_size;
  322. /*
  323. * consumed_length will add the num of data
  324. * bytes copied from input buffer
  325. * to output buffer
  326. */
  327. consumed_length +=
  328. ccmni_dev
  329. [ccmni_inx].pkt_size;
  330. retrieved_num_ip_pkts++;
  331. /* Change the state to parse the next one */
  332. ccmni_dev
  333. [ccmni_inx].unframe_state =
  334. PARSE_PFP_FRAME_START_FLAG_STATE;
  335. ccmni_dev[ccmni_inx].pkt_size =
  336. 0;
  337. } else {
  338. /*
  339. * Not available free space pointed by cooked_data to put one complete
  340. * IP Packet : Keep the unframe_state as GET_DATA_STATE
  341. */
  342. #ifdef __PFP_KERNEL_DEBUG__
  343. CCCI_MSG
  344. ("CCMNI%d: not enough free space provided by cooked_data\n",
  345. ccmni_inx);
  346. #endif
  347. keep_parsing = 0;
  348. }
  349. break;
  350. default:
  351. break;
  352. }
  353. } while (local_raw_size > 0 && keep_parsing == 1);
  354. error_handle_return:
  355. entry.consumed_length = consumed_length;
  356. entry.num_complete_packets = retrieved_num_ip_pkts;
  357. entry.parse_data_state = ccmni_dev[ccmni_inx].unframe_state;
  358. return entry;
  359. }
  360. void traverse_pkt_list(struct complete_ippkt_t *node)
  361. {
  362. struct complete_ippkt_t *t_pkt_node = node;
  363. struct complete_ippkt_t *prev_pkt_node = NULL;
  364. while (t_pkt_node != NULL) {
  365. #ifdef __PFP_KERNEL_DEBUG__
  366. CCCI_MSG("Packet Node: data=0x%08x, size=%d\n",
  367. t_pkt_node->pkt_data, t_pkt_node->pkt_size);
  368. #endif
  369. prev_pkt_node = t_pkt_node;
  370. t_pkt_node = t_pkt_node->next;
  371. vfree(prev_pkt_node);
  372. }
  373. }