htc_recv.c 19 KB

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