htc.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149
  1. /*
  2. * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for
  5. * any purpose with or without fee is hereby granted, provided that the
  6. * above copyright notice and this permission notice appear in all
  7. * copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  10. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  12. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  13. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  14. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  16. * PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #include "htc_debug.h"
  19. #include "htc_internal.h"
  20. #include "htc_credit_history.h"
  21. #include <hif.h>
  22. #include <qdf_nbuf.h> /* qdf_nbuf_t */
  23. #include <qdf_types.h> /* qdf_print */
  24. #define MAX_HTC_RX_BUNDLE 2
  25. #if defined(WLAN_DEBUG) || defined(DEBUG)
  26. static ATH_DEBUG_MASK_DESCRIPTION g_htc_debug_description[] = {
  27. {ATH_DEBUG_SEND, "Send"},
  28. {ATH_DEBUG_RECV, "Recv"},
  29. {ATH_DEBUG_SYNC, "Sync"},
  30. {ATH_DEBUG_DUMP, "Dump Data (RX or TX)"},
  31. {ATH_DEBUG_SETUP, "Setup"},
  32. };
  33. ATH_DEBUG_INSTANTIATE_MODULE_VAR(htc,
  34. "htc",
  35. "Host Target Communications",
  36. ATH_DEBUG_MASK_DEFAULTS | ATH_DEBUG_INFO |
  37. ATH_DEBUG_SETUP,
  38. ATH_DEBUG_DESCRIPTION_COUNT
  39. (g_htc_debug_description),
  40. g_htc_debug_description);
  41. #endif
  42. #if (defined(WMI_MULTI_MAC_SVC) || defined(QCA_WIFI_QCA8074) || \
  43. defined(QCA_WIFI_QCA6018))
  44. static const uint32_t svc_id[] = {WMI_CONTROL_SVC, WMI_CONTROL_SVC_WMAC1,
  45. WMI_CONTROL_SVC_WMAC2};
  46. #else
  47. static const uint32_t svc_id[] = {WMI_CONTROL_SVC};
  48. #endif
  49. extern unsigned int htc_credit_flow;
  50. static void reset_endpoint_states(HTC_TARGET *target);
  51. static void destroy_htc_tx_ctrl_packet(HTC_PACKET *pPacket)
  52. {
  53. qdf_nbuf_t netbuf;
  54. netbuf = (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
  55. if (netbuf)
  56. qdf_nbuf_free(netbuf);
  57. qdf_mem_free(pPacket);
  58. }
  59. static HTC_PACKET *build_htc_tx_ctrl_packet(qdf_device_t osdev)
  60. {
  61. HTC_PACKET *pPacket = NULL;
  62. qdf_nbuf_t netbuf;
  63. do {
  64. pPacket = (HTC_PACKET *) qdf_mem_malloc(sizeof(HTC_PACKET));
  65. if (!pPacket)
  66. break;
  67. netbuf = qdf_nbuf_alloc(osdev, HTC_CONTROL_BUFFER_SIZE,
  68. 20, 4, true);
  69. if (!netbuf) {
  70. qdf_mem_free(pPacket);
  71. pPacket = NULL;
  72. break;
  73. }
  74. SET_HTC_PACKET_NET_BUF_CONTEXT(pPacket, netbuf);
  75. } while (false);
  76. return pPacket;
  77. }
  78. void htc_free_control_tx_packet(HTC_TARGET *target, HTC_PACKET *pPacket)
  79. {
  80. #ifdef TODO_FIXME
  81. LOCK_HTC(target);
  82. HTC_PACKET_ENQUEUE(&target->ControlBufferTXFreeList, pPacket);
  83. UNLOCK_HTC(target);
  84. /* TODO_FIXME netbufs cannot be RESET! */
  85. #else
  86. destroy_htc_tx_ctrl_packet(pPacket);
  87. #endif
  88. }
  89. HTC_PACKET *htc_alloc_control_tx_packet(HTC_TARGET *target)
  90. {
  91. #ifdef TODO_FIXME
  92. HTC_PACKET *pPacket;
  93. LOCK_HTC(target);
  94. pPacket = htc_packet_dequeue(&target->ControlBufferTXFreeList);
  95. UNLOCK_HTC(target);
  96. return pPacket;
  97. #else
  98. return build_htc_tx_ctrl_packet(target->osdev);
  99. #endif
  100. }
  101. /* Set the target failure handling callback */
  102. void htc_set_target_failure_callback(HTC_HANDLE HTCHandle,
  103. HTC_TARGET_FAILURE Callback)
  104. {
  105. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  106. target->HTCInitInfo.TargetFailure = Callback;
  107. }
  108. void htc_dump(HTC_HANDLE HTCHandle, uint8_t CmdId, bool start)
  109. {
  110. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  111. hif_dump(target->hif_dev, CmdId, start);
  112. }
  113. /* cleanup the HTC instance */
  114. static void htc_cleanup(HTC_TARGET *target)
  115. {
  116. HTC_PACKET *pPacket;
  117. int i;
  118. HTC_ENDPOINT *endpoint;
  119. HTC_PACKET_QUEUE *pkt_queue;
  120. qdf_nbuf_t netbuf;
  121. if (target->hif_dev) {
  122. hif_detach_htc(target->hif_dev);
  123. hif_mask_interrupt_call(target->hif_dev);
  124. target->hif_dev = NULL;
  125. }
  126. while (true) {
  127. pPacket = allocate_htc_packet_container(target);
  128. if (!pPacket)
  129. break;
  130. qdf_mem_free(pPacket);
  131. }
  132. LOCK_HTC_TX(target);
  133. pPacket = target->pBundleFreeList;
  134. target->pBundleFreeList = NULL;
  135. UNLOCK_HTC_TX(target);
  136. while (pPacket) {
  137. HTC_PACKET *pPacketTmp = (HTC_PACKET *) pPacket->ListLink.pNext;
  138. netbuf = GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
  139. if (netbuf)
  140. qdf_nbuf_free(netbuf);
  141. pkt_queue = pPacket->pContext;
  142. if (pkt_queue)
  143. qdf_mem_free(pkt_queue);
  144. qdf_mem_free(pPacket);
  145. pPacket = pPacketTmp;
  146. }
  147. #ifdef TODO_FIXME
  148. while (true) {
  149. pPacket = htc_alloc_control_tx_packet(target);
  150. if (!pPacket)
  151. break;
  152. netbuf = (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pPacket);
  153. if (netbuf)
  154. qdf_nbuf_free(netbuf);
  155. qdf_mem_free(pPacket);
  156. }
  157. #endif
  158. htc_flush_endpoint_txlookupQ(target, ENDPOINT_0, true);
  159. qdf_spinlock_destroy(&target->HTCLock);
  160. qdf_spinlock_destroy(&target->HTCRxLock);
  161. qdf_spinlock_destroy(&target->HTCTxLock);
  162. for (i = 0; i < ENDPOINT_MAX; i++) {
  163. endpoint = &target->endpoint[i];
  164. qdf_spinlock_destroy(&endpoint->lookup_queue_lock);
  165. }
  166. /* free our instance */
  167. qdf_mem_free(target);
  168. }
  169. #ifdef FEATURE_RUNTIME_PM
  170. /**
  171. * htc_runtime_pm_init(): runtime pm related intialization
  172. *
  173. * need to initialize a work item.
  174. */
  175. static void htc_runtime_pm_init(HTC_TARGET *target)
  176. {
  177. qdf_create_work(0, &target->queue_kicker, htc_kick_queues, target);
  178. }
  179. /**
  180. * htc_runtime_suspend() - runtime suspend HTC
  181. *
  182. * @htc_ctx: HTC context pointer
  183. *
  184. * This is a dummy function for symmetry.
  185. *
  186. * Return: 0 for success
  187. */
  188. int htc_runtime_suspend(HTC_HANDLE htc_ctx)
  189. {
  190. return 0;
  191. }
  192. /**
  193. * htc_runtime_resume(): resume htc
  194. *
  195. * The htc message queue needs to be kicked off after
  196. * a runtime resume. Otherwise messages would get stuck.
  197. *
  198. * @htc_ctx: HTC context pointer
  199. *
  200. * Return: 0 for success;
  201. */
  202. int htc_runtime_resume(HTC_HANDLE htc_ctx)
  203. {
  204. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_ctx);
  205. if (!target)
  206. return 0;
  207. qdf_sched_work(0, &target->queue_kicker);
  208. return 0;
  209. }
  210. #else
  211. static inline void htc_runtime_pm_init(HTC_TARGET *target) { }
  212. #endif
  213. #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT)
  214. static
  215. void htc_update_rx_bundle_stats(void *ctx, uint8_t no_of_pkt_in_bundle)
  216. {
  217. HTC_TARGET *target = (HTC_TARGET *)ctx;
  218. no_of_pkt_in_bundle--;
  219. if (target && (no_of_pkt_in_bundle < HTC_MAX_MSG_PER_BUNDLE_RX))
  220. target->rx_bundle_stats[no_of_pkt_in_bundle]++;
  221. }
  222. #else
  223. static
  224. void htc_update_rx_bundle_stats(void *ctx, uint8_t no_of_pkt_in_bundle)
  225. {
  226. }
  227. #endif
  228. /* registered target arrival callback from the HIF layer */
  229. HTC_HANDLE htc_create(void *ol_sc, struct htc_init_info *pInfo,
  230. qdf_device_t osdev, uint32_t con_mode)
  231. {
  232. struct hif_msg_callbacks htcCallbacks;
  233. HTC_ENDPOINT *pEndpoint = NULL;
  234. HTC_TARGET *target = NULL;
  235. int i;
  236. if (!ol_sc) {
  237. HTC_ERROR("%s: ol_sc = NULL", __func__);
  238. return NULL;
  239. }
  240. HTC_TRACE("+htc_create .. HIF :%pK", ol_sc);
  241. A_REGISTER_MODULE_DEBUG_INFO(htc);
  242. target = (HTC_TARGET *) qdf_mem_malloc(sizeof(HTC_TARGET));
  243. if (!target)
  244. return NULL;
  245. htc_runtime_pm_init(target);
  246. htc_credit_history_init();
  247. qdf_spinlock_create(&target->HTCLock);
  248. qdf_spinlock_create(&target->HTCRxLock);
  249. qdf_spinlock_create(&target->HTCTxLock);
  250. for (i = 0; i < ENDPOINT_MAX; i++) {
  251. pEndpoint = &target->endpoint[i];
  252. qdf_spinlock_create(&pEndpoint->lookup_queue_lock);
  253. }
  254. target->is_nodrop_pkt = false;
  255. target->htc_hdr_length_check = false;
  256. target->wmi_ep_count = 1;
  257. do {
  258. qdf_mem_copy(&target->HTCInitInfo, pInfo,
  259. sizeof(struct htc_init_info));
  260. target->host_handle = pInfo->pContext;
  261. target->osdev = osdev;
  262. target->con_mode = con_mode;
  263. reset_endpoint_states(target);
  264. INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList);
  265. for (i = 0; i < HTC_PACKET_CONTAINER_ALLOCATION; i++) {
  266. HTC_PACKET *pPacket = (HTC_PACKET *)
  267. qdf_mem_malloc(sizeof(HTC_PACKET));
  268. if (pPacket)
  269. free_htc_packet_container(target, pPacket);
  270. }
  271. #ifdef TODO_FIXME
  272. for (i = 0; i < NUM_CONTROL_TX_BUFFERS; i++) {
  273. pPacket = build_htc_tx_ctrl_packet();
  274. if (!pPacket)
  275. break;
  276. htc_free_control_tx_packet(target, pPacket);
  277. }
  278. #endif
  279. /* setup HIF layer callbacks */
  280. qdf_mem_zero(&htcCallbacks, sizeof(struct hif_msg_callbacks));
  281. htcCallbacks.Context = target;
  282. htcCallbacks.rxCompletionHandler = htc_rx_completion_handler;
  283. htcCallbacks.txCompletionHandler = htc_tx_completion_handler;
  284. htcCallbacks.txResourceAvailHandler =
  285. htc_tx_resource_avail_handler;
  286. htcCallbacks.fwEventHandler = htc_fw_event_handler;
  287. htcCallbacks.update_bundle_stats = htc_update_rx_bundle_stats;
  288. target->hif_dev = ol_sc;
  289. /* Get HIF default pipe for HTC message exchange */
  290. pEndpoint = &target->endpoint[ENDPOINT_0];
  291. hif_post_init(target->hif_dev, target, &htcCallbacks);
  292. hif_get_default_pipe(target->hif_dev, &pEndpoint->UL_PipeID,
  293. &pEndpoint->DL_PipeID);
  294. hif_set_initial_wakeup_cb(target->hif_dev,
  295. pInfo->target_initial_wakeup_cb,
  296. pInfo->target_psoc);
  297. } while (false);
  298. htc_recv_init(target);
  299. HTC_TRACE("-htc_create: (0x%pK)", target);
  300. return (HTC_HANDLE) target;
  301. }
  302. void htc_destroy(HTC_HANDLE HTCHandle)
  303. {
  304. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  305. AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
  306. ("+htc_destroy .. Destroying :0x%pK\n", target));
  307. hif_stop(htc_get_hif_device(HTCHandle));
  308. if (target)
  309. htc_cleanup(target);
  310. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_destroy\n"));
  311. }
  312. /* get the low level HIF device for the caller , the caller may wish to do low
  313. * level HIF requests
  314. */
  315. void *htc_get_hif_device(HTC_HANDLE HTCHandle)
  316. {
  317. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  318. return target->hif_dev;
  319. }
  320. static void htc_control_tx_complete(void *Context, HTC_PACKET *pPacket)
  321. {
  322. HTC_TARGET *target = (HTC_TARGET *) Context;
  323. AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
  324. ("+-htc_control_tx_complete 0x%pK (l:%d)\n", pPacket,
  325. pPacket->ActualLength));
  326. htc_free_control_tx_packet(target, pPacket);
  327. }
  328. /* TODO, this is just a temporary max packet size */
  329. #define MAX_MESSAGE_SIZE 1536
  330. /**
  331. * htc_setup_epping_credit_allocation() - allocate credits/HTC buffers to WMI
  332. * @scn: pointer to hif_opaque_softc
  333. * @pEntry: pointer to tx credit allocation entry
  334. * @credits: number of credits
  335. *
  336. * Return: None
  337. */
  338. static void
  339. htc_setup_epping_credit_allocation(struct hif_opaque_softc *scn,
  340. struct htc_service_tx_credit_allocation *pEntry,
  341. int credits)
  342. {
  343. switch (hif_get_bus_type(scn)) {
  344. case QDF_BUS_TYPE_PCI:
  345. case QDF_BUS_TYPE_USB:
  346. pEntry++;
  347. pEntry->service_id = WMI_DATA_BE_SVC;
  348. pEntry->CreditAllocation = (credits >> 1);
  349. pEntry++;
  350. pEntry->service_id = WMI_DATA_BK_SVC;
  351. pEntry->CreditAllocation = (credits >> 1);
  352. break;
  353. case QDF_BUS_TYPE_SDIO:
  354. pEntry++;
  355. pEntry->service_id = WMI_DATA_BE_SVC;
  356. pEntry->CreditAllocation = credits;
  357. break;
  358. default:
  359. break;
  360. }
  361. }
  362. /**
  363. * htc_setup_target_buffer_assignments() - setup target buffer assignments
  364. * @target: HTC Target Pointer
  365. *
  366. * Return: A_STATUS
  367. */
  368. static
  369. A_STATUS htc_setup_target_buffer_assignments(HTC_TARGET *target)
  370. {
  371. struct htc_service_tx_credit_allocation *pEntry;
  372. A_STATUS status;
  373. int credits;
  374. int creditsPerMaxMsg;
  375. creditsPerMaxMsg = MAX_MESSAGE_SIZE / target->TargetCreditSize;
  376. if (MAX_MESSAGE_SIZE % target->TargetCreditSize)
  377. creditsPerMaxMsg++;
  378. /* TODO, this should be configured by the caller! */
  379. credits = target->TotalTransmitCredits;
  380. pEntry = &target->ServiceTxAllocTable[0];
  381. status = A_OK;
  382. /*
  383. * Allocate all credists/HTC buffers to WMI.
  384. * no buffers are used/required for data. data always
  385. * remains on host.
  386. */
  387. if (HTC_IS_EPPING_ENABLED(target->con_mode)) {
  388. pEntry++;
  389. pEntry->service_id = WMI_CONTROL_SVC;
  390. pEntry->CreditAllocation = credits;
  391. /* endpoint ping is a testing tool directly on top of HTC in
  392. * both target and host sides.
  393. * In target side, the endppint ping fw has no wlan stack and
  394. * FW mboxping app directly sits on HTC and it simply drops
  395. * or loops back TX packets. For rx perf, FW mboxping app
  396. * generates packets and passes packets to HTC to send to host.
  397. * There is no WMI message exchanges between host and target
  398. * in endpoint ping case.
  399. * In host side, the endpoint ping driver is a Ethernet driver
  400. * and it directly sits on HTC. Only HIF, HTC, QDF, ADF are
  401. * used by the endpoint ping driver. There is no wifi stack
  402. * at all in host side also. For tx perf use case,
  403. * the user space mboxping app sends the raw packets to endpoint
  404. * ping driver and it directly forwards to HTC for transmission
  405. * to stress the bus. For the rx perf, HTC passes the received
  406. * packets to endpoint ping driver and it is passed to the user
  407. * space through the Ethernet interface.
  408. * For credit allocation, in SDIO bus case, only BE service is
  409. * used for tx/rx perf testing so that all credits are given
  410. * to BE service. In PCIe and USB bus case, endpoint ping uses
  411. * both BE and BK services to stress the bus so that the total
  412. * credits are equally distributed to BE and BK services.
  413. */
  414. htc_setup_epping_credit_allocation(target->hif_dev,
  415. pEntry, credits);
  416. } else {
  417. int i;
  418. uint32_t max_wmi_svc = (sizeof(svc_id) / sizeof(uint32_t));
  419. if ((target->wmi_ep_count == 0) ||
  420. (target->wmi_ep_count > max_wmi_svc))
  421. return A_ERROR;
  422. /*
  423. * Divide credit among number of endpoints for WMI
  424. */
  425. credits = credits / target->wmi_ep_count;
  426. for (i = 0; i < target->wmi_ep_count; i++) {
  427. status = A_OK;
  428. pEntry++;
  429. pEntry->service_id = svc_id[i];
  430. pEntry->CreditAllocation = credits;
  431. }
  432. }
  433. if (A_SUCCESS(status)) {
  434. int i;
  435. for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) {
  436. if (target->ServiceTxAllocTable[i].service_id != 0) {
  437. AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
  438. ("SVS Index : %d TX : 0x%2.2X : alloc:%d",
  439. i,
  440. target->ServiceTxAllocTable[i].
  441. service_id,
  442. target->ServiceTxAllocTable[i].
  443. CreditAllocation));
  444. }
  445. }
  446. }
  447. return status;
  448. }
  449. uint8_t htc_get_credit_allocation(HTC_TARGET *target, uint16_t service_id)
  450. {
  451. uint8_t allocation = 0;
  452. int i;
  453. for (i = 0; i < HTC_MAX_SERVICE_ALLOC_ENTRIES; i++) {
  454. if (target->ServiceTxAllocTable[i].service_id == service_id) {
  455. allocation =
  456. target->ServiceTxAllocTable[i].CreditAllocation;
  457. }
  458. }
  459. if (0 == allocation) {
  460. AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1,
  461. ("HTC Service TX : 0x%2.2X : allocation is zero!\n",
  462. service_id));
  463. }
  464. return allocation;
  465. }
  466. QDF_STATUS htc_wait_target(HTC_HANDLE HTCHandle)
  467. {
  468. QDF_STATUS status = QDF_STATUS_SUCCESS;
  469. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  470. HTC_READY_EX_MSG *pReadyMsg;
  471. struct htc_service_connect_req connect;
  472. struct htc_service_connect_resp resp;
  473. HTC_READY_MSG *rdy_msg;
  474. uint16_t htc_rdy_msg_id;
  475. uint8_t i = 0;
  476. HTC_PACKET *rx_bundle_packet, *temp_bundle_packet;
  477. AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
  478. ("htc_wait_target - Enter (target:0x%pK)\n", HTCHandle));
  479. AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, ("+HWT\n"));
  480. do {
  481. status = hif_start(target->hif_dev);
  482. if (QDF_IS_STATUS_ERROR(status)) {
  483. AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
  484. ("hif_start failed\n"));
  485. break;
  486. }
  487. status = htc_wait_recv_ctrl_message(target);
  488. if (QDF_IS_STATUS_ERROR(status))
  489. break;
  490. if (target->CtrlResponseLength < (sizeof(HTC_READY_EX_MSG))) {
  491. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  492. ("Invalid HTC Ready Msg Len:%d!\n",
  493. target->CtrlResponseLength));
  494. status = QDF_STATUS_E_BADMSG;
  495. break;
  496. }
  497. pReadyMsg = (HTC_READY_EX_MSG *) target->CtrlResponseBuffer;
  498. rdy_msg = &pReadyMsg->Version2_0_Info;
  499. htc_rdy_msg_id =
  500. HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, MESSAGEID);
  501. if (htc_rdy_msg_id != HTC_MSG_READY_ID) {
  502. AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
  503. ("Invalid HTC Ready Msg : 0x%X!\n",
  504. htc_rdy_msg_id));
  505. status = QDF_STATUS_E_BADMSG;
  506. break;
  507. }
  508. target->TotalTransmitCredits = HTC_GET_FIELD(rdy_msg,
  509. HTC_READY_MSG, CREDITCOUNT);
  510. if (target->HTCInitInfo.cfg_wmi_credit_cnt &&
  511. (target->HTCInitInfo.cfg_wmi_credit_cnt <
  512. target->TotalTransmitCredits))
  513. /*
  514. * If INI configured value is less than FW advertised,
  515. * then use INI configured value, otherwise use FW
  516. * advertised.
  517. */
  518. target->TotalTransmitCredits =
  519. target->HTCInitInfo.cfg_wmi_credit_cnt;
  520. target->TargetCreditSize =
  521. (int)HTC_GET_FIELD(rdy_msg, HTC_READY_MSG, CREDITSIZE);
  522. target->MaxMsgsPerHTCBundle =
  523. (uint8_t) pReadyMsg->MaxMsgsPerHTCBundle;
  524. UPDATE_ALT_CREDIT(target, pReadyMsg->AltDataCreditSize);
  525. /* for old fw this value is set to 0. But the minimum value
  526. * should be 1, i.e., no bundling
  527. */
  528. if (target->MaxMsgsPerHTCBundle < 1)
  529. target->MaxMsgsPerHTCBundle = 1;
  530. AR_DEBUG_PRINTF(ATH_DEBUG_INIT,
  531. ("Target Ready! TX resource : %d size:%d, MaxMsgsPerHTCBundle = %d",
  532. target->TotalTransmitCredits,
  533. target->TargetCreditSize,
  534. target->MaxMsgsPerHTCBundle));
  535. if ((0 == target->TotalTransmitCredits)
  536. || (0 == target->TargetCreditSize)) {
  537. status = QDF_STATUS_E_ABORTED;
  538. break;
  539. }
  540. /* Allocate expected number of RX bundle buffer allocation */
  541. if (HTC_RX_BUNDLE_ENABLED(target)) {
  542. temp_bundle_packet = NULL;
  543. for (i = 0; i < MAX_HTC_RX_BUNDLE; i++) {
  544. rx_bundle_packet =
  545. allocate_htc_bundle_packet(target);
  546. if (rx_bundle_packet)
  547. rx_bundle_packet->ListLink.pNext =
  548. (DL_LIST *)temp_bundle_packet;
  549. else
  550. break;
  551. temp_bundle_packet = rx_bundle_packet;
  552. }
  553. LOCK_HTC_TX(target);
  554. target->pBundleFreeList = temp_bundle_packet;
  555. UNLOCK_HTC_TX(target);
  556. }
  557. /* done processing */
  558. target->CtrlResponseProcessing = false;
  559. htc_setup_target_buffer_assignments(target);
  560. /* setup our pseudo HTC control endpoint connection */
  561. qdf_mem_zero(&connect, sizeof(connect));
  562. qdf_mem_zero(&resp, sizeof(resp));
  563. connect.EpCallbacks.pContext = target;
  564. connect.EpCallbacks.EpTxComplete = htc_control_tx_complete;
  565. connect.EpCallbacks.EpRecv = htc_control_rx_complete;
  566. connect.MaxSendQueueDepth = NUM_CONTROL_TX_BUFFERS;
  567. connect.service_id = HTC_CTRL_RSVD_SVC;
  568. /* connect fake service */
  569. status = htc_connect_service((HTC_HANDLE) target,
  570. &connect, &resp);
  571. } while (false);
  572. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_wait_target - Exit (%d)\n",
  573. status));
  574. AR_DEBUG_PRINTF(ATH_DEBUG_RSVD1, ("-HWT\n"));
  575. return status;
  576. }
  577. /* start HTC, this is called after all services are connected */
  578. static A_STATUS htc_config_target_hif_pipe(HTC_TARGET *target)
  579. {
  580. return A_OK;
  581. }
  582. static void reset_endpoint_states(HTC_TARGET *target)
  583. {
  584. HTC_ENDPOINT *pEndpoint;
  585. int i;
  586. for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
  587. pEndpoint = &target->endpoint[i];
  588. pEndpoint->service_id = 0;
  589. pEndpoint->MaxMsgLength = 0;
  590. pEndpoint->MaxTxQueueDepth = 0;
  591. pEndpoint->Id = i;
  592. INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue);
  593. INIT_HTC_PACKET_QUEUE(&pEndpoint->TxLookupQueue);
  594. INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBufferHoldQueue);
  595. pEndpoint->target = target;
  596. pEndpoint->TxCreditFlowEnabled = (bool)htc_credit_flow;
  597. qdf_atomic_init(&pEndpoint->TxProcessCount);
  598. }
  599. }
  600. /**
  601. * htc_start() - Main HTC function to trigger HTC start
  602. * @HTCHandle: pointer to HTC handle
  603. *
  604. * Return: QDF_STATUS_SUCCESS for success or an appropriate QDF_STATUS error
  605. */
  606. QDF_STATUS htc_start(HTC_HANDLE HTCHandle)
  607. {
  608. qdf_nbuf_t netbuf;
  609. QDF_STATUS status = QDF_STATUS_SUCCESS;
  610. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  611. HTC_SETUP_COMPLETE_EX_MSG *pSetupComp;
  612. HTC_PACKET *pSendPacket;
  613. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Enter\n"));
  614. do {
  615. htc_config_target_hif_pipe(target);
  616. /* allocate a buffer to send */
  617. pSendPacket = htc_alloc_control_tx_packet(target);
  618. if (!pSendPacket) {
  619. AR_DEBUG_ASSERT(false);
  620. qdf_print("%s: allocControlTxPacket failed",
  621. __func__);
  622. status = QDF_STATUS_E_NOMEM;
  623. break;
  624. }
  625. netbuf =
  626. (qdf_nbuf_t) GET_HTC_PACKET_NET_BUF_CONTEXT(pSendPacket);
  627. /* assemble setup complete message */
  628. qdf_nbuf_put_tail(netbuf, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
  629. pSetupComp =
  630. (HTC_SETUP_COMPLETE_EX_MSG *) qdf_nbuf_data(netbuf);
  631. qdf_mem_zero(pSetupComp, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
  632. HTC_SET_FIELD(pSetupComp, HTC_SETUP_COMPLETE_EX_MSG,
  633. MESSAGEID, HTC_MSG_SETUP_COMPLETE_EX_ID);
  634. if (!htc_credit_flow) {
  635. AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
  636. ("HTC will not use TX credit flow control"));
  637. pSetupComp->SetupFlags |=
  638. HTC_SETUP_COMPLETE_FLAGS_DISABLE_TX_CREDIT_FLOW;
  639. } else {
  640. AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
  641. ("HTC using TX credit flow control"));
  642. }
  643. if ((hif_get_bus_type(target->hif_dev) == QDF_BUS_TYPE_SDIO) ||
  644. (hif_get_bus_type(target->hif_dev) ==
  645. QDF_BUS_TYPE_USB)) {
  646. if (HTC_RX_BUNDLE_ENABLED(target))
  647. pSetupComp->SetupFlags |=
  648. HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV;
  649. hif_set_bundle_mode(target->hif_dev, true,
  650. HTC_MAX_MSG_PER_BUNDLE_RX);
  651. pSetupComp->MaxMsgsPerBundledRecv = HTC_MAX_MSG_PER_BUNDLE_RX;
  652. }
  653. SET_HTC_PACKET_INFO_TX(pSendPacket,
  654. NULL,
  655. (uint8_t *) pSetupComp,
  656. sizeof(HTC_SETUP_COMPLETE_EX_MSG),
  657. ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
  658. status = htc_send_pkt((HTC_HANDLE) target, pSendPacket);
  659. if (QDF_IS_STATUS_ERROR(status))
  660. break;
  661. } while (false);
  662. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htc_start Exit\n"));
  663. return status;
  664. }
  665. /*flush all queued buffers for surpriseremove case*/
  666. void htc_flush_surprise_remove(HTC_HANDLE HTCHandle)
  667. {
  668. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  669. int i;
  670. HTC_ENDPOINT *pEndpoint;
  671. #ifdef RX_SG_SUPPORT
  672. qdf_nbuf_t netbuf;
  673. qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
  674. #endif
  675. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_flush_surprise_remove\n"));
  676. /* cleanup endpoints */
  677. for (i = 0; i < ENDPOINT_MAX; i++) {
  678. pEndpoint = &target->endpoint[i];
  679. htc_flush_rx_hold_queue(target, pEndpoint);
  680. htc_flush_endpoint_tx(target, pEndpoint, HTC_TX_PACKET_TAG_ALL);
  681. }
  682. hif_flush_surprise_remove(target->hif_dev);
  683. #ifdef RX_SG_SUPPORT
  684. LOCK_HTC_RX(target);
  685. while ((netbuf = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL)
  686. qdf_nbuf_free(netbuf);
  687. RESET_RX_SG_CONFIG(target);
  688. UNLOCK_HTC_RX(target);
  689. #endif
  690. reset_endpoint_states(target);
  691. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_flush_surprise_remove\n"));
  692. }
  693. /* stop HTC communications, i.e. stop interrupt reception, and flush all queued
  694. * buffers
  695. */
  696. void htc_stop(HTC_HANDLE HTCHandle)
  697. {
  698. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  699. int i;
  700. HTC_ENDPOINT *endpoint;
  701. #ifdef RX_SG_SUPPORT
  702. qdf_nbuf_t netbuf;
  703. qdf_nbuf_queue_t *rx_sg_queue = &target->RxSgQueue;
  704. #endif
  705. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+htc_stop\n"));
  706. HTC_INFO("%s: endpoints cleanup\n", __func__);
  707. /* cleanup endpoints */
  708. for (i = 0; i < ENDPOINT_MAX; i++) {
  709. endpoint = &target->endpoint[i];
  710. htc_flush_rx_hold_queue(target, endpoint);
  711. htc_flush_endpoint_tx(target, endpoint, HTC_TX_PACKET_TAG_ALL);
  712. if (endpoint->ul_is_polled) {
  713. qdf_timer_stop(&endpoint->ul_poll_timer);
  714. qdf_timer_free(&endpoint->ul_poll_timer);
  715. }
  716. }
  717. /* Note: htc_flush_endpoint_tx for all endpoints should be called before
  718. * hif_stop - otherwise htc_tx_completion_handler called from
  719. * hif_send_buffer_cleanup_on_pipe for residual tx frames in HIF layer,
  720. * might queue the packet again to HIF Layer - which could cause tx
  721. * buffer leak
  722. */
  723. HTC_INFO("%s: stopping hif layer\n", __func__);
  724. hif_stop(target->hif_dev);
  725. #ifdef RX_SG_SUPPORT
  726. LOCK_HTC_RX(target);
  727. while ((netbuf = qdf_nbuf_queue_remove(rx_sg_queue)) != NULL)
  728. qdf_nbuf_free(netbuf);
  729. RESET_RX_SG_CONFIG(target);
  730. UNLOCK_HTC_RX(target);
  731. #endif
  732. /**
  733. * In SSR case, HTC tx completion callback for wmi will be blocked
  734. * by TARGET_STATUS_RESET and HTC packets will be left unfreed on
  735. * lookup queue.
  736. *
  737. * In case of target failing to send wmi_ready_event, the htc connect
  738. * msg buffer will be left unmapped and not freed. So calling the
  739. * completion handler for this buffer will handle this scenario.
  740. */
  741. HTC_INFO("%s: flush endpoints Tx lookup queue\n", __func__);
  742. for (i = 0; i < ENDPOINT_MAX; i++) {
  743. endpoint = &target->endpoint[i];
  744. if (endpoint->service_id == WMI_CONTROL_SVC)
  745. htc_flush_endpoint_txlookupQ(target, i, false);
  746. else if (endpoint->service_id == HTC_CTRL_RSVD_SVC)
  747. htc_flush_endpoint_txlookupQ(target, i, true);
  748. }
  749. HTC_INFO("%s: resetting endpoints state\n", __func__);
  750. reset_endpoint_states(target);
  751. AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-htc_stop\n"));
  752. }
  753. void htc_dump_credit_states(HTC_HANDLE HTCHandle)
  754. {
  755. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  756. HTC_ENDPOINT *pEndpoint;
  757. int i;
  758. for (i = 0; i < ENDPOINT_MAX; i++) {
  759. pEndpoint = &target->endpoint[i];
  760. if (0 == pEndpoint->service_id)
  761. continue;
  762. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  763. ("--- EP : %d service_id: 0x%X --------------\n",
  764. pEndpoint->Id, pEndpoint->service_id));
  765. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  766. (" TxCredits : %d\n",
  767. pEndpoint->TxCredits));
  768. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  769. (" TxCreditSize : %d\n",
  770. pEndpoint->TxCreditSize));
  771. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  772. (" TxCreditsPerMaxMsg : %d\n",
  773. pEndpoint->TxCreditsPerMaxMsg));
  774. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  775. (" TxQueueDepth : %d\n",
  776. HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
  777. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  778. ("----------------------------------------\n"));
  779. }
  780. }
  781. bool htc_get_endpoint_statistics(HTC_HANDLE HTCHandle,
  782. HTC_ENDPOINT_ID Endpoint,
  783. enum htc_endpoint_stat_action Action,
  784. struct htc_endpoint_stats *pStats)
  785. {
  786. #ifdef HTC_EP_STAT_PROFILING
  787. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  788. bool clearStats = false;
  789. bool sample = false;
  790. switch (Action) {
  791. case HTC_EP_STAT_SAMPLE:
  792. sample = true;
  793. break;
  794. case HTC_EP_STAT_SAMPLE_AND_CLEAR:
  795. sample = true;
  796. clearStats = true;
  797. break;
  798. case HTC_EP_STAT_CLEAR:
  799. clearStats = true;
  800. break;
  801. default:
  802. break;
  803. }
  804. A_ASSERT(Endpoint < ENDPOINT_MAX);
  805. /* lock out TX and RX while we sample and/or clear */
  806. LOCK_HTC_TX(target);
  807. LOCK_HTC_RX(target);
  808. if (sample) {
  809. A_ASSERT(pStats);
  810. /* return the stats to the caller */
  811. qdf_mem_copy(pStats, &target->endpoint[Endpoint].endpoint_stats,
  812. sizeof(struct htc_endpoint_stats));
  813. }
  814. if (clearStats) {
  815. /* reset stats */
  816. qdf_mem_zero(&target->endpoint[Endpoint].endpoint_stats,
  817. sizeof(struct htc_endpoint_stats));
  818. }
  819. UNLOCK_HTC_RX(target);
  820. UNLOCK_HTC_TX(target);
  821. return true;
  822. #else
  823. return false;
  824. #endif
  825. }
  826. void *htc_get_targetdef(HTC_HANDLE htc_handle)
  827. {
  828. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
  829. return hif_get_targetdef(target->hif_dev);
  830. }
  831. #ifdef IPA_OFFLOAD
  832. /**
  833. * htc_ipa_get_ce_resource() - get uc resource on lower layer
  834. * @htc_handle: htc context
  835. * @ce_sr_base_paddr: copyengine source ring base physical address
  836. * @ce_sr_ring_size: copyengine source ring size
  837. * @ce_reg_paddr: copyengine register physical address
  838. *
  839. * Return: None
  840. */
  841. void htc_ipa_get_ce_resource(HTC_HANDLE htc_handle,
  842. qdf_shared_mem_t **ce_sr,
  843. uint32_t *ce_sr_ring_size,
  844. qdf_dma_addr_t *ce_reg_paddr)
  845. {
  846. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
  847. if (target->hif_dev)
  848. hif_ipa_get_ce_resource(target->hif_dev,
  849. ce_sr, ce_sr_ring_size, ce_reg_paddr);
  850. }
  851. #endif /* IPA_OFFLOAD */
  852. #if defined(DEBUG_HL_LOGGING) && defined(CONFIG_HL_SUPPORT)
  853. void htc_dump_bundle_stats(HTC_HANDLE HTCHandle)
  854. {
  855. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  856. int total, i;
  857. total = 0;
  858. for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_RX; i++)
  859. total += target->rx_bundle_stats[i];
  860. if (total) {
  861. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("RX Bundle stats:\n"));
  862. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("Total RX packets: %d\n",
  863. total));
  864. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (
  865. "Number of bundle: Number of packets\n"));
  866. for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_RX; i++)
  867. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  868. ("%10d:%10d(%2d%s)\n", (i+1),
  869. target->rx_bundle_stats[i],
  870. ((target->rx_bundle_stats[i]*100)/
  871. total), "%"));
  872. }
  873. total = 0;
  874. for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_TX; i++)
  875. total += target->tx_bundle_stats[i];
  876. if (total) {
  877. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("TX Bundle stats:\n"));
  878. AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("Total TX packets: %d\n",
  879. total));
  880. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  881. ("Number of bundle: Number of packets\n"));
  882. for (i = 0; i < HTC_MAX_MSG_PER_BUNDLE_TX; i++)
  883. AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
  884. ("%10d:%10d(%2d%s)\n", (i+1),
  885. target->tx_bundle_stats[i],
  886. ((target->tx_bundle_stats[i]*100)/
  887. total), "%"));
  888. }
  889. }
  890. void htc_clear_bundle_stats(HTC_HANDLE HTCHandle)
  891. {
  892. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
  893. qdf_mem_zero(&target->rx_bundle_stats, sizeof(target->rx_bundle_stats));
  894. qdf_mem_zero(&target->tx_bundle_stats, sizeof(target->tx_bundle_stats));
  895. }
  896. #endif
  897. /**
  898. * htc_vote_link_down - API to vote for link down
  899. * @htc_handle: HTC handle
  900. *
  901. * API for upper layers to call HIF to vote for link down
  902. *
  903. * Return: void
  904. */
  905. void htc_vote_link_down(HTC_HANDLE htc_handle)
  906. {
  907. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
  908. if (!target->hif_dev)
  909. return;
  910. hif_vote_link_down(target->hif_dev);
  911. }
  912. /**
  913. * htc_vote_link_up - API to vote for link up
  914. * @htc_handle: HTC Handle
  915. *
  916. * API for upper layers to call HIF to vote for link up
  917. *
  918. * Return: void
  919. */
  920. void htc_vote_link_up(HTC_HANDLE htc_handle)
  921. {
  922. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
  923. if (!target->hif_dev)
  924. return;
  925. hif_vote_link_up(target->hif_dev);
  926. }
  927. /**
  928. * htc_can_suspend_link - API to query HIF for link status
  929. * @htc_handle: HTC Handle
  930. *
  931. * API for upper layers to call HIF to query if the link can suspend
  932. *
  933. * Return: void
  934. */
  935. bool htc_can_suspend_link(HTC_HANDLE htc_handle)
  936. {
  937. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
  938. if (!target->hif_dev)
  939. return false;
  940. return hif_can_suspend_link(target->hif_dev);
  941. }
  942. #ifdef FEATURE_RUNTIME_PM
  943. int htc_pm_runtime_get(HTC_HANDLE htc_handle)
  944. {
  945. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
  946. return hif_pm_runtime_get(target->hif_dev);
  947. }
  948. int htc_pm_runtime_put(HTC_HANDLE htc_handle)
  949. {
  950. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
  951. return hif_pm_runtime_put(target->hif_dev);
  952. }
  953. #endif
  954. /**
  955. * htc_set_wmi_endpoint_count: Set number of WMI endpoint
  956. * @htc_handle: HTC handle
  957. * @wmi_ep_count: WMI enpoint count
  958. *
  959. * return: None
  960. */
  961. void htc_set_wmi_endpoint_count(HTC_HANDLE htc_handle, uint8_t wmi_ep_count)
  962. {
  963. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
  964. target->wmi_ep_count = wmi_ep_count;
  965. }
  966. /**
  967. * htc_get_wmi_endpoint_count: Get number of WMI endpoint
  968. * @htc_handle: HTC handle
  969. *
  970. * return: WMI enpoint count
  971. */
  972. uint8_t htc_get_wmi_endpoint_count(HTC_HANDLE htc_handle)
  973. {
  974. HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
  975. return target->wmi_ep_count;
  976. }