htc.c 34 KB

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