htc.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826
  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. hif_stop(htc_get_hif_device(HTCHandle));
  235. if (target)
  236. htc_cleanup(target);
  237. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_destroy\n"));
  238. }
  239. /* get the low level HIF device for the caller , the caller may wish to do low level
  240. * HIF requests */
  241. void *htc_get_hif_device(HTC_HANDLE HTCHandle)
  242. {
  243. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  244. return target->hif_dev;
  245. }
  246. void htc_control_tx_complete(void *Context, HTC_PACKET *pPacket)
  247. {
  248. HTC_TARGET *target = (HTC_TARGET *) Context;
  249. AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
  250. ("+-htc_control_tx_complete 0x%p (l:%d) \n", pPacket,
  251. pPacket->ActualLength));
  252. htc_free_control_tx_packet(target, pPacket);
  253. }
  254. /* TODO, this is just a temporary max packet size */
  255. #define MAX_MESSAGE_SIZE 1536
  256. /**
  257. * htc_setup_target_buffer_assignments() - setup target buffer assignments
  258. * @target: HTC Target Pointer
  259. *
  260. * Return: A_STATUS
  261. */
  262. A_STATUS htc_setup_target_buffer_assignments(HTC_TARGET *target)
  263. {
  264. HTC_SERVICE_TX_CREDIT_ALLOCATION *pEntry;
  265. A_STATUS status;
  266. int credits;
  267. int creditsPerMaxMsg;
  268. creditsPerMaxMsg = MAX_MESSAGE_SIZE / target->TargetCreditSize;
  269. if (MAX_MESSAGE_SIZE % target->TargetCreditSize) {
  270. creditsPerMaxMsg++;
  271. }
  272. /* TODO, this should be configured by the caller! */
  273. credits = target->TotalTransmitCredits;
  274. pEntry = &target->ServiceTxAllocTable[0];
  275. /*
  276. * Allocate all credists/HTC buffers to WMI.
  277. * no buffers are used/required for data. data always
  278. * remains on host.
  279. */
  280. status = A_OK;
  281. pEntry++;
  282. pEntry->ServiceID = WMI_CONTROL_SVC;
  283. pEntry->CreditAllocation = credits;
  284. if (WLAN_IS_EPPING_ENABLED(cds_get_conparam())) {
  285. /* endpoint ping is a testing tool directly on top of HTC in
  286. * both target and host sides.
  287. * In target side, the endppint ping fw has no wlan stack and the
  288. * FW mboxping app directly sits on HTC and it simply drops
  289. * or loops back TX packets. For rx perf, FW mboxping app
  290. * generates packets and passes packets to HTC to send to host.
  291. * There is no WMI mesage exchanges between host and target
  292. * in endpoint ping case.
  293. * In host side, the endpoint ping driver is a Ethernet driver
  294. * and it directly sits on HTC. Only HIF, HTC, CDF, ADF are
  295. * used by the endpoint ping driver. There is no wifi stack
  296. * at all in host side also. For tx perf use case,
  297. * the user space mboxping app sends the raw packets to endpoint
  298. * ping driver and it directly forwards to HTC for transmission
  299. * to stress the bus. For the rx perf, HTC passes the received
  300. * packets to endpoint ping driver and it is passed to the user
  301. * space through the Ethernet interface.
  302. * For credit allocation, in SDIO bus case, only BE service is
  303. * used for tx/rx perf testing so that all credits are given
  304. * to BE service. In PCIe and USB bus case, endpoint ping uses both
  305. * BE and BK services to stress the bus so that the total credits
  306. * are equally distributed to BE and BK services.
  307. */
  308. pEntry->ServiceID = WMI_DATA_BE_SVC;
  309. pEntry->CreditAllocation = (credits >> 1);
  310. pEntry++;
  311. pEntry->ServiceID = WMI_DATA_BK_SVC;
  312. pEntry->CreditAllocation = (credits >> 1);
  313. }
  314. if (A_SUCCESS(status)) {
  315. int i;
  316. for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) {
  317. if (target->ServiceTxAllocTable[i].ServiceID != 0) {
  318. AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
  319. ("HTC Service Index : %d TX : 0x%2.2X : alloc:%d \n",
  320. i,
  321. target->ServiceTxAllocTable[i].
  322. ServiceID,
  323. target->ServiceTxAllocTable[i].
  324. CreditAllocation));
  325. }
  326. }
  327. }
  328. return status;
  329. }
  330. A_UINT8 htc_get_credit_allocation(HTC_TARGET *target, A_UINT16 ServiceID)
  331. {
  332. A_UINT8 allocation = 0;
  333. int i;
  334. for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) {
  335. if (target->ServiceTxAllocTable[i].ServiceID == ServiceID) {
  336. allocation =
  337. target->ServiceTxAllocTable[i].CreditAllocation;
  338. }
  339. }
  340. if (0 == allocation) {
  341. AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
  342. ("HTC Service TX : 0x%2.2X : allocation is zero! \n",
  343. ServiceID));
  344. }
  345. return allocation;
  346. }
  347. A_STATUS htc_wait_target(HTC_HANDLE HTCHandle)
  348. {
  349. A_STATUS status = A_OK;
  350. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  351. HTC_READY_EX_MSG *pReadyMsg;
  352. HTC_SERVICE_CONNECT_REQ connect;
  353. HTC_SERVICE_CONNECT_RESP resp;
  354. HTC_READY_MSG *rdy_msg;
  355. A_UINT16 htc_rdy_msg_id;
  356. AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
  357. ("htc_wait_target - Enter (target:0x%p) \n", HTCHandle));
  358. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("+HWT\n"));
  359. do {
  360. status = hif_start(target->hif_dev);
  361. if (A_FAILED(status)) {
  362. AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("hif_start failed\n"));
  363. break;
  364. }
  365. status = htc_wait_recv_ctrl_message(target);
  366. if (A_FAILED(status)) {
  367. break;
  368. }
  369. if (target->CtrlResponseLength < (sizeof(HTC_READY_EX_MSG))) {
  370. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  371. ("Invalid HTC Ready Msg Len:%d! \n",
  372. target->CtrlResponseLength));
  373. status = A_ECOMM;
  374. break;
  375. }
  376. pReadyMsg = (HTC_READY_EX_MSG *) target->CtrlResponseBuffer;
  377. rdy_msg = &pReadyMsg->Version2_0_Info;
  378. htc_rdy_msg_id =
  379. HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, MESSAGEID);
  380. if (htc_rdy_msg_id != HTC_MSG_READY_ID) {
  381. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  382. ("Invalid HTC Ready Msg : 0x%X ! \n",
  383. htc_rdy_msg_id));
  384. status = A_ECOMM;
  385. break;
  386. }
  387. target->TotalTransmitCredits =
  388. HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITCOUNT);
  389. target->TargetCreditSize =
  390. (int)HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITSIZE);
  391. target->MaxMsgsPerHTCBundle =
  392. (A_UINT8) pReadyMsg->MaxMsgsPerHTCBundle;
  393. /* for old fw this value is set to 0. But the minimum value should be 1,
  394. * i.e., no bundling */
  395. if (target->MaxMsgsPerHTCBundle < 1)
  396. target->MaxMsgsPerHTCBundle = 1;
  397. AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
  398. ("Target Ready! : transmit resources : %d size:%d, MaxMsgsPerHTCBundle = %d\n",
  399. target->TotalTransmitCredits,
  400. target->TargetCreditSize,
  401. target->MaxMsgsPerHTCBundle));
  402. if ((0 == target->TotalTransmitCredits)
  403. || (0 == target->TargetCreditSize)) {
  404. status = A_ECOMM;
  405. break;
  406. }
  407. /* done processing */
  408. target->CtrlResponseProcessing = false;
  409. htc_setup_target_buffer_assignments(target);
  410. /* setup our pseudo HTC control endpoint connection */
  411. A_MEMZERO(&connect, sizeof(connect));
  412. A_MEMZERO(&resp, sizeof(resp));
  413. connect.EpCallbacks.pContext = target;
  414. connect.EpCallbacks.EpTxComplete = htc_control_tx_complete;
  415. connect.EpCallbacks.EpRecv = htc_control_rx_complete;
  416. connect.MaxSendQueueDepth = NUM_CONTROL_TX_BUFFERS;
  417. connect.ServiceID = HTC_CTRL_RSVD_SVC;
  418. /* connect fake service */
  419. status = htc_connect_service((HTC_HANDLE) target,
  420. &connect, &resp);
  421. } while (false);
  422. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_wait_target - Exit (%d)\n", status));
  423. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("-HWT\n"));
  424. return status;
  425. }
  426. /* start HTC, this is called after all services are connected */
  427. static A_STATUS htc_config_target_hif_pipe(HTC_TARGET *target)
  428. {
  429. return A_OK;
  430. }
  431. static void reset_endpoint_states(HTC_TARGET *target)
  432. {
  433. HTC_ENDPOINT *pEndpoint;
  434. int i;
  435. for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
  436. pEndpoint = &target->EndPoint[i];
  437. pEndpoint->ServiceID = 0;
  438. pEndpoint->MaxMsgLength = 0;
  439. pEndpoint->MaxTxQueueDepth = 0;
  440. pEndpoint->Id = i;
  441. INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue);
  442. INIT_HTC_PACKET_QUEUE(&pEndpoint->TxLookupQueue);
  443. INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBufferHoldQueue);
  444. pEndpoint->target = target;
  445. /* pEndpoint->TxCreditFlowEnabled = (A_BOOL)htc_credit_flow; */
  446. pEndpoint->TxCreditFlowEnabled = (A_BOOL) 1;
  447. cdf_atomic_init(&pEndpoint->TxProcessCount);
  448. }
  449. }
  450. A_STATUS htc_start(HTC_HANDLE HTCHandle)
  451. {
  452. cdf_nbuf_t netbuf;
  453. A_STATUS status = A_OK;
  454. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  455. HTC_SETUP_COMPLETE_EX_MSG *pSetupComp;
  456. HTC_PACKET *pSendPacket;
  457. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Enter\n"));
  458. do {
  459. htc_config_target_hif_pipe(target);
  460. /* allocate a buffer to send */
  461. pSendPacket = htc_alloc_control_tx_packet(target);
  462. if (NULL == pSendPacket) {
  463. AR_DEBUG_ASSERT(false);
  464. cdf_print("%s: allocControlTxPacket failed\n",
  465. __func__);
  466. status = A_NO_MEMORY;
  467. break;
  468. }
  469. netbuf =
  470. (cdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket);
  471. /* assemble setup complete message */
  472. cdf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
  473. pSetupComp =
  474. (HTC_SETUP_COMPLETE_EX_MSG *) cdf_nbuf_data(netbuf);
  475. A_MEMZERO(pSetupComp, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
  476. HTC_SET_FIELD(pSetupComp, HTC_SETUP_COMPLETE_EX_MSG,
  477. MESSAGEID, HTC_MSG_SETUP_COMPLETE_EX_ID);
  478. if (!htc_credit_flow) {
  479. AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
  480. ("HTC will not use TX credit flow control\n"));
  481. pSetupComp->SetupFlags |=
  482. HTC_SETUP_COMPLETE_FLAGS_DISABLE_TX_CREDIT_FLOW;
  483. } else {
  484. AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
  485. ("HTC using TX credit flow control\n"));
  486. }
  487. #ifdef HIF_SDIO
  488. #if ENABLE_BUNDLE_RX
  489. if (HTC_ENABLE_BUNDLE(target))
  490. pSetupComp->SetupFlags |=
  491. HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV;
  492. #endif /* ENABLE_BUNDLE_RX */
  493. #endif /* HIF_SDIO */
  494. SET_HTC_PACKET_INFO_TX(pSendPacket,
  495. NULL,
  496. (A_UINT8 *) pSetupComp,
  497. sizeof(HTC_SETUP_COMPLETE_EX_MSG),
  498. ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
  499. status = htc_send_pkt((HTC_HANDLE) target, pSendPacket);
  500. if (A_FAILED(status)) {
  501. break;
  502. }
  503. } while (false);
  504. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Exit\n"));
  505. return status;
  506. }
  507. /*flush all queued buffers for surpriseremove case*/
  508. void htc_flush_surprise_remove(HTC_HANDLE HTCHandle)
  509. {
  510. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  511. int i;
  512. HTC_ENDPOINT *pEndpoint;
  513. #ifdef RX_SG_SUPPORT
  514. cdf_nbuf_t netbuf;
  515. cdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
  516. #endif
  517. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_flush_surprise_remove \n"));
  518. /* cleanup endpoints */
  519. for (i = 0; i < ENDPOINT_MAX; i++) {
  520. pEndpoint = &target->EndPoint[i];
  521. htc_flush_rx_hold_queue(target, pEndpoint);
  522. htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL);
  523. }
  524. hif_flush_surprise_remove(target->hif_dev);
  525. #ifdef RX_SG_SUPPORT
  526. LOCK_HTC_RX(target);
  527. while ((netbuf = cdf_nbuf_queue_remove(rx_sg_queue)) != NULL) {
  528. cdf_nbuf_free(netbuf);
  529. }
  530. RESET_RX_SG_CONFIG(target);
  531. UNLOCK_HTC_RX(target);
  532. #endif
  533. reset_endpoint_states(target);
  534. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_flush_surprise_remove \n"));
  535. }
  536. /* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */
  537. void htc_stop(HTC_HANDLE HTCHandle)
  538. {
  539. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  540. int i;
  541. HTC_ENDPOINT *pEndpoint;
  542. #ifdef RX_SG_SUPPORT
  543. cdf_nbuf_t netbuf;
  544. cdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
  545. #endif
  546. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_stop \n"));
  547. /* cleanup endpoints */
  548. for (i = 0; i < ENDPOINT_MAX; i++) {
  549. pEndpoint = &target->EndPoint[i];
  550. htc_flush_rx_hold_queue(target, pEndpoint);
  551. htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL);
  552. if (pEndpoint->ul_is_polled) {
  553. cdf_softirq_timer_cancel(&pEndpoint->ul_poll_timer);
  554. cdf_softirq_timer_free(&pEndpoint->ul_poll_timer);
  555. }
  556. }
  557. /* Note: htc_flush_endpoint_tx for all endpoints should be called before
  558. * hif_stop - otherwise htc_tx_completion_handler called from
  559. * hif_send_buffer_cleanup_on_pipe for residual tx frames in HIF layer,
  560. * might queue the packet again to HIF Layer - which could cause tx
  561. * buffer leak
  562. */
  563. hif_stop(target->hif_dev);
  564. #ifdef RX_SG_SUPPORT
  565. LOCK_HTC_RX(target);
  566. while ((netbuf = cdf_nbuf_queue_remove(rx_sg_queue)) != NULL) {
  567. cdf_nbuf_free(netbuf);
  568. }
  569. RESET_RX_SG_CONFIG(target);
  570. UNLOCK_HTC_RX(target);
  571. #endif
  572. reset_endpoint_states(target);
  573. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_stop \n"));
  574. }
  575. void htc_dump_credit_states(HTC_HANDLE HTCHandle)
  576. {
  577. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  578. HTC_ENDPOINT *pEndpoint;
  579. int i;
  580. for (i = 0; i < ENDPOINT_MAX; i++) {
  581. pEndpoint = &target->EndPoint[i];
  582. if (0 == pEndpoint->ServiceID) {
  583. continue;
  584. }
  585. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  586. ("--- EP : %d ServiceID: 0x%X --------------\n",
  587. pEndpoint->Id, pEndpoint->ServiceID));
  588. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  589. (" TxCredits : %d \n",
  590. pEndpoint->TxCredits));
  591. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  592. (" TxCreditSize : %d \n",
  593. pEndpoint->TxCreditSize));
  594. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  595. (" TxCreditsPerMaxMsg : %d \n",
  596. pEndpoint->TxCreditsPerMaxMsg));
  597. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  598. (" TxQueueDepth : %d \n",
  599. HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
  600. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  601. ("----------------------------------------------------\n"));
  602. }
  603. }
  604. A_BOOL htc_get_endpoint_statistics(HTC_HANDLE HTCHandle,
  605. HTC_ENDPOINT_ID Endpoint,
  606. HTC_ENDPOINT_STAT_ACTION Action,
  607. HTC_ENDPOINT_STATS *pStats)
  608. {
  609. #ifdef HTC_EP_STAT_PROFILING
  610. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  611. A_BOOL clearStats = false;
  612. A_BOOL sample = false;
  613. switch (Action) {
  614. case HTC_EP_STAT_SAMPLE:
  615. sample = true;
  616. break;
  617. case HTC_EP_STAT_SAMPLE_AND_CLEAR:
  618. sample = true;
  619. clearStats = true;
  620. break;
  621. case HTC_EP_STAT_CLEAR:
  622. clearStats = true;
  623. break;
  624. default:
  625. break;
  626. }
  627. A_ASSERT(Endpoint < ENDPOINT_MAX);
  628. /* lock out TX and RX while we sample and/or clear */
  629. LOCK_HTC_TX(target);
  630. LOCK_HTC_RX(target);
  631. if (sample) {
  632. A_ASSERT(pStats != NULL);
  633. /* return the stats to the caller */
  634. A_MEMCPY(pStats, &target->EndPoint[Endpoint].EndPointStats,
  635. sizeof(HTC_ENDPOINT_STATS));
  636. }
  637. if (clearStats) {
  638. /* reset stats */
  639. A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats,
  640. sizeof(HTC_ENDPOINT_STATS));
  641. }
  642. UNLOCK_HTC_RX(target);
  643. UNLOCK_HTC_TX(target);
  644. return true;
  645. #else
  646. return false;
  647. #endif
  648. }
  649. void *htc_get_targetdef(HTC_HANDLE htc_handle)
  650. {
  651. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
  652. return hif_get_targetdef(target->hif_dev);
  653. }
  654. /**
  655. * htc_set_target_to_sleep() - set target to sleep
  656. * @context: ol_softc context
  657. *
  658. * Return: none
  659. */
  660. void htc_set_target_to_sleep(void *context)
  661. {
  662. struct ol_softc *scn = (struct ol_softc *)context;
  663. hif_set_target_sleep(scn, true, false);
  664. }
  665. /**
  666. * htc_cancel_deferred_target_sleep() - cancel deferred target sleep
  667. * @context: ol_softc context
  668. *
  669. * Return: none
  670. */
  671. void htc_cancel_deferred_target_sleep(void *context)
  672. {
  673. struct ol_softc *scn = (struct ol_softc *)context;
  674. hif_cancel_deferred_target_sleep(scn);
  675. }
  676. #ifdef IPA_OFFLOAD
  677. /**
  678. * htc_ipa_get_ce_resource() - get uc resource on lower layer
  679. * @htc_handle: htc context
  680. * @ce_sr_base_paddr: copyengine source ring base physical address
  681. * @ce_sr_ring_size: copyengine source ring size
  682. * @ce_reg_paddr: copyengine register physical address
  683. *
  684. * Return: None
  685. */
  686. void htc_ipa_get_ce_resource(HTC_HANDLE htc_handle,
  687. cdf_dma_addr_t *ce_sr_base_paddr,
  688. uint32_t *ce_sr_ring_size,
  689. cdf_dma_addr_t *ce_reg_paddr)
  690. {
  691. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
  692. if (target->hif_dev != NULL) {
  693. hif_ipa_get_ce_resource(target->hif_dev,
  694. ce_sr_base_paddr,
  695. ce_sr_ring_size, ce_reg_paddr);
  696. }
  697. }
  698. #endif /* IPA_OFFLOAD */