htc_recv.c 19 KB

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