htc_recv.c 18 KB

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