htc_recv.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  1. /*
  2. * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for
  5. * any purpose with or without fee is hereby granted, provided that the
  6. * above copyright notice and this permission notice appear in all
  7. * copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  10. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  12. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  13. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  14. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  16. * PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #include "htc_debug.h"
  19. #include "htc_internal.h"
  20. #include "htc_credit_history.h"
  21. #include <qdf_nbuf.h> /* qdf_nbuf_t */
  22. #if defined(WLAN_DEBUG) || defined(DEBUG)
  23. void debug_dump_bytes(uint8_t *buffer, uint16_t length, char *pDescription)
  24. {
  25. int8_t stream[60];
  26. int8_t byteOffsetStr[10];
  27. uint32_t i;
  28. uint16_t offset, count, byteOffset;
  29. A_PRINTF("<---------Dumping %d Bytes : %s ------>\n", length,
  30. pDescription);
  31. count = 0;
  32. offset = 0;
  33. byteOffset = 0;
  34. for (i = 0; i < length; i++) {
  35. A_SNPRINTF(stream + offset, (sizeof(stream) - offset),
  36. "%02X ", buffer[i]);
  37. count++;
  38. offset += 3;
  39. if (count == 16) {
  40. count = 0;
  41. offset = 0;
  42. A_SNPRINTF(byteOffsetStr, sizeof(byteOffset), "%4.4X",
  43. byteOffset);
  44. A_PRINTF("[%s]: %s\n", byteOffsetStr, stream);
  45. qdf_mem_zero(stream, 60);
  46. byteOffset += 16;
  47. }
  48. }
  49. if (offset != 0) {
  50. A_SNPRINTF(byteOffsetStr, sizeof(byteOffset), "%4.4X",
  51. byteOffset);
  52. A_PRINTF("[%s]: %s\n", byteOffsetStr, stream);
  53. }
  54. A_PRINTF("<------------------------------------------------->\n");
  55. }
  56. #else
  57. void debug_dump_bytes(uint8_t *buffer, uint16_t length, char *pDescription)
  58. {
  59. }
  60. #endif
  61. static A_STATUS htc_process_trailer(HTC_TARGET *target,
  62. uint8_t *pBuffer,
  63. int Length, HTC_ENDPOINT_ID FromEndpoint);
  64. static void do_recv_completion_pkt(HTC_ENDPOINT *pEndpoint,
  65. HTC_PACKET *pPacket)
  66. {
  67. if (!pEndpoint->EpCallBacks.EpRecv) {
  68. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  69. ("HTC ep %d has NULL recv callback on packet %pK\n",
  70. pEndpoint->Id,
  71. pPacket));
  72. if (pPacket)
  73. qdf_nbuf_free(pPacket->pPktContext);
  74. } else {
  75. AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
  76. ("HTC calling ep %d recv callback on packet %pK\n",
  77. pEndpoint->Id, pPacket));
  78. pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext,
  79. pPacket);
  80. }
  81. }
  82. static void do_recv_completion(HTC_ENDPOINT *pEndpoint,
  83. HTC_PACKET_QUEUE *pQueueToIndicate)
  84. {
  85. HTC_PACKET *pPacket;
  86. if (HTC_QUEUE_EMPTY(pQueueToIndicate)) {
  87. /* nothing to indicate */
  88. return;
  89. }
  90. while (!HTC_QUEUE_EMPTY(pQueueToIndicate)) {
  91. pPacket = htc_packet_dequeue(pQueueToIndicate);
  92. do_recv_completion_pkt(pEndpoint, pPacket);
  93. }
  94. }
  95. void htc_control_rx_complete(void *Context, HTC_PACKET *pPacket)
  96. {
  97. /* TODO, can't really receive HTC control messages yet.... */
  98. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  99. ("Invalid call to htc_control_rx_complete\n"));
  100. }
  101. void htc_unblock_recv(HTC_HANDLE HTCHandle)
  102. {
  103. /* TODO find the Need in new model */
  104. }
  105. void htc_enable_recv(HTC_HANDLE HTCHandle)
  106. {
  107. /* TODO find the Need in new model */
  108. }
  109. void htc_disable_recv(HTC_HANDLE HTCHandle)
  110. {
  111. /* TODO find the Need in new model */
  112. }
  113. int htc_get_num_recv_buffers(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint)
  114. {
  115. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  116. HTC_ENDPOINT *pEndpoint = &target->endpoint[Endpoint];
  117. return HTC_PACKET_QUEUE_DEPTH(&pEndpoint->RxBufferHoldQueue);
  118. }
  119. HTC_PACKET *allocate_htc_packet_container(HTC_TARGET *target)
  120. {
  121. HTC_PACKET *pPacket;
  122. LOCK_HTC_RX(target);
  123. if (!target->pHTCPacketStructPool) {
  124. UNLOCK_HTC_RX(target);
  125. return NULL;
  126. }
  127. pPacket = target->pHTCPacketStructPool;
  128. target->pHTCPacketStructPool = (HTC_PACKET *) pPacket->ListLink.pNext;
  129. UNLOCK_HTC_RX(target);
  130. pPacket->ListLink.pNext = NULL;
  131. return pPacket;
  132. }
  133. void free_htc_packet_container(HTC_TARGET *target, HTC_PACKET *pPacket)
  134. {
  135. pPacket->ListLink.pPrev = NULL;
  136. LOCK_HTC_RX(target);
  137. if (!target->pHTCPacketStructPool) {
  138. target->pHTCPacketStructPool = pPacket;
  139. pPacket->ListLink.pNext = NULL;
  140. } else {
  141. pPacket->ListLink.pNext =
  142. (DL_LIST *) target->pHTCPacketStructPool;
  143. target->pHTCPacketStructPool = pPacket;
  144. }
  145. UNLOCK_HTC_RX(target);
  146. }
  147. #ifdef RX_SG_SUPPORT
  148. qdf_nbuf_t rx_sg_to_single_netbuf(HTC_TARGET *target)
  149. {
  150. qdf_nbuf_t skb;
  151. uint8_t *anbdata;
  152. uint8_t *anbdata_new;
  153. uint32_t anblen;
  154. qdf_nbuf_t new_skb = NULL;
  155. uint32_t sg_queue_len;
  156. qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
  157. sg_queue_len = qdf_nbuf_queue_len(rx_sg_queue);
  158. if (sg_queue_len <= 1) {
  159. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  160. ("rx_sg_to_single_netbuf: invalid sg queue len %u\n"));
  161. goto _failed;
  162. }
  163. new_skb = qdf_nbuf_alloc(target->ExpRxSgTotalLen, 0, 4, false);
  164. if (!new_skb) {
  165. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  166. ("rx_sg_to_single_netbuf: can't allocate %u size netbuf\n",
  167. target->ExpRxSgTotalLen));
  168. goto _failed;
  169. }
  170. qdf_nbuf_peek_header(new_skb, &anbdata_new, &anblen);
  171. skb = qdf_nbuf_queue_remove(rx_sg_queue);
  172. do {
  173. qdf_nbuf_peek_header(skb, &anbdata, &anblen);
  174. qdf_mem_copy(anbdata_new, anbdata, qdf_nbuf_len(skb));
  175. qdf_nbuf_put_tail(new_skb, qdf_nbuf_len(skb));
  176. anbdata_new += qdf_nbuf_len(skb);
  177. qdf_nbuf_free(skb);
  178. skb = qdf_nbuf_queue_remove(rx_sg_queue);
  179. } while (skb);
  180. RESET_RX_SG_CONFIG(target);
  181. return new_skb;
  182. _failed:
  183. while ((skb = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL)
  184. qdf_nbuf_free(skb);
  185. RESET_RX_SG_CONFIG(target);
  186. return NULL;
  187. }
  188. #endif
  189. QDF_STATUS htc_rx_completion_handler(void *Context, qdf_nbuf_t netbuf,
  190. uint8_t pipeID)
  191. {
  192. QDF_STATUS status = QDF_STATUS_SUCCESS;
  193. HTC_FRAME_HDR *HtcHdr;
  194. HTC_TARGET *target = (HTC_TARGET *) Context;
  195. uint8_t *netdata;
  196. uint32_t netlen;
  197. HTC_ENDPOINT *pEndpoint, *currendpoint;
  198. HTC_PACKET *pPacket;
  199. uint16_t payloadLen;
  200. uint32_t trailerlen = 0;
  201. uint8_t htc_ep_id;
  202. int i;
  203. #ifdef HTC_MSG_WAKEUP_FROM_SUSPEND_ID
  204. struct htc_init_info *info;
  205. #endif
  206. #ifdef RX_SG_SUPPORT
  207. LOCK_HTC_RX(target);
  208. if (target->IsRxSgInprogress) {
  209. target->CurRxSgTotalLen += qdf_nbuf_len(netbuf);
  210. qdf_nbuf_queue_add(&target->RxSgQueue, netbuf);
  211. if (target->CurRxSgTotalLen == target->ExpRxSgTotalLen) {
  212. netbuf = rx_sg_to_single_netbuf(target);
  213. if (!netbuf) {
  214. UNLOCK_HTC_RX(target);
  215. goto _out;
  216. }
  217. } else {
  218. netbuf = NULL;
  219. UNLOCK_HTC_RX(target);
  220. goto _out;
  221. }
  222. }
  223. UNLOCK_HTC_RX(target);
  224. #endif
  225. netdata = qdf_nbuf_data(netbuf);
  226. netlen = qdf_nbuf_len(netbuf);
  227. HtcHdr = (HTC_FRAME_HDR *) netdata;
  228. do {
  229. htc_ep_id = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, ENDPOINTID);
  230. if (htc_ep_id >= ENDPOINT_MAX) {
  231. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  232. ("HTC Rx: invalid EndpointID=%d\n",
  233. htc_ep_id));
  234. debug_dump_bytes((uint8_t *) HtcHdr,
  235. sizeof(HTC_FRAME_HDR),
  236. "BAD HTC Header");
  237. status = QDF_STATUS_E_FAILURE;
  238. DPTRACE(qdf_dp_trace(
  239. netbuf,
  240. QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
  241. QDF_TRACE_DEFAULT_PDEV_ID,
  242. qdf_nbuf_data_addr(netbuf),
  243. sizeof(qdf_nbuf_data(netbuf)),
  244. QDF_RX));
  245. break;
  246. }
  247. pEndpoint = &target->endpoint[htc_ep_id];
  248. /*
  249. * If this endpoint that received a message from the target has
  250. * a to-target HIF pipe whose send completions are polled rather
  251. * than interrupt driven, this is a good point to ask HIF to
  252. * check whether it has any completed sends to handle.
  253. */
  254. if (pEndpoint->ul_is_polled) {
  255. for (i = 0; i < ENDPOINT_MAX; i++) {
  256. currendpoint = &target->endpoint[i];
  257. if ((currendpoint->DL_PipeID ==
  258. pEndpoint->DL_PipeID) &&
  259. currendpoint->ul_is_polled) {
  260. htc_send_complete_check(currendpoint,
  261. 1);
  262. }
  263. }
  264. }
  265. payloadLen = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, PAYLOADLEN);
  266. if (netlen < (payloadLen + HTC_HDR_LENGTH)) {
  267. #ifdef RX_SG_SUPPORT
  268. LOCK_HTC_RX(target);
  269. target->IsRxSgInprogress = true;
  270. qdf_nbuf_queue_init(&target->RxSgQueue);
  271. qdf_nbuf_queue_add(&target->RxSgQueue, netbuf);
  272. target->ExpRxSgTotalLen = (payloadLen + HTC_HDR_LENGTH);
  273. target->CurRxSgTotalLen += netlen;
  274. UNLOCK_HTC_RX(target);
  275. netbuf = NULL;
  276. break;
  277. #else
  278. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  279. ("HTC Rx: insufficient length, got:%d expected =%zu\n",
  280. netlen, payloadLen + HTC_HDR_LENGTH));
  281. debug_dump_bytes((uint8_t *) HtcHdr,
  282. sizeof(HTC_FRAME_HDR),
  283. "BAD RX packet length");
  284. status = QDF_STATUS_E_FAILURE;
  285. DPTRACE(qdf_dp_trace(
  286. netbuf,
  287. QDF_DP_TRACE_HTC_PACKET_PTR_RECORD,
  288. QDF_TRACE_DEFAULT_PDEV_ID,
  289. qdf_nbuf_data_addr(netbuf),
  290. sizeof(qdf_nbuf_data(netbuf)),
  291. QDF_RX));
  292. break;
  293. #endif
  294. }
  295. #ifdef HTC_EP_STAT_PROFILING
  296. LOCK_HTC_RX(target);
  297. INC_HTC_EP_STAT(pEndpoint, RxReceived, 1);
  298. UNLOCK_HTC_RX(target);
  299. #endif
  300. /* if (IS_TX_CREDIT_FLOW_ENABLED(pEndpoint)) { */
  301. {
  302. uint8_t temp;
  303. A_STATUS temp_status;
  304. /* get flags to check for trailer */
  305. temp = HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR, FLAGS);
  306. if (temp & HTC_FLAGS_RECV_TRAILER) {
  307. /* extract the trailer length */
  308. temp =
  309. HTC_GET_FIELD(HtcHdr, HTC_FRAME_HDR,
  310. CONTROLBYTES0);
  311. if ((temp < sizeof(HTC_RECORD_HDR))
  312. || (temp > payloadLen)) {
  313. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  314. ("htc_rx_completion_handler, invalid header (payloadlength should be :%d, CB[0] is:%d)\n",
  315. payloadLen, temp));
  316. status = QDF_STATUS_E_INVAL;
  317. break;
  318. }
  319. trailerlen = temp;
  320. /* process trailer data that follows HDR +
  321. * application payload
  322. */
  323. temp_status = htc_process_trailer(target,
  324. ((uint8_t *) HtcHdr +
  325. HTC_HDR_LENGTH +
  326. payloadLen - temp),
  327. temp, htc_ep_id);
  328. if (A_FAILED(temp_status)) {
  329. status = QDF_STATUS_E_FAILURE;
  330. break;
  331. }
  332. }
  333. }
  334. if (((int)payloadLen - (int)trailerlen) <= 0) {
  335. /* 0 length packet with trailer data, just drop these */
  336. break;
  337. }
  338. if (htc_ep_id == ENDPOINT_0) {
  339. uint16_t message_id;
  340. HTC_UNKNOWN_MSG *htc_msg;
  341. bool wow_nack;
  342. /* remove HTC header */
  343. qdf_nbuf_pull_head(netbuf, HTC_HDR_LENGTH);
  344. netdata = qdf_nbuf_data(netbuf);
  345. netlen = qdf_nbuf_len(netbuf);
  346. htc_msg = (HTC_UNKNOWN_MSG *) netdata;
  347. message_id = HTC_GET_FIELD(htc_msg, HTC_UNKNOWN_MSG,
  348. MESSAGEID);
  349. switch (message_id) {
  350. default:
  351. /* handle HTC control message */
  352. if (target->CtrlResponseProcessing) {
  353. /* this is a fatal error, target should
  354. * not be sending unsolicited messages
  355. * on the endpoint 0
  356. */
  357. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  358. ("HTC Rx Ctrl still processing\n"));
  359. status = QDF_STATUS_E_FAILURE;
  360. QDF_BUG(false);
  361. break;
  362. }
  363. LOCK_HTC_RX(target);
  364. target->CtrlResponseLength =
  365. min((int)netlen,
  366. HTC_MAX_CONTROL_MESSAGE_LENGTH);
  367. qdf_mem_copy(target->CtrlResponseBuffer,
  368. netdata,
  369. target->CtrlResponseLength);
  370. /* Requester will clear this flag */
  371. target->CtrlResponseProcessing = true;
  372. UNLOCK_HTC_RX(target);
  373. qdf_event_set(&target->ctrl_response_valid);
  374. break;
  375. #ifdef HTC_MSG_WAKEUP_FROM_SUSPEND_ID
  376. case HTC_MSG_WAKEUP_FROM_SUSPEND_ID:
  377. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  378. ("Received initial wake up"));
  379. htc_credit_record(HTC_INITIAL_WAKE_UP,
  380. pEndpoint->TxCredits,
  381. HTC_PACKET_QUEUE_DEPTH(
  382. &pEndpoint->TxQueue));
  383. info = &target->HTCInitInfo;
  384. if (info && info->target_initial_wakeup_cb)
  385. info->target_initial_wakeup_cb(
  386. info->target_psoc);
  387. else
  388. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  389. ("No initial wake up cb"));
  390. break;
  391. #endif
  392. case HTC_MSG_SEND_SUSPEND_COMPLETE:
  393. wow_nack = false;
  394. htc_credit_record(HTC_SUSPEND_ACK,
  395. pEndpoint->TxCredits,
  396. HTC_PACKET_QUEUE_DEPTH(
  397. &pEndpoint->TxQueue));
  398. target->HTCInitInfo.TargetSendSuspendComplete(
  399. target->HTCInitInfo.target_psoc,
  400. wow_nack);
  401. break;
  402. case HTC_MSG_NACK_SUSPEND:
  403. wow_nack = true;
  404. htc_credit_record(HTC_SUSPEND_ACK,
  405. pEndpoint->TxCredits,
  406. HTC_PACKET_QUEUE_DEPTH(
  407. &pEndpoint->TxQueue));
  408. target->HTCInitInfo.TargetSendSuspendComplete(
  409. target->HTCInitInfo.target_psoc,
  410. wow_nack);
  411. break;
  412. }
  413. qdf_nbuf_free(netbuf);
  414. netbuf = NULL;
  415. break;
  416. }
  417. /* the current message based HIF architecture allocates net bufs
  418. * for recv packets since this layer bridges that HIF to upper
  419. * layers , which expects HTC packets, we form the packets here
  420. * TODO_FIXME
  421. */
  422. pPacket = allocate_htc_packet_container(target);
  423. if (!pPacket) {
  424. status = QDF_STATUS_E_RESOURCES;
  425. break;
  426. }
  427. pPacket->Status = QDF_STATUS_SUCCESS;
  428. pPacket->Endpoint = htc_ep_id;
  429. pPacket->pPktContext = netbuf;
  430. pPacket->pBuffer = qdf_nbuf_data(netbuf) + HTC_HDR_LENGTH;
  431. pPacket->ActualLength = netlen - HTC_HEADER_LEN - trailerlen;
  432. qdf_nbuf_pull_head(netbuf, HTC_HEADER_LEN);
  433. qdf_nbuf_set_pktlen(netbuf, pPacket->ActualLength);
  434. do_recv_completion_pkt(pEndpoint, pPacket);
  435. /* recover the packet container */
  436. free_htc_packet_container(target, pPacket);
  437. netbuf = NULL;
  438. } while (false);
  439. #ifdef RX_SG_SUPPORT
  440. _out:
  441. #endif
  442. if (netbuf)
  443. qdf_nbuf_free(netbuf);
  444. return status;
  445. }
  446. A_STATUS htc_add_receive_pkt_multiple(HTC_HANDLE HTCHandle,
  447. HTC_PACKET_QUEUE *pPktQueue)
  448. {
  449. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  450. HTC_ENDPOINT *pEndpoint;
  451. HTC_PACKET *pFirstPacket;
  452. A_STATUS status = A_OK;
  453. HTC_PACKET *pPacket;
  454. pFirstPacket = htc_get_pkt_at_head(pPktQueue);
  455. if (!pFirstPacket) {
  456. A_ASSERT(false);
  457. return A_EINVAL;
  458. }
  459. if (pFirstPacket->Endpoint >= ENDPOINT_MAX) {
  460. A_ASSERT(false);
  461. return A_EINVAL;
  462. }
  463. AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
  464. ("+- htc_add_receive_pkt_multiple : endPointId: %d, cnt:%d, length: %d\n",
  465. pFirstPacket->Endpoint,
  466. HTC_PACKET_QUEUE_DEPTH(pPktQueue),
  467. pFirstPacket->BufferLength));
  468. pEndpoint = &target->endpoint[pFirstPacket->Endpoint];
  469. LOCK_HTC_RX(target);
  470. do {
  471. if (HTC_STOPPING(target)) {
  472. status = A_ERROR;
  473. break;
  474. }
  475. /* store receive packets */
  476. HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&pEndpoint->RxBufferHoldQueue,
  477. pPktQueue);
  478. } while (false);
  479. UNLOCK_HTC_RX(target);
  480. if (A_FAILED(status)) {
  481. /* walk through queue and mark each one canceled */
  482. HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pPktQueue, pPacket) {
  483. pPacket->Status = QDF_STATUS_E_CANCELED;
  484. }
  485. HTC_PACKET_QUEUE_ITERATE_END;
  486. do_recv_completion(pEndpoint, pPktQueue);
  487. }
  488. return status;
  489. }
  490. void htc_flush_rx_hold_queue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
  491. {
  492. HTC_PACKET *pPacket;
  493. LOCK_HTC_RX(target);
  494. while (1) {
  495. pPacket = htc_packet_dequeue(&pEndpoint->RxBufferHoldQueue);
  496. if (!pPacket)
  497. break;
  498. UNLOCK_HTC_RX(target);
  499. pPacket->Status = QDF_STATUS_E_CANCELED;
  500. pPacket->ActualLength = 0;
  501. AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
  502. ("Flushing RX packet:%pK, length:%d, ep:%d\n",
  503. pPacket, pPacket->BufferLength,
  504. pPacket->Endpoint));
  505. /* give the packet back */
  506. do_recv_completion_pkt(pEndpoint, pPacket);
  507. LOCK_HTC_RX(target);
  508. }
  509. UNLOCK_HTC_RX(target);
  510. }
  511. void htc_recv_init(HTC_TARGET *target)
  512. {
  513. /* Initialize ctrl_response_valid to block */
  514. qdf_event_create(&target->ctrl_response_valid);
  515. }
  516. /* polling routine to wait for a control packet to be received */
  517. QDF_STATUS htc_wait_recv_ctrl_message(HTC_TARGET *target)
  518. {
  519. /* int count = HTC_TARGET_MAX_RESPONSE_POLL; */
  520. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCWaitCtrlMessageRecv\n"));
  521. /* Wait for BMI request/response transaction to complete */
  522. if (qdf_wait_single_event(&target->ctrl_response_valid,
  523. (target->HTCInitInfo.htc_ready_timeout_ms))) {
  524. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  525. ("Failed to receive control message\n"));
  526. return QDF_STATUS_E_FAILURE;
  527. }
  528. LOCK_HTC_RX(target);
  529. /* caller will clear this flag */
  530. target->CtrlResponseProcessing = true;
  531. UNLOCK_HTC_RX(target);
  532. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCWaitCtrlMessageRecv success\n"));
  533. return QDF_STATUS_SUCCESS;
  534. }
  535. static A_STATUS htc_process_trailer(HTC_TARGET *target,
  536. uint8_t *pBuffer,
  537. int Length, HTC_ENDPOINT_ID FromEndpoint)
  538. {
  539. HTC_RECORD_HDR *pRecord;
  540. uint8_t htc_rec_id;
  541. uint8_t htc_rec_len;
  542. uint8_t *pRecordBuf;
  543. uint8_t *pOrigBuffer;
  544. int origLength;
  545. A_STATUS status;
  546. AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
  547. ("+htc_process_trailer (length:%d)\n", Length));
  548. if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV))
  549. AR_DEBUG_PRINTBUF(pBuffer, Length, "Recv Trailer");
  550. pOrigBuffer = pBuffer;
  551. origLength = Length;
  552. status = A_OK;
  553. while (Length > 0) {
  554. if (Length < sizeof(HTC_RECORD_HDR)) {
  555. status = A_EPROTO;
  556. break;
  557. }
  558. /* these are byte aligned structs */
  559. pRecord = (HTC_RECORD_HDR *) pBuffer;
  560. Length -= sizeof(HTC_RECORD_HDR);
  561. pBuffer += sizeof(HTC_RECORD_HDR);
  562. htc_rec_len = HTC_GET_FIELD(pRecord, HTC_RECORD_HDR, LENGTH);
  563. htc_rec_id = HTC_GET_FIELD(pRecord, HTC_RECORD_HDR, RECORDID);
  564. if (htc_rec_len > Length) {
  565. /* no room left in buffer for record */
  566. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  567. ("invalid record length: %d (id:%d) buffer has: %d bytes left\n",
  568. htc_rec_len, htc_rec_id, Length));
  569. status = A_EPROTO;
  570. break;
  571. }
  572. /* start of record follows the header */
  573. pRecordBuf = pBuffer;
  574. switch (htc_rec_id) {
  575. case HTC_RECORD_CREDITS:
  576. AR_DEBUG_ASSERT(htc_rec_len >=
  577. sizeof(HTC_CREDIT_REPORT));
  578. htc_process_credit_rpt(target,
  579. (HTC_CREDIT_REPORT *) pRecordBuf,
  580. htc_rec_len /
  581. (sizeof(HTC_CREDIT_REPORT)),
  582. FromEndpoint);
  583. break;
  584. #ifdef HIF_SDIO
  585. case HTC_RECORD_LOOKAHEAD:
  586. /* Process in HIF layer */
  587. break;
  588. case HTC_RECORD_LOOKAHEAD_BUNDLE:
  589. /* Process in HIF layer */
  590. break;
  591. #endif /* HIF_SDIO */
  592. default:
  593. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  594. ("HTC unhandled record: id:%d length:%d\n",
  595. htc_rec_id, htc_rec_len));
  596. break;
  597. }
  598. if (A_FAILED(status)) {
  599. break;
  600. }
  601. /* advance buffer past this record for next time around */
  602. pBuffer += htc_rec_len;
  603. Length -= htc_rec_len;
  604. }
  605. if (A_FAILED(status))
  606. debug_dump_bytes(pOrigBuffer, origLength, "BAD Recv Trailer");
  607. AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-htc_process_trailer\n"));
  608. return status;
  609. }