htc_recv.c 18 KB

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