htc.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. /*
  2. * Copyright (c) 2013-2015 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 "ol_if_athvar.h"
  27. #include "htc_debug.h"
  28. #include "htc_internal.h"
  29. #include <cdf_nbuf.h> /* cdf_nbuf_t */
  30. #include <cdf_types.h> /* cdf_print */
  31. #include <hif.h>
  32. #include "epping_main.h"
  33. #include "hif_io32.h"
  34. #include "cds_concurrency.h"
  35. #ifdef DEBUG
  36. static ATH_DEBUG_MASK_DESCRIPTION g_htc_debug_description[] = {
  37. {ATH_DEBUG_SEND, "Send"},
  38. {ATH_DEBUG_RECV, "Recv"},
  39. {ATH_DEBUG_SYNC, "Sync"},
  40. {ATH_DEBUG_DUMP, "Dump Data (RX or TX)"},
  41. {ATH_DEBUG_SETUP, "Setup"},
  42. };
  43. ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc,
  44. "htc",
  45. "Host Target Communications",
  46. ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO |
  47. ATH_DEBUG_SETUP,
  48. ATH_DEBUG_DESCRIPTION_COUNT
  49. (g_htc_debug_description),
  50. g_htc_debug_description);
  51. #endif
  52. extern unsigned int htc_credit_flow;
  53. static void reset_endpoint_states(HTC_TARGET *target);
  54. static void destroy_htc_tx_ctrl_packet(HTC_PACKET *pPacket)
  55. {
  56. cdf_nbuf_t netbuf;
  57. netbuf = (cdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
  58. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("free ctrl netbuf :0x%p \n", netbuf));
  59. if (netbuf != NULL) {
  60. cdf_nbuf_free(netbuf);
  61. }
  62. cdf_mem_free(pPacket);
  63. }
  64. static HTC_PACKET *build_htc_tx_ctrl_packet(cdf_device_t osdev)
  65. {
  66. HTC_PACKET *pPacket = NULL;
  67. cdf_nbuf_t netbuf;
  68. do {
  69. pPacket = (HTC_PACKET *) cdf_mem_malloc(sizeof(HTC_PACKET));
  70. if (NULL == pPacket) {
  71. break;
  72. }
  73. A_MEMZERO(pPacket, sizeof(HTC_PACKET));
  74. netbuf =
  75. cdf_nbuf_alloc(osdev, HTC_CONTROL_BUFFER_SIZE, 20, 4, true);
  76. if (NULL == netbuf) {
  77. cdf_mem_free(pPacket);
  78. pPacket = NULL;
  79. cdf_print("%s: nbuf alloc failed\n", __func__);
  80. break;
  81. }
  82. AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
  83. ("alloc ctrl netbuf :0x%p \n", netbuf));
  84. SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf);
  85. } while (false);
  86. return pPacket;
  87. }
  88. void htc_free_control_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket)
  89. {
  90. #ifdef TODO_FIXME
  91. LOCK_HTC(target);
  92. HTC_PACKET_ENQUEUE(&target->ControlBufferTXFreeList, pPacket);
  93. UNLOCK_HTC(target);
  94. /* TODO_FIXME netbufs cannot be RESET! */
  95. #else
  96. destroy_htc_tx_ctrl_packet(pPacket);
  97. #endif
  98. }
  99. HTC_PACKET *htc_alloc_control_tx_packet(HTC_TARGET *target)
  100. {
  101. #ifdef TODO_FIXME
  102. HTC_PACKET *pPacket;
  103. LOCK_HTC(target);
  104. pPacket = htc_packet_dequeue(&target->ControlBufferTXFreeList);
  105. UNLOCK_HTC(target);
  106. return pPacket;
  107. #else
  108. return build_htc_tx_ctrl_packet(target->osdev);
  109. #endif
  110. }
  111. /* Set the target failure handling callback */
  112. void htc_set_target_failure_callback(HTC_HANDLE HTCHandle,
  113. HTC_TARGET_FAILURE Callback)
  114. {
  115. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  116. target->HTCInitInfo.TargetFailure = Callback;
  117. }
  118. void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start)
  119. {
  120. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  121. hif_dump(target->hif_dev, CmdId, start);
  122. }
  123. /* cleanup the HTC instance */
  124. static void htc_cleanup(HTC_TARGET *target)
  125. {
  126. HTC_PACKET *pPacket;
  127. /* cdf_nbuf_t netbuf; */
  128. if (target->hif_dev != NULL) {
  129. hif_detach_htc(target->hif_dev);
  130. target->hif_dev = NULL;
  131. }
  132. while (true) {
  133. pPacket = allocate_htc_packet_container(target);
  134. if (NULL == pPacket) {
  135. break;
  136. }
  137. cdf_mem_free(pPacket);
  138. }
  139. pPacket = target->pBundleFreeList;
  140. while (pPacket) {
  141. HTC_PACKET *pPacketTmp = (HTC_PACKET *) pPacket->ListLink.pNext;
  142. cdf_mem_free(pPacket);
  143. pPacket = pPacketTmp;
  144. }
  145. #ifdef TODO_FIXME
  146. while (true) {
  147. pPacket = htc_alloc_control_tx_packet(target);
  148. if (NULL == pPacket) {
  149. break;
  150. }
  151. netbuf = (cdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
  152. if (netbuf != NULL) {
  153. cdf_nbuf_free(netbuf);
  154. }
  155. cdf_mem_free(pPacket);
  156. }
  157. #endif
  158. cdf_spinlock_destroy(&target->HTCLock);
  159. cdf_spinlock_destroy(&target->HTCRxLock);
  160. cdf_spinlock_destroy(&target->HTCTxLock);
  161. cdf_spinlock_destroy(&target->HTCCreditLock);
  162. /* free our instance */
  163. cdf_mem_free(target);
  164. }
  165. /* registered target arrival callback from the HIF layer */
  166. HTC_HANDLE htc_create(void *ol_sc, HTC_INIT_INFO *pInfo, cdf_device_t osdev)
  167. {
  168. struct hif_msg_callbacks htcCallbacks;
  169. HTC_ENDPOINT *pEndpoint = NULL;
  170. HTC_TARGET *target = NULL;
  171. int i;
  172. if (ol_sc == NULL) {
  173. HTC_ERROR("%s: ol_sc = NULL", __func__);
  174. return NULL;
  175. }
  176. HTC_TRACE("+htc_create .. HIF :%p", ol_sc);
  177. A_REGISTER_MODULE_DEBUG_INFO(htc);
  178. target = (HTC_TARGET *) cdf_mem_malloc(sizeof(HTC_TARGET));
  179. if (target == NULL) {
  180. HTC_ERROR("%s: Unable to allocate memory", __func__);
  181. return NULL;
  182. }
  183. A_MEMZERO(target, sizeof(HTC_TARGET));
  184. cdf_spinlock_init(&target->HTCLock);
  185. cdf_spinlock_init(&target->HTCRxLock);
  186. cdf_spinlock_init(&target->HTCTxLock);
  187. cdf_spinlock_init(&target->HTCCreditLock);
  188. do {
  189. A_MEMCPY(&target->HTCInitInfo, pInfo, sizeof(HTC_INIT_INFO));
  190. target->host_handle = pInfo->pContext;
  191. target->osdev = osdev;
  192. reset_endpoint_states(target);
  193. INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList);
  194. for (i = 0; i < HTC_PACKET_CONTAINER_ALLOCATION; i++) {
  195. HTC_PACKET *pPacket =
  196. (HTC_PACKET *) cdf_mem_malloc(sizeof(HTC_PACKET));
  197. if (pPacket != NULL) {
  198. A_MEMZERO(pPacket, sizeof(HTC_PACKET));
  199. free_htc_packet_container(target, pPacket);
  200. }
  201. }
  202. #ifdef TODO_FIXME
  203. for (i = 0; i < NUM_CONTROL_TX_BUFFERS; i++) {
  204. pPacket = build_htc_tx_ctrl_packet();
  205. if (NULL == pPacket) {
  206. break;
  207. }
  208. htc_free_control_tx_packet(target, pPacket);
  209. }
  210. #endif
  211. /* setup HIF layer callbacks */
  212. cdf_mem_zero(&htcCallbacks, sizeof(struct hif_msg_callbacks));
  213. htcCallbacks.Context = target;
  214. htcCallbacks.rxCompletionHandler = htc_rx_completion_handler;
  215. htcCallbacks.txCompletionHandler = htc_tx_completion_handler;
  216. htcCallbacks.txResourceAvailHandler = htc_tx_resource_avail_handler;
  217. htcCallbacks.fwEventHandler = htc_fw_event_handler;
  218. target->hif_dev = ol_sc;
  219. /* Get HIF default pipe for HTC message exchange */
  220. pEndpoint = &target->EndPoint[ENDPOINT_0];
  221. hif_post_init(target->hif_dev, target, &htcCallbacks);
  222. hif_get_default_pipe(target->hif_dev, &pEndpoint->UL_PipeID,
  223. &pEndpoint->DL_PipeID);
  224. } while (false);
  225. htc_recv_init(target);
  226. HTC_TRACE("-htc_create: (0x%p)", target);
  227. return (HTC_HANDLE) target;
  228. }
  229. void htc_destroy(HTC_HANDLE HTCHandle)
  230. {
  231. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  232. AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
  233. ("+htc_destroy .. Destroying :0x%p\n", target));
  234. if (target)
  235. htc_cleanup(target);
  236. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_destroy\n"));
  237. }
  238. /* get the low level HIF device for the caller , the caller may wish to do low level
  239. * HIF requests */
  240. void *htc_get_hif_device(HTC_HANDLE HTCHandle)
  241. {
  242. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  243. return target->hif_dev;
  244. }
  245. void htc_control_tx_complete(void *Context, HTC_PACKET *pPacket)
  246. {
  247. HTC_TARGET *target = (HTC_TARGET *) Context;
  248. AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
  249. ("+-htc_control_tx_complete 0x%p (l:%d) \n", pPacket,
  250. pPacket->ActualLength));
  251. htc_free_control_tx_packet(target, pPacket);
  252. }
  253. /* TODO, this is just a temporary max packet size */
  254. #define MAX_MESSAGE_SIZE 1536
  255. /**
  256. * htc_setup_target_buffer_assignments() - setup target buffer assignments
  257. * @target: HTC Target Pointer
  258. *
  259. * Return: A_STATUS
  260. */
  261. A_STATUS htc_setup_target_buffer_assignments(HTC_TARGET *target)
  262. {
  263. HTC_SERVICE_TX_CREDIT_ALLOCATION *pEntry;
  264. A_STATUS status;
  265. int credits;
  266. int creditsPerMaxMsg;
  267. creditsPerMaxMsg = MAX_MESSAGE_SIZE / target->TargetCreditSize;
  268. if (MAX_MESSAGE_SIZE % target->TargetCreditSize) {
  269. creditsPerMaxMsg++;
  270. }
  271. /* TODO, this should be configured by the caller! */
  272. credits = target->TotalTransmitCredits;
  273. pEntry = &target->ServiceTxAllocTable[0];
  274. /*
  275. * Allocate all credists/HTC buffers to WMI.
  276. * no buffers are used/required for data. data always
  277. * remains on host.
  278. */
  279. status = A_OK;
  280. pEntry++;
  281. pEntry->ServiceID = WMI_CONTROL_SVC;
  282. pEntry->CreditAllocation = credits;
  283. if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) {
  284. /* endpoint ping is a testing tool directly on top of HTC in
  285. * both target and host sides.
  286. * In target side, the endppint ping fw has no wlan stack and the
  287. * FW mboxping app directly sits on HTC and it simply drops
  288. * or loops back TX packets. For rx perf, FW mboxping app
  289. * generates packets and passes packets to HTC to send to host.
  290. * There is no WMI mesage exchanges between host and target
  291. * in endpoint ping case.
  292. * In host side, the endpoint ping driver is a Ethernet driver
  293. * and it directly sits on HTC. Only HIF, HTC, CDF, ADF are
  294. * used by the endpoint ping driver. There is no wifi stack
  295. * at all in host side also. For tx perf use case,
  296. * the user space mboxping app sends the raw packets to endpoint
  297. * ping driver and it directly forwards to HTC for transmission
  298. * to stress the bus. For the rx perf, HTC passes the received
  299. * packets to endpoint ping driver and it is passed to the user
  300. * space through the Ethernet interface.
  301. * For credit allocation, in SDIO bus case, only BE service is
  302. * used for tx/rx perf testing so that all credits are given
  303. * to BE service. In PCIe and USB bus case, endpoint ping uses both
  304. * BE and BK services to stress the bus so that the total credits
  305. * are equally distributed to BE and BK services.
  306. */
  307. pEntry->ServiceID = WMI_DATA_BE_SVC;
  308. pEntry->CreditAllocation = (credits >> 1);
  309. pEntry++;
  310. pEntry->ServiceID = WMI_DATA_BK_SVC;
  311. pEntry->CreditAllocation = (credits >> 1);
  312. }
  313. if (A_SUCCESS(status)) {
  314. int i;
  315. for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) {
  316. if (target->ServiceTxAllocTable[i].ServiceID != 0) {
  317. AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
  318. ("HTC Service Index : %d TX : 0x%2.2X : alloc:%d \n",
  319. i,
  320. target->ServiceTxAllocTable[i].
  321. ServiceID,
  322. target->ServiceTxAllocTable[i].
  323. CreditAllocation));
  324. }
  325. }
  326. }
  327. return status;
  328. }
  329. A_UINT8 htc_get_credit_allocation(HTC_TARGET *target, A_UINT16 ServiceID)
  330. {
  331. A_UINT8 allocation = 0;
  332. int i;
  333. for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) {
  334. if (target->ServiceTxAllocTable[i].ServiceID == ServiceID) {
  335. allocation =
  336. target->ServiceTxAllocTable[i].CreditAllocation;
  337. }
  338. }
  339. if (0 == allocation) {
  340. AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
  341. ("HTC Service TX : 0x%2.2X : allocation is zero! \n",
  342. ServiceID));
  343. }
  344. return allocation;
  345. }
  346. A_STATUS htc_wait_target(HTC_HANDLE HTCHandle)
  347. {
  348. A_STATUS status = A_OK;
  349. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  350. HTC_READY_EX_MSG *pReadyMsg;
  351. HTC_SERVICE_CONNECT_REQ connect;
  352. HTC_SERVICE_CONNECT_RESP resp;
  353. HTC_READY_MSG *rdy_msg;
  354. A_UINT16 htc_rdy_msg_id;
  355. AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
  356. ("htc_wait_target - Enter (target:0x%p) \n", HTCHandle));
  357. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("+HWT\n"));
  358. do {
  359. status = hif_start(target->hif_dev);
  360. if (A_FAILED(status)) {
  361. AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("hif_start failed\n"));
  362. break;
  363. }
  364. status = htc_wait_recv_ctrl_message(target);
  365. if (A_FAILED(status)) {
  366. break;
  367. }
  368. if (target->CtrlResponseLength < (sizeof(HTC_READY_EX_MSG))) {
  369. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  370. ("Invalid HTC Ready Msg Len:%d! \n",
  371. target->CtrlResponseLength));
  372. status = A_ECOMM;
  373. break;
  374. }
  375. pReadyMsg = (HTC_READY_EX_MSG *) target->CtrlResponseBuffer;
  376. rdy_msg = &pReadyMsg->Version2_0_Info;
  377. htc_rdy_msg_id =
  378. HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, MESSAGEID);
  379. if (htc_rdy_msg_id != HTC_MSG_READY_ID) {
  380. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  381. ("Invalid HTC Ready Msg : 0x%X ! \n",
  382. htc_rdy_msg_id));
  383. status = A_ECOMM;
  384. break;
  385. }
  386. target->TotalTransmitCredits =
  387. HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITCOUNT);
  388. target->TargetCreditSize =
  389. (int)HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITSIZE);
  390. target->MaxMsgsPerHTCBundle =
  391. (A_UINT8) pReadyMsg->MaxMsgsPerHTCBundle;
  392. /* for old fw this value is set to 0. But the minimum value should be 1,
  393. * i.e., no bundling */
  394. if (target->MaxMsgsPerHTCBundle < 1)
  395. target->MaxMsgsPerHTCBundle = 1;
  396. AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
  397. ("Target Ready! : transmit resources : %d size:%d, MaxMsgsPerHTCBundle = %d\n",
  398. target->TotalTransmitCredits,
  399. target->TargetCreditSize,
  400. target->MaxMsgsPerHTCBundle));
  401. if ((0 == target->TotalTransmitCredits)
  402. || (0 == target->TargetCreditSize)) {
  403. status = A_ECOMM;
  404. break;
  405. }
  406. /* done processing */
  407. target->CtrlResponseProcessing = false;
  408. htc_setup_target_buffer_assignments(target);
  409. /* setup our pseudo HTC control endpoint connection */
  410. A_MEMZERO(&connect, sizeof(connect));
  411. A_MEMZERO(&resp, sizeof(resp));
  412. connect.EpCallbacks.pContext = target;
  413. connect.EpCallbacks.EpTxComplete = htc_control_tx_complete;
  414. connect.EpCallbacks.EpRecv = htc_control_rx_complete;
  415. connect.MaxSendQueueDepth = NUM_CONTROL_TX_BUFFERS;
  416. connect.ServiceID = HTC_CTRL_RSVD_SVC;
  417. /* connect fake service */
  418. status = htc_connect_service((HTC_HANDLE) target,
  419. &connect, &resp);
  420. } while (false);
  421. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_wait_target - Exit (%d)\n", status));
  422. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("-HWT\n"));
  423. return status;
  424. }
  425. /* start HTC, this is called after all services are connected */
  426. static A_STATUS htc_config_target_hif_pipe(HTC_TARGET *target)
  427. {
  428. return A_OK;
  429. }
  430. static void reset_endpoint_states(HTC_TARGET *target)
  431. {
  432. HTC_ENDPOINT *pEndpoint;
  433. int i;
  434. for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
  435. pEndpoint = &target->EndPoint[i];
  436. pEndpoint->ServiceID = 0;
  437. pEndpoint->MaxMsgLength = 0;
  438. pEndpoint->MaxTxQueueDepth = 0;
  439. pEndpoint->Id = i;
  440. INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue);
  441. INIT_HTC_PACKET_QUEUE(&pEndpoint->TxLookupQueue);
  442. INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBufferHoldQueue);
  443. pEndpoint->target = target;
  444. /* pEndpoint->TxCreditFlowEnabled = (A_BOOL)htc_credit_flow; */
  445. pEndpoint->TxCreditFlowEnabled = (A_BOOL) 1;
  446. cdf_atomic_init(&pEndpoint->TxProcessCount);
  447. }
  448. }
  449. A_STATUS htc_start(HTC_HANDLE HTCHandle)
  450. {
  451. cdf_nbuf_t netbuf;
  452. A_STATUS status = A_OK;
  453. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  454. HTC_SETUP_COMPLETE_EX_MSG *pSetupComp;
  455. HTC_PACKET *pSendPacket;
  456. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Enter\n"));
  457. do {
  458. htc_config_target_hif_pipe(target);
  459. /* allocate a buffer to send */
  460. pSendPacket = htc_alloc_control_tx_packet(target);
  461. if (NULL == pSendPacket) {
  462. AR_DEBUG_ASSERT(false);
  463. cdf_print("%s: allocControlTxPacket failed\n",
  464. __func__);
  465. status = A_NO_MEMORY;
  466. break;
  467. }
  468. netbuf =
  469. (cdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket);
  470. /* assemble setup complete message */
  471. cdf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
  472. pSetupComp =
  473. (HTC_SETUP_COMPLETE_EX_MSG *) cdf_nbuf_data(netbuf);
  474. A_MEMZERO(pSetupComp, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
  475. HTC_SET_FIELD(pSetupComp, HTC_SETUP_COMPLETE_EX_MSG,
  476. MESSAGEID, HTC_MSG_SETUP_COMPLETE_EX_ID);
  477. if (!htc_credit_flow) {
  478. AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
  479. ("HTC will not use TX credit flow control\n"));
  480. pSetupComp->SetupFlags |=
  481. HTC_SETUP_COMPLETE_FLAGS_DISABLE_TX_CREDIT_FLOW;
  482. } else {
  483. AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
  484. ("HTC using TX credit flow control\n"));
  485. }
  486. #ifdef HIF_SDIO
  487. #if ENABLE_BUNDLE_RX
  488. if (HTC_ENABLE_BUNDLE(target))
  489. pSetupComp->SetupFlags |=
  490. HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV;
  491. #endif /* ENABLE_BUNDLE_RX */
  492. #endif /* HIF_SDIO */
  493. SET_HTC_PACKET_INFO_TX(pSendPacket,
  494. NULL,
  495. (A_UINT8 *) pSetupComp,
  496. sizeof(HTC_SETUP_COMPLETE_EX_MSG),
  497. ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
  498. status = htc_send_pkt((HTC_HANDLE) target, pSendPacket);
  499. if (A_FAILED(status)) {
  500. break;
  501. }
  502. } while (false);
  503. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Exit\n"));
  504. return status;
  505. }
  506. /*flush all queued buffers for surpriseremove case*/
  507. void htc_flush_surprise_remove(HTC_HANDLE HTCHandle)
  508. {
  509. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  510. int i;
  511. HTC_ENDPOINT *pEndpoint;
  512. #ifdef RX_SG_SUPPORT
  513. cdf_nbuf_t netbuf;
  514. cdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
  515. #endif
  516. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_flush_surprise_remove \n"));
  517. /* cleanup endpoints */
  518. for (i = 0; i < ENDPOINT_MAX; i++) {
  519. pEndpoint = &target->EndPoint[i];
  520. htc_flush_rx_hold_queue(target, pEndpoint);
  521. htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL);
  522. }
  523. hif_flush_surprise_remove(target->hif_dev);
  524. #ifdef RX_SG_SUPPORT
  525. LOCK_HTC_RX(target);
  526. while ((netbuf = cdf_nbuf_queue_remove(rx_sg_queue)) != NULL) {
  527. cdf_nbuf_free(netbuf);
  528. }
  529. RESET_RX_SG_CONFIG(target);
  530. UNLOCK_HTC_RX(target);
  531. #endif
  532. reset_endpoint_states(target);
  533. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_flush_surprise_remove \n"));
  534. }
  535. /* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */
  536. void htc_stop(HTC_HANDLE HTCHandle)
  537. {
  538. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  539. int i;
  540. HTC_ENDPOINT *pEndpoint;
  541. #ifdef RX_SG_SUPPORT
  542. cdf_nbuf_t netbuf;
  543. cdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
  544. #endif
  545. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_stop \n"));
  546. /* cleanup endpoints */
  547. for (i = 0; i < ENDPOINT_MAX; i++) {
  548. pEndpoint = &target->EndPoint[i];
  549. htc_flush_rx_hold_queue(target, pEndpoint);
  550. htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL);
  551. if (pEndpoint->ul_is_polled) {
  552. cdf_softirq_timer_cancel(&pEndpoint->ul_poll_timer);
  553. cdf_softirq_timer_free(&pEndpoint->ul_poll_timer);
  554. }
  555. }
  556. /* Note: htc_flush_endpoint_tx for all endpoints should be called before
  557. * hif_stop - otherwise htc_tx_completion_handler called from
  558. * hif_send_buffer_cleanup_on_pipe for residual tx frames in HIF layer,
  559. * might queue the packet again to HIF Layer - which could cause tx
  560. * buffer leak
  561. */
  562. hif_stop(target->hif_dev);
  563. #ifdef RX_SG_SUPPORT
  564. LOCK_HTC_RX(target);
  565. while ((netbuf = cdf_nbuf_queue_remove(rx_sg_queue)) != NULL) {
  566. cdf_nbuf_free(netbuf);
  567. }
  568. RESET_RX_SG_CONFIG(target);
  569. UNLOCK_HTC_RX(target);
  570. #endif
  571. reset_endpoint_states(target);
  572. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_stop \n"));
  573. }
  574. void htc_dump_credit_states(HTC_HANDLE HTCHandle)
  575. {
  576. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  577. HTC_ENDPOINT *pEndpoint;
  578. int i;
  579. for (i = 0; i < ENDPOINT_MAX; i++) {
  580. pEndpoint = &target->EndPoint[i];
  581. if (0 == pEndpoint->ServiceID) {
  582. continue;
  583. }
  584. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  585. ("--- EP : %d ServiceID: 0x%X --------------\n",
  586. pEndpoint->Id, pEndpoint->ServiceID));
  587. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  588. (" TxCredits : %d \n",
  589. pEndpoint->TxCredits));
  590. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  591. (" TxCreditSize : %d \n",
  592. pEndpoint->TxCreditSize));
  593. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  594. (" TxCreditsPerMaxMsg : %d \n",
  595. pEndpoint->TxCreditsPerMaxMsg));
  596. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  597. (" TxQueueDepth : %d \n",
  598. HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
  599. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  600. ("----------------------------------------------------\n"));
  601. }
  602. }
  603. A_BOOL htc_get_endpoint_statistics(HTC_HANDLE HTCHandle,
  604. HTC_ENDPOINT_ID Endpoint,
  605. HTC_ENDPOINT_STAT_ACTION Action,
  606. HTC_ENDPOINT_STATS *pStats)
  607. {
  608. #ifdef HTC_EP_STAT_PROFILING
  609. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  610. A_BOOL clearStats = false;
  611. A_BOOL sample = false;
  612. switch (Action) {
  613. case HTC_EP_STAT_SAMPLE:
  614. sample = true;
  615. break;
  616. case HTC_EP_STAT_SAMPLE_AND_CLEAR:
  617. sample = true;
  618. clearStats = true;
  619. break;
  620. case HTC_EP_STAT_CLEAR:
  621. clearStats = true;
  622. break;
  623. default:
  624. break;
  625. }
  626. A_ASSERT(Endpoint < ENDPOINT_MAX);
  627. /* lock out TX and RX while we sample and/or clear */
  628. LOCK_HTC_TX(target);
  629. LOCK_HTC_RX(target);
  630. if (sample) {
  631. A_ASSERT(pStats != NULL);
  632. /* return the stats to the caller */
  633. A_MEMCPY(pStats, &target->EndPoint[Endpoint].EndPointStats,
  634. sizeof(HTC_ENDPOINT_STATS));
  635. }
  636. if (clearStats) {
  637. /* reset stats */
  638. A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats,
  639. sizeof(HTC_ENDPOINT_STATS));
  640. }
  641. UNLOCK_HTC_RX(target);
  642. UNLOCK_HTC_TX(target);
  643. return true;
  644. #else
  645. return false;
  646. #endif
  647. }
  648. void *htc_get_targetdef(HTC_HANDLE htc_handle)
  649. {
  650. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
  651. return hif_get_targetdef(target->hif_dev);
  652. }
  653. /**
  654. * htc_set_target_to_sleep() - set target to sleep
  655. * @context: ol_softc context
  656. *
  657. * Return: none
  658. */
  659. void htc_set_target_to_sleep(void *context)
  660. {
  661. struct ol_softc *scn = (struct ol_softc *)context;
  662. hif_set_target_sleep(scn, true, false);
  663. }
  664. /**
  665. * htc_cancel_deferred_target_sleep() - cancel deferred target sleep
  666. * @context: ol_softc context
  667. *
  668. * Return: none
  669. */
  670. void htc_cancel_deferred_target_sleep(void *context)
  671. {
  672. struct ol_softc *scn = (struct ol_softc *)context;
  673. hif_cancel_deferred_target_sleep(scn);
  674. }
  675. #ifdef IPA_OFFLOAD
  676. void htc_ipa_get_ce_resource(HTC_HANDLE htc_handle,
  677. uint32_t *ce_sr_base_paddr,
  678. uint32_t *ce_sr_ring_size,
  679. cdf_dma_addr_t *ce_reg_paddr)
  680. {
  681. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
  682. if (target->hif_dev != NULL) {
  683. hif_ipa_get_ce_resource(target->hif_dev,
  684. ce_sr_base_paddr,
  685. ce_sr_ring_size, ce_reg_paddr);
  686. }
  687. }
  688. #endif /* IPA_OFFLOAD */