htc_recv.c 18 KB

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