htc_recv.c 18 KB

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