htc.c 30 KB

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