htc.c 23 KB

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