htc_recv.c 18 KB

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