hif_main.c 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745
  1. /*
  2. * Copyright (c) 2015-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 "targcfg.h"
  19. #include "qdf_lock.h"
  20. #include "qdf_status.h"
  21. #include "qdf_status.h"
  22. #include <qdf_atomic.h> /* qdf_atomic_read */
  23. #include <targaddrs.h>
  24. #include "hif_io32.h"
  25. #include <hif.h>
  26. #include <target_type.h>
  27. #include "regtable.h"
  28. #define ATH_MODULE_NAME hif
  29. #include <a_debug.h>
  30. #include "hif_main.h"
  31. #include "hif_hw_version.h"
  32. #if (defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \
  33. defined(HIF_IPCI))
  34. #include "ce_tasklet.h"
  35. #include "ce_api.h"
  36. #endif
  37. #include "qdf_trace.h"
  38. #include "qdf_status.h"
  39. #include "hif_debug.h"
  40. #include "mp_dev.h"
  41. #if defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) || \
  42. defined(QCA_WIFI_QCA5018)
  43. #include "hal_api.h"
  44. #endif
  45. #include "hif_napi.h"
  46. #include "hif_unit_test_suspend_i.h"
  47. #include "qdf_module.h"
  48. #ifdef HIF_CE_LOG_INFO
  49. #include <qdf_notifier.h>
  50. #include <qdf_hang_event_notifier.h>
  51. #endif
  52. void hif_dump(struct hif_opaque_softc *hif_ctx, uint8_t cmd_id, bool start)
  53. {
  54. hif_trigger_dump(hif_ctx, cmd_id, start);
  55. }
  56. /**
  57. * hif_get_target_id(): hif_get_target_id
  58. *
  59. * Return the virtual memory base address to the caller
  60. *
  61. * @scn: hif_softc
  62. *
  63. * Return: A_target_id_t
  64. */
  65. A_target_id_t hif_get_target_id(struct hif_softc *scn)
  66. {
  67. return scn->mem;
  68. }
  69. /**
  70. * hif_get_targetdef(): hif_get_targetdef
  71. * @scn: scn
  72. *
  73. * Return: void *
  74. */
  75. void *hif_get_targetdef(struct hif_opaque_softc *hif_ctx)
  76. {
  77. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  78. return scn->targetdef;
  79. }
  80. #ifdef FORCE_WAKE
  81. void hif_srng_init_phase(struct hif_opaque_softc *hif_ctx,
  82. bool init_phase)
  83. {
  84. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  85. if (ce_srng_based(scn))
  86. hal_set_init_phase(scn->hal_soc, init_phase);
  87. }
  88. #endif /* FORCE_WAKE */
  89. #ifdef HIF_IPCI
  90. void hif_shutdown_notifier_cb(void *hif_ctx)
  91. {
  92. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  93. scn->recovery = true;
  94. }
  95. #endif
  96. /**
  97. * hif_vote_link_down(): unvote for link up
  98. *
  99. * Call hif_vote_link_down to release a previous request made using
  100. * hif_vote_link_up. A hif_vote_link_down call should only be made
  101. * after a corresponding hif_vote_link_up, otherwise you could be
  102. * negating a vote from another source. When no votes are present
  103. * hif will not guarantee the linkstate after hif_bus_suspend.
  104. *
  105. * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread
  106. * and initialization deinitialization sequencences.
  107. *
  108. * Return: n/a
  109. */
  110. void hif_vote_link_down(struct hif_opaque_softc *hif_ctx)
  111. {
  112. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  113. QDF_BUG(scn);
  114. scn->linkstate_vote--;
  115. hif_info("Down_linkstate_vote %d", scn->linkstate_vote);
  116. if (scn->linkstate_vote == 0)
  117. hif_bus_prevent_linkdown(scn, false);
  118. }
  119. /**
  120. * hif_vote_link_up(): vote to prevent bus from suspending
  121. *
  122. * Makes hif guarantee that fw can message the host normally
  123. * durring suspend.
  124. *
  125. * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread
  126. * and initialization deinitialization sequencences.
  127. *
  128. * Return: n/a
  129. */
  130. void hif_vote_link_up(struct hif_opaque_softc *hif_ctx)
  131. {
  132. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  133. QDF_BUG(scn);
  134. scn->linkstate_vote++;
  135. hif_info("Up_linkstate_vote %d", scn->linkstate_vote);
  136. if (scn->linkstate_vote == 1)
  137. hif_bus_prevent_linkdown(scn, true);
  138. }
  139. /**
  140. * hif_can_suspend_link(): query if hif is permitted to suspend the link
  141. *
  142. * Hif will ensure that the link won't be suspended if the upperlayers
  143. * don't want it to.
  144. *
  145. * SYNCHRONIZATION: MC thread is stopped before bus suspend thus
  146. * we don't need extra locking to ensure votes dont change while
  147. * we are in the process of suspending or resuming.
  148. *
  149. * Return: false if hif will guarantee link up durring suspend.
  150. */
  151. bool hif_can_suspend_link(struct hif_opaque_softc *hif_ctx)
  152. {
  153. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  154. QDF_BUG(scn);
  155. return scn->linkstate_vote == 0;
  156. }
  157. /**
  158. * hif_hia_item_address(): hif_hia_item_address
  159. * @target_type: target_type
  160. * @item_offset: item_offset
  161. *
  162. * Return: n/a
  163. */
  164. uint32_t hif_hia_item_address(uint32_t target_type, uint32_t item_offset)
  165. {
  166. switch (target_type) {
  167. case TARGET_TYPE_AR6002:
  168. return AR6002_HOST_INTEREST_ADDRESS + item_offset;
  169. case TARGET_TYPE_AR6003:
  170. return AR6003_HOST_INTEREST_ADDRESS + item_offset;
  171. case TARGET_TYPE_AR6004:
  172. return AR6004_HOST_INTEREST_ADDRESS + item_offset;
  173. case TARGET_TYPE_AR6006:
  174. return AR6006_HOST_INTEREST_ADDRESS + item_offset;
  175. case TARGET_TYPE_AR9888:
  176. return AR9888_HOST_INTEREST_ADDRESS + item_offset;
  177. case TARGET_TYPE_AR6320:
  178. case TARGET_TYPE_AR6320V2:
  179. return AR6320_HOST_INTEREST_ADDRESS + item_offset;
  180. case TARGET_TYPE_ADRASTEA:
  181. /* ADRASTEA doesn't have a host interest address */
  182. ASSERT(0);
  183. return 0;
  184. case TARGET_TYPE_AR900B:
  185. return AR900B_HOST_INTEREST_ADDRESS + item_offset;
  186. case TARGET_TYPE_QCA9984:
  187. return QCA9984_HOST_INTEREST_ADDRESS + item_offset;
  188. case TARGET_TYPE_QCA9888:
  189. return QCA9888_HOST_INTEREST_ADDRESS + item_offset;
  190. case TARGET_TYPE_IPQ4019:
  191. return IPQ4019_HOST_INTEREST_ADDRESS + item_offset;
  192. default:
  193. ASSERT(0);
  194. return 0;
  195. }
  196. }
  197. /**
  198. * hif_max_num_receives_reached() - check max receive is reached
  199. * @scn: HIF Context
  200. * @count: unsigned int.
  201. *
  202. * Output check status as bool
  203. *
  204. * Return: bool
  205. */
  206. bool hif_max_num_receives_reached(struct hif_softc *scn, unsigned int count)
  207. {
  208. if (QDF_IS_EPPING_ENABLED(hif_get_conparam(scn)))
  209. return count > 120;
  210. else
  211. return count > MAX_NUM_OF_RECEIVES;
  212. }
  213. /**
  214. * init_buffer_count() - initial buffer count
  215. * @maxSize: qdf_size_t
  216. *
  217. * routine to modify the initial buffer count to be allocated on an os
  218. * platform basis. Platform owner will need to modify this as needed
  219. *
  220. * Return: qdf_size_t
  221. */
  222. qdf_size_t init_buffer_count(qdf_size_t maxSize)
  223. {
  224. return maxSize;
  225. }
  226. /**
  227. * hif_save_htc_htt_config_endpoint() - save htt_tx_endpoint
  228. * @hif_ctx: hif context
  229. * @htc_htt_tx_endpoint: htt_tx_endpoint
  230. *
  231. * Return: void
  232. */
  233. void hif_save_htc_htt_config_endpoint(struct hif_opaque_softc *hif_ctx,
  234. int htc_htt_tx_endpoint)
  235. {
  236. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  237. if (!scn) {
  238. hif_err("scn or scn->hif_sc is NULL!");
  239. return;
  240. }
  241. scn->htc_htt_tx_endpoint = htc_htt_tx_endpoint;
  242. }
  243. qdf_export_symbol(hif_save_htc_htt_config_endpoint);
  244. static const struct qwlan_hw qwlan_hw_list[] = {
  245. {
  246. .id = AR6320_REV1_VERSION,
  247. .subid = 0,
  248. .name = "QCA6174_REV1",
  249. },
  250. {
  251. .id = AR6320_REV1_1_VERSION,
  252. .subid = 0x1,
  253. .name = "QCA6174_REV1_1",
  254. },
  255. {
  256. .id = AR6320_REV1_3_VERSION,
  257. .subid = 0x2,
  258. .name = "QCA6174_REV1_3",
  259. },
  260. {
  261. .id = AR6320_REV2_1_VERSION,
  262. .subid = 0x4,
  263. .name = "QCA6174_REV2_1",
  264. },
  265. {
  266. .id = AR6320_REV2_1_VERSION,
  267. .subid = 0x5,
  268. .name = "QCA6174_REV2_2",
  269. },
  270. {
  271. .id = AR6320_REV3_VERSION,
  272. .subid = 0x6,
  273. .name = "QCA6174_REV2.3",
  274. },
  275. {
  276. .id = AR6320_REV3_VERSION,
  277. .subid = 0x8,
  278. .name = "QCA6174_REV3",
  279. },
  280. {
  281. .id = AR6320_REV3_VERSION,
  282. .subid = 0x9,
  283. .name = "QCA6174_REV3_1",
  284. },
  285. {
  286. .id = AR6320_REV3_2_VERSION,
  287. .subid = 0xA,
  288. .name = "AR6320_REV3_2_VERSION",
  289. },
  290. {
  291. .id = QCA6390_V1,
  292. .subid = 0x0,
  293. .name = "QCA6390_V1",
  294. },
  295. {
  296. .id = QCA6490_V1,
  297. .subid = 0x0,
  298. .name = "QCA6490_V1",
  299. },
  300. {
  301. .id = WCN3990_v1,
  302. .subid = 0x0,
  303. .name = "WCN3990_V1",
  304. },
  305. {
  306. .id = WCN3990_v2,
  307. .subid = 0x0,
  308. .name = "WCN3990_V2",
  309. },
  310. {
  311. .id = WCN3990_v2_1,
  312. .subid = 0x0,
  313. .name = "WCN3990_V2.1",
  314. },
  315. {
  316. .id = WCN3998,
  317. .subid = 0x0,
  318. .name = "WCN3998",
  319. },
  320. {
  321. .id = QCA9379_REV1_VERSION,
  322. .subid = 0xC,
  323. .name = "QCA9379_REV1",
  324. },
  325. {
  326. .id = QCA9379_REV1_VERSION,
  327. .subid = 0xD,
  328. .name = "QCA9379_REV1_1",
  329. }
  330. };
  331. /**
  332. * hif_get_hw_name(): get a human readable name for the hardware
  333. * @info: Target Info
  334. *
  335. * Return: human readable name for the underlying wifi hardware.
  336. */
  337. static const char *hif_get_hw_name(struct hif_target_info *info)
  338. {
  339. int i;
  340. if (info->hw_name)
  341. return info->hw_name;
  342. for (i = 0; i < ARRAY_SIZE(qwlan_hw_list); i++) {
  343. if (info->target_version == qwlan_hw_list[i].id &&
  344. info->target_revision == qwlan_hw_list[i].subid) {
  345. return qwlan_hw_list[i].name;
  346. }
  347. }
  348. info->hw_name = qdf_mem_malloc(64);
  349. if (!info->hw_name)
  350. return "Unknown Device (nomem)";
  351. i = qdf_snprint(info->hw_name, 64, "HW_VERSION=%x.",
  352. info->target_version);
  353. if (i < 0)
  354. return "Unknown Device (snprintf failure)";
  355. else
  356. return info->hw_name;
  357. }
  358. /**
  359. * hif_get_hw_info(): hif_get_hw_info
  360. * @scn: scn
  361. * @version: version
  362. * @revision: revision
  363. *
  364. * Return: n/a
  365. */
  366. void hif_get_hw_info(struct hif_opaque_softc *scn, u32 *version, u32 *revision,
  367. const char **target_name)
  368. {
  369. struct hif_target_info *info = hif_get_target_info_handle(scn);
  370. struct hif_softc *sc = HIF_GET_SOFTC(scn);
  371. if (sc->bus_type == QDF_BUS_TYPE_USB)
  372. hif_usb_get_hw_info(sc);
  373. *version = info->target_version;
  374. *revision = info->target_revision;
  375. *target_name = hif_get_hw_name(info);
  376. }
  377. /**
  378. * hif_get_dev_ba(): API to get device base address.
  379. * @scn: scn
  380. * @version: version
  381. * @revision: revision
  382. *
  383. * Return: n/a
  384. */
  385. void *hif_get_dev_ba(struct hif_opaque_softc *hif_handle)
  386. {
  387. struct hif_softc *scn = (struct hif_softc *)hif_handle;
  388. return scn->mem;
  389. }
  390. qdf_export_symbol(hif_get_dev_ba);
  391. /**
  392. * hif_get_dev_ba_ce(): API to get device ce base address.
  393. * @scn: scn
  394. *
  395. * Return: dev mem base address for CE
  396. */
  397. void *hif_get_dev_ba_ce(struct hif_opaque_softc *hif_handle)
  398. {
  399. struct hif_softc *scn = (struct hif_softc *)hif_handle;
  400. return scn->mem_ce;
  401. }
  402. qdf_export_symbol(hif_get_dev_ba_ce);
  403. #ifdef WLAN_CE_INTERRUPT_THRESHOLD_CONFIG
  404. /**
  405. * hif_get_cfg_from_psoc() - Retrieve ini cfg from psoc
  406. * @scn: hif context
  407. * @psoc: psoc objmgr handle
  408. *
  409. * Return: None
  410. */
  411. static inline
  412. void hif_get_cfg_from_psoc(struct hif_softc *scn,
  413. struct wlan_objmgr_psoc *psoc)
  414. {
  415. if (psoc) {
  416. scn->ini_cfg.ce_status_ring_timer_threshold =
  417. cfg_get(psoc,
  418. CFG_CE_STATUS_RING_TIMER_THRESHOLD);
  419. scn->ini_cfg.ce_status_ring_batch_count_threshold =
  420. cfg_get(psoc,
  421. CFG_CE_STATUS_RING_BATCH_COUNT_THRESHOLD);
  422. }
  423. }
  424. #else
  425. static inline
  426. void hif_get_cfg_from_psoc(struct hif_softc *scn,
  427. struct wlan_objmgr_psoc *psoc)
  428. {
  429. }
  430. #endif /* WLAN_CE_INTERRUPT_THRESHOLD_CONFIG */
  431. #ifdef HIF_CE_LOG_INFO
  432. /**
  433. * hif_recovery_notifier_cb - Recovery notifier callback to log
  434. * hang event data
  435. * @block: notifier block
  436. * @state: state
  437. * @data: notifier data
  438. *
  439. * Return: status
  440. */
  441. static
  442. int hif_recovery_notifier_cb(struct notifier_block *block, unsigned long state,
  443. void *data)
  444. {
  445. struct qdf_notifer_data *notif_data = data;
  446. qdf_notif_block *notif_block;
  447. struct hif_softc *hif_handle;
  448. if (!data || !block)
  449. return -EINVAL;
  450. notif_block = qdf_container_of(block, qdf_notif_block, notif_block);
  451. hif_handle = notif_block->priv_data;
  452. if (!hif_handle)
  453. return -EINVAL;
  454. hif_log_ce_info(hif_handle, notif_data->hang_data,
  455. &notif_data->offset);
  456. return 0;
  457. }
  458. /**
  459. * hif_register_recovery_notifier - Register hif recovery notifier
  460. * @hif_handle: hif handle
  461. *
  462. * Return: status
  463. */
  464. static
  465. QDF_STATUS hif_register_recovery_notifier(struct hif_softc *hif_handle)
  466. {
  467. qdf_notif_block *hif_notifier;
  468. if (!hif_handle)
  469. return QDF_STATUS_E_FAILURE;
  470. hif_notifier = &hif_handle->hif_recovery_notifier;
  471. hif_notifier->notif_block.notifier_call = hif_recovery_notifier_cb;
  472. hif_notifier->priv_data = hif_handle;
  473. return qdf_hang_event_register_notifier(hif_notifier);
  474. }
  475. /**
  476. * hif_unregister_recovery_notifier - Un-register hif recovery notifier
  477. * @hif_handle: hif handle
  478. *
  479. * Return: status
  480. */
  481. static
  482. QDF_STATUS hif_unregister_recovery_notifier(struct hif_softc *hif_handle)
  483. {
  484. qdf_notif_block *hif_notifier = &hif_handle->hif_recovery_notifier;
  485. return qdf_hang_event_unregister_notifier(hif_notifier);
  486. }
  487. #else
  488. static inline
  489. QDF_STATUS hif_register_recovery_notifier(struct hif_softc *hif_handle)
  490. {
  491. return QDF_STATUS_SUCCESS;
  492. }
  493. static inline
  494. QDF_STATUS hif_unregister_recovery_notifier(struct hif_softc *hif_handle)
  495. {
  496. return QDF_STATUS_SUCCESS;
  497. }
  498. #endif
  499. #ifdef HIF_CPU_PERF_AFFINE_MASK
  500. /**
  501. * __hif_cpu_hotplug_notify() - CPU hotplug event handler
  502. * @cpu: CPU Id of the CPU generating the event
  503. * @cpu_up: true if the CPU is online
  504. *
  505. * Return: None
  506. */
  507. static void __hif_cpu_hotplug_notify(void *context,
  508. uint32_t cpu, bool cpu_up)
  509. {
  510. struct hif_softc *scn = context;
  511. if (!scn)
  512. return;
  513. if (hif_is_driver_unloading(scn) || hif_is_recovery_in_progress(scn))
  514. return;
  515. if (cpu_up) {
  516. hif_config_irq_set_perf_affinity_hint(GET_HIF_OPAQUE_HDL(scn));
  517. hif_debug("Setting affinity for online CPU: %d", cpu);
  518. } else {
  519. hif_debug("Skip setting affinity for offline CPU: %d", cpu);
  520. }
  521. }
  522. /**
  523. * hif_cpu_hotplug_notify - cpu core up/down notification
  524. * handler
  525. * @cpu: CPU generating the event
  526. * @cpu_up: true if the CPU is online
  527. *
  528. * Return: None
  529. */
  530. static void hif_cpu_hotplug_notify(void *context, uint32_t cpu, bool cpu_up)
  531. {
  532. struct qdf_op_sync *op_sync;
  533. if (qdf_op_protect(&op_sync))
  534. return;
  535. __hif_cpu_hotplug_notify(context, cpu, cpu_up);
  536. qdf_op_unprotect(op_sync);
  537. }
  538. static void hif_cpu_online_cb(void *context, uint32_t cpu)
  539. {
  540. hif_cpu_hotplug_notify(context, cpu, true);
  541. }
  542. static void hif_cpu_before_offline_cb(void *context, uint32_t cpu)
  543. {
  544. hif_cpu_hotplug_notify(context, cpu, false);
  545. }
  546. static void hif_cpuhp_register(struct hif_softc *scn)
  547. {
  548. if (!scn) {
  549. hif_info_high("cannot register hotplug notifiers");
  550. return;
  551. }
  552. qdf_cpuhp_register(&scn->cpuhp_event_handle,
  553. scn,
  554. hif_cpu_online_cb,
  555. hif_cpu_before_offline_cb);
  556. }
  557. static void hif_cpuhp_unregister(struct hif_softc *scn)
  558. {
  559. if (!scn) {
  560. hif_info_high("cannot unregister hotplug notifiers");
  561. return;
  562. }
  563. qdf_cpuhp_unregister(&scn->cpuhp_event_handle);
  564. }
  565. #else
  566. static void hif_cpuhp_register(struct hif_softc *scn)
  567. {
  568. }
  569. static void hif_cpuhp_unregister(struct hif_softc *scn)
  570. {
  571. }
  572. #endif /* ifdef HIF_CPU_PERF_AFFINE_MASK */
  573. struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx,
  574. uint32_t mode,
  575. enum qdf_bus_type bus_type,
  576. struct hif_driver_state_callbacks *cbk,
  577. struct wlan_objmgr_psoc *psoc)
  578. {
  579. struct hif_softc *scn;
  580. QDF_STATUS status = QDF_STATUS_SUCCESS;
  581. int bus_context_size = hif_bus_get_context_size(bus_type);
  582. if (bus_context_size == 0) {
  583. hif_err("context size 0 not allowed");
  584. return NULL;
  585. }
  586. scn = (struct hif_softc *)qdf_mem_malloc(bus_context_size);
  587. if (!scn)
  588. return GET_HIF_OPAQUE_HDL(scn);
  589. scn->qdf_dev = qdf_ctx;
  590. scn->hif_con_param = mode;
  591. qdf_atomic_init(&scn->active_tasklet_cnt);
  592. qdf_atomic_init(&scn->active_grp_tasklet_cnt);
  593. qdf_atomic_init(&scn->link_suspended);
  594. qdf_atomic_init(&scn->tasklet_from_intr);
  595. qdf_mem_copy(&scn->callbacks, cbk,
  596. sizeof(struct hif_driver_state_callbacks));
  597. scn->bus_type = bus_type;
  598. hif_get_cfg_from_psoc(scn, psoc);
  599. hif_set_event_hist_mask(GET_HIF_OPAQUE_HDL(scn));
  600. status = hif_bus_open(scn, bus_type);
  601. if (status != QDF_STATUS_SUCCESS) {
  602. hif_err("hif_bus_open error = %d, bus_type = %d",
  603. status, bus_type);
  604. qdf_mem_free(scn);
  605. scn = NULL;
  606. }
  607. hif_cpuhp_register(scn);
  608. return GET_HIF_OPAQUE_HDL(scn);
  609. }
  610. #ifdef ADRASTEA_RRI_ON_DDR
  611. /**
  612. * hif_uninit_rri_on_ddr(): free consistent memory allocated for rri
  613. * @scn: hif context
  614. *
  615. * Return: none
  616. */
  617. void hif_uninit_rri_on_ddr(struct hif_softc *scn)
  618. {
  619. if (scn->vaddr_rri_on_ddr)
  620. qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev,
  621. (CE_COUNT * sizeof(uint32_t)),
  622. scn->vaddr_rri_on_ddr,
  623. scn->paddr_rri_on_ddr, 0);
  624. scn->vaddr_rri_on_ddr = NULL;
  625. }
  626. #endif
  627. /**
  628. * hif_close(): hif_close
  629. * @hif_ctx: hif_ctx
  630. *
  631. * Return: n/a
  632. */
  633. void hif_close(struct hif_opaque_softc *hif_ctx)
  634. {
  635. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  636. if (!scn) {
  637. hif_err("hif_opaque_softc is NULL");
  638. return;
  639. }
  640. if (scn->athdiag_procfs_inited) {
  641. athdiag_procfs_remove();
  642. scn->athdiag_procfs_inited = false;
  643. }
  644. if (scn->target_info.hw_name) {
  645. char *hw_name = scn->target_info.hw_name;
  646. scn->target_info.hw_name = "ErrUnloading";
  647. qdf_mem_free(hw_name);
  648. }
  649. hif_uninit_rri_on_ddr(scn);
  650. hif_cpuhp_unregister(scn);
  651. hif_bus_close(scn);
  652. qdf_mem_free(scn);
  653. }
  654. /**
  655. * hif_get_num_active_tasklets() - get the number of active
  656. * tasklets pending to be completed.
  657. * @scn: HIF context
  658. *
  659. * Returns: the number of tasklets which are active
  660. */
  661. static inline int hif_get_num_active_tasklets(struct hif_softc *scn)
  662. {
  663. return qdf_atomic_read(&scn->active_tasklet_cnt);
  664. }
  665. /**
  666. * hif_get_num_active_grp_tasklets() - get the number of active
  667. * datapath group tasklets pending to be completed.
  668. * @scn: HIF context
  669. *
  670. * Returns: the number of datapath group tasklets which are active
  671. */
  672. static inline int hif_get_num_active_grp_tasklets(struct hif_softc *scn)
  673. {
  674. return qdf_atomic_read(&scn->active_grp_tasklet_cnt);
  675. }
  676. #if (defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) || \
  677. defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) || \
  678. defined(QCA_WIFI_QCN9000) || defined(QCA_WIFI_QCA6490) || \
  679. defined(QCA_WIFI_QCA6750) || defined(QCA_WIFI_QCA5018))
  680. /**
  681. * hif_get_num_pending_work() - get the number of entries in
  682. * the workqueue pending to be completed.
  683. * @scn: HIF context
  684. *
  685. * Returns: the number of tasklets which are active
  686. */
  687. static inline int hif_get_num_pending_work(struct hif_softc *scn)
  688. {
  689. return hal_get_reg_write_pending_work(scn->hal_soc);
  690. }
  691. #else
  692. static inline int hif_get_num_pending_work(struct hif_softc *scn)
  693. {
  694. return 0;
  695. }
  696. #endif
  697. QDF_STATUS hif_try_complete_tasks(struct hif_softc *scn)
  698. {
  699. uint32_t task_drain_wait_cnt = 0;
  700. int tasklet = 0, grp_tasklet = 0, work = 0;
  701. while ((tasklet = hif_get_num_active_tasklets(scn)) ||
  702. (grp_tasklet = hif_get_num_active_grp_tasklets(scn)) ||
  703. (work = hif_get_num_pending_work(scn))) {
  704. if (++task_drain_wait_cnt > HIF_TASK_DRAIN_WAIT_CNT) {
  705. hif_err("pending tasklets %d grp tasklets %d work %d",
  706. tasklet, grp_tasklet, work);
  707. return QDF_STATUS_E_FAULT;
  708. }
  709. hif_info("waiting for tasklets %d grp tasklets %d work %d",
  710. tasklet, grp_tasklet, work);
  711. msleep(10);
  712. }
  713. return QDF_STATUS_SUCCESS;
  714. }
  715. #if (defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) || \
  716. defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) || \
  717. defined(QCA_WIFI_QCN9000) || defined(QCA_WIFI_QCA6490) || \
  718. defined(QCA_WIFI_QCA6750) || defined(QCA_WIFI_QCA5018))
  719. static QDF_STATUS hif_hal_attach(struct hif_softc *scn)
  720. {
  721. if (ce_srng_based(scn)) {
  722. scn->hal_soc = hal_attach(
  723. hif_softc_to_hif_opaque_softc(scn),
  724. scn->qdf_dev);
  725. if (!scn->hal_soc)
  726. return QDF_STATUS_E_FAILURE;
  727. }
  728. return QDF_STATUS_SUCCESS;
  729. }
  730. static QDF_STATUS hif_hal_detach(struct hif_softc *scn)
  731. {
  732. if (ce_srng_based(scn)) {
  733. hal_detach(scn->hal_soc);
  734. scn->hal_soc = NULL;
  735. }
  736. return QDF_STATUS_SUCCESS;
  737. }
  738. #else
  739. static QDF_STATUS hif_hal_attach(struct hif_softc *scn)
  740. {
  741. return QDF_STATUS_SUCCESS;
  742. }
  743. static QDF_STATUS hif_hal_detach(struct hif_softc *scn)
  744. {
  745. return QDF_STATUS_SUCCESS;
  746. }
  747. #endif
  748. /**
  749. * hif_enable(): hif_enable
  750. * @hif_ctx: hif_ctx
  751. * @dev: dev
  752. * @bdev: bus dev
  753. * @bid: bus ID
  754. * @bus_type: bus type
  755. * @type: enable type
  756. *
  757. * Return: QDF_STATUS
  758. */
  759. QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev,
  760. void *bdev,
  761. const struct hif_bus_id *bid,
  762. enum qdf_bus_type bus_type,
  763. enum hif_enable_type type)
  764. {
  765. QDF_STATUS status;
  766. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  767. if (!scn) {
  768. hif_err("hif_ctx = NULL");
  769. return QDF_STATUS_E_NULL_VALUE;
  770. }
  771. status = hif_enable_bus(scn, dev, bdev, bid, type);
  772. if (status != QDF_STATUS_SUCCESS) {
  773. hif_err("hif_enable_bus error = %d", status);
  774. return status;
  775. }
  776. status = hif_hal_attach(scn);
  777. if (status != QDF_STATUS_SUCCESS) {
  778. hif_err("hal attach failed");
  779. goto disable_bus;
  780. }
  781. if (hif_bus_configure(scn)) {
  782. hif_err("Target probe failed");
  783. status = QDF_STATUS_E_FAILURE;
  784. goto hal_detach;
  785. }
  786. hif_ut_suspend_init(scn);
  787. hif_register_recovery_notifier(scn);
  788. /*
  789. * Flag to avoid potential unallocated memory access from MSI
  790. * interrupt handler which could get scheduled as soon as MSI
  791. * is enabled, i.e to take care of the race due to the order
  792. * in where MSI is enabled before the memory, that will be
  793. * in interrupt handlers, is allocated.
  794. */
  795. scn->hif_init_done = true;
  796. hif_debug("OK");
  797. return QDF_STATUS_SUCCESS;
  798. hal_detach:
  799. hif_hal_detach(scn);
  800. disable_bus:
  801. hif_disable_bus(scn);
  802. return status;
  803. }
  804. void hif_disable(struct hif_opaque_softc *hif_ctx, enum hif_disable_type type)
  805. {
  806. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  807. if (!scn)
  808. return;
  809. hif_unregister_recovery_notifier(scn);
  810. hif_nointrs(scn);
  811. if (scn->hif_init_done == false)
  812. hif_shutdown_device(hif_ctx);
  813. else
  814. hif_stop(hif_ctx);
  815. hif_hal_detach(scn);
  816. hif_disable_bus(scn);
  817. hif_wlan_disable(scn);
  818. scn->notice_send = false;
  819. hif_debug("X");
  820. }
  821. #ifdef CE_TASKLET_DEBUG_ENABLE
  822. void hif_enable_ce_latency_stats(struct hif_opaque_softc *hif_ctx, uint8_t val)
  823. {
  824. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  825. if (!scn)
  826. return;
  827. scn->ce_latency_stats = val;
  828. }
  829. #endif
  830. void hif_display_stats(struct hif_opaque_softc *hif_ctx)
  831. {
  832. hif_display_bus_stats(hif_ctx);
  833. }
  834. qdf_export_symbol(hif_display_stats);
  835. void hif_clear_stats(struct hif_opaque_softc *hif_ctx)
  836. {
  837. hif_clear_bus_stats(hif_ctx);
  838. }
  839. /**
  840. * hif_crash_shutdown_dump_bus_register() - dump bus registers
  841. * @hif_ctx: hif_ctx
  842. *
  843. * Return: n/a
  844. */
  845. #if defined(TARGET_RAMDUMP_AFTER_KERNEL_PANIC) && defined(WLAN_FEATURE_BMI)
  846. static void hif_crash_shutdown_dump_bus_register(void *hif_ctx)
  847. {
  848. struct hif_opaque_softc *scn = hif_ctx;
  849. if (hif_check_soc_status(scn))
  850. return;
  851. if (hif_dump_registers(scn))
  852. hif_err("Failed to dump bus registers!");
  853. }
  854. /**
  855. * hif_crash_shutdown(): hif_crash_shutdown
  856. *
  857. * This function is called by the platform driver to dump CE registers
  858. *
  859. * @hif_ctx: hif_ctx
  860. *
  861. * Return: n/a
  862. */
  863. void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx)
  864. {
  865. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  866. if (!hif_ctx)
  867. return;
  868. if (scn->bus_type == QDF_BUS_TYPE_SNOC) {
  869. hif_warn("RAM dump disabled for bustype %d", scn->bus_type);
  870. return;
  871. }
  872. if (TARGET_STATUS_RESET == scn->target_status) {
  873. hif_warn("Target is already asserted, ignore!");
  874. return;
  875. }
  876. if (hif_is_load_or_unload_in_progress(scn)) {
  877. hif_err("Load/unload is in progress, ignore!");
  878. return;
  879. }
  880. hif_crash_shutdown_dump_bus_register(hif_ctx);
  881. hif_set_target_status(hif_ctx, TARGET_STATUS_RESET);
  882. if (ol_copy_ramdump(hif_ctx))
  883. goto out;
  884. hif_info("RAM dump collecting completed!");
  885. out:
  886. return;
  887. }
  888. #else
  889. void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx)
  890. {
  891. hif_debug("Collecting target RAM dump disabled");
  892. }
  893. #endif /* TARGET_RAMDUMP_AFTER_KERNEL_PANIC */
  894. #ifdef QCA_WIFI_3_0
  895. /**
  896. * hif_check_fw_reg(): hif_check_fw_reg
  897. * @scn: scn
  898. * @state:
  899. *
  900. * Return: int
  901. */
  902. int hif_check_fw_reg(struct hif_opaque_softc *scn)
  903. {
  904. return 0;
  905. }
  906. #endif
  907. /**
  908. * hif_read_phy_mem_base(): hif_read_phy_mem_base
  909. * @scn: scn
  910. * @phy_mem_base: physical mem base
  911. *
  912. * Return: n/a
  913. */
  914. void hif_read_phy_mem_base(struct hif_softc *scn, qdf_dma_addr_t *phy_mem_base)
  915. {
  916. *phy_mem_base = scn->mem_pa;
  917. }
  918. qdf_export_symbol(hif_read_phy_mem_base);
  919. /**
  920. * hif_get_device_type(): hif_get_device_type
  921. * @device_id: device_id
  922. * @revision_id: revision_id
  923. * @hif_type: returned hif_type
  924. * @target_type: returned target_type
  925. *
  926. * Return: int
  927. */
  928. int hif_get_device_type(uint32_t device_id,
  929. uint32_t revision_id,
  930. uint32_t *hif_type, uint32_t *target_type)
  931. {
  932. int ret = 0;
  933. switch (device_id) {
  934. case ADRASTEA_DEVICE_ID_P2_E12:
  935. *hif_type = HIF_TYPE_ADRASTEA;
  936. *target_type = TARGET_TYPE_ADRASTEA;
  937. break;
  938. case AR9888_DEVICE_ID:
  939. *hif_type = HIF_TYPE_AR9888;
  940. *target_type = TARGET_TYPE_AR9888;
  941. break;
  942. case AR6320_DEVICE_ID:
  943. switch (revision_id) {
  944. case AR6320_FW_1_1:
  945. case AR6320_FW_1_3:
  946. *hif_type = HIF_TYPE_AR6320;
  947. *target_type = TARGET_TYPE_AR6320;
  948. break;
  949. case AR6320_FW_2_0:
  950. case AR6320_FW_3_0:
  951. case AR6320_FW_3_2:
  952. *hif_type = HIF_TYPE_AR6320V2;
  953. *target_type = TARGET_TYPE_AR6320V2;
  954. break;
  955. default:
  956. hif_err("dev_id = 0x%x, rev_id = 0x%x",
  957. device_id, revision_id);
  958. ret = -ENODEV;
  959. goto end;
  960. }
  961. break;
  962. case AR9887_DEVICE_ID:
  963. *hif_type = HIF_TYPE_AR9888;
  964. *target_type = TARGET_TYPE_AR9888;
  965. hif_info(" *********** AR9887 **************");
  966. break;
  967. case QCA9984_DEVICE_ID:
  968. *hif_type = HIF_TYPE_QCA9984;
  969. *target_type = TARGET_TYPE_QCA9984;
  970. hif_info(" *********** QCA9984 *************");
  971. break;
  972. case QCA9888_DEVICE_ID:
  973. *hif_type = HIF_TYPE_QCA9888;
  974. *target_type = TARGET_TYPE_QCA9888;
  975. hif_info(" *********** QCA9888 *************");
  976. break;
  977. case AR900B_DEVICE_ID:
  978. *hif_type = HIF_TYPE_AR900B;
  979. *target_type = TARGET_TYPE_AR900B;
  980. hif_info(" *********** AR900B *************");
  981. break;
  982. case IPQ4019_DEVICE_ID:
  983. *hif_type = HIF_TYPE_IPQ4019;
  984. *target_type = TARGET_TYPE_IPQ4019;
  985. hif_info(" *********** IPQ4019 *************");
  986. break;
  987. case QCA8074_DEVICE_ID:
  988. *hif_type = HIF_TYPE_QCA8074;
  989. *target_type = TARGET_TYPE_QCA8074;
  990. hif_info(" *********** QCA8074 *************");
  991. break;
  992. case QCA6290_EMULATION_DEVICE_ID:
  993. case QCA6290_DEVICE_ID:
  994. *hif_type = HIF_TYPE_QCA6290;
  995. *target_type = TARGET_TYPE_QCA6290;
  996. hif_info(" *********** QCA6290EMU *************");
  997. break;
  998. case QCN9000_DEVICE_ID:
  999. *hif_type = HIF_TYPE_QCN9000;
  1000. *target_type = TARGET_TYPE_QCN9000;
  1001. hif_info(" *********** QCN9000 *************");
  1002. break;
  1003. case QCN9100_DEVICE_ID:
  1004. *hif_type = HIF_TYPE_QCN9100;
  1005. *target_type = TARGET_TYPE_QCN9100;
  1006. hif_info(" *********** QCN9100 *************");
  1007. break;
  1008. case QCN7605_DEVICE_ID:
  1009. case QCN7605_COMPOSITE:
  1010. case QCN7605_STANDALONE:
  1011. case QCN7605_STANDALONE_V2:
  1012. case QCN7605_COMPOSITE_V2:
  1013. *hif_type = HIF_TYPE_QCN7605;
  1014. *target_type = TARGET_TYPE_QCN7605;
  1015. hif_info(" *********** QCN7605 *************");
  1016. break;
  1017. case QCA6390_DEVICE_ID:
  1018. case QCA6390_EMULATION_DEVICE_ID:
  1019. *hif_type = HIF_TYPE_QCA6390;
  1020. *target_type = TARGET_TYPE_QCA6390;
  1021. hif_info(" *********** QCA6390 *************");
  1022. break;
  1023. case QCA6490_DEVICE_ID:
  1024. case QCA6490_EMULATION_DEVICE_ID:
  1025. *hif_type = HIF_TYPE_QCA6490;
  1026. *target_type = TARGET_TYPE_QCA6490;
  1027. hif_info(" *********** QCA6490 *************");
  1028. break;
  1029. case QCA6750_DEVICE_ID:
  1030. case QCA6750_EMULATION_DEVICE_ID:
  1031. *hif_type = HIF_TYPE_QCA6750;
  1032. *target_type = TARGET_TYPE_QCA6750;
  1033. hif_info(" *********** QCA6750 *************");
  1034. break;
  1035. case QCA8074V2_DEVICE_ID:
  1036. *hif_type = HIF_TYPE_QCA8074V2;
  1037. *target_type = TARGET_TYPE_QCA8074V2;
  1038. hif_info(" *********** QCA8074V2 *************");
  1039. break;
  1040. case QCA6018_DEVICE_ID:
  1041. case RUMIM2M_DEVICE_ID_NODE0:
  1042. case RUMIM2M_DEVICE_ID_NODE1:
  1043. case RUMIM2M_DEVICE_ID_NODE2:
  1044. case RUMIM2M_DEVICE_ID_NODE3:
  1045. case RUMIM2M_DEVICE_ID_NODE4:
  1046. case RUMIM2M_DEVICE_ID_NODE5:
  1047. *hif_type = HIF_TYPE_QCA6018;
  1048. *target_type = TARGET_TYPE_QCA6018;
  1049. hif_info(" *********** QCA6018 *************");
  1050. break;
  1051. case QCA5018_DEVICE_ID:
  1052. *hif_type = HIF_TYPE_QCA5018;
  1053. *target_type = TARGET_TYPE_QCA5018;
  1054. hif_info(" *********** qca5018 *************");
  1055. break;
  1056. default:
  1057. hif_err("Unsupported device ID = 0x%x!", device_id);
  1058. ret = -ENODEV;
  1059. break;
  1060. }
  1061. if (*target_type == TARGET_TYPE_UNKNOWN) {
  1062. hif_err("Unsupported target_type!");
  1063. ret = -ENODEV;
  1064. }
  1065. end:
  1066. return ret;
  1067. }
  1068. /**
  1069. * hif_get_bus_type() - return the bus type
  1070. *
  1071. * Return: enum qdf_bus_type
  1072. */
  1073. enum qdf_bus_type hif_get_bus_type(struct hif_opaque_softc *hif_hdl)
  1074. {
  1075. struct hif_softc *scn = HIF_GET_SOFTC(hif_hdl);
  1076. return scn->bus_type;
  1077. }
  1078. /**
  1079. * Target info and ini parameters are global to the driver
  1080. * Hence these structures are exposed to all the modules in
  1081. * the driver and they don't need to maintains multiple copies
  1082. * of the same info, instead get the handle from hif and
  1083. * modify them in hif
  1084. */
  1085. /**
  1086. * hif_get_ini_handle() - API to get hif_config_param handle
  1087. * @hif_ctx: HIF Context
  1088. *
  1089. * Return: pointer to hif_config_info
  1090. */
  1091. struct hif_config_info *hif_get_ini_handle(struct hif_opaque_softc *hif_ctx)
  1092. {
  1093. struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx);
  1094. return &sc->hif_config;
  1095. }
  1096. /**
  1097. * hif_get_target_info_handle() - API to get hif_target_info handle
  1098. * @hif_ctx: HIF context
  1099. *
  1100. * Return: Pointer to hif_target_info
  1101. */
  1102. struct hif_target_info *hif_get_target_info_handle(
  1103. struct hif_opaque_softc *hif_ctx)
  1104. {
  1105. struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx);
  1106. return &sc->target_info;
  1107. }
  1108. qdf_export_symbol(hif_get_target_info_handle);
  1109. #ifdef RECEIVE_OFFLOAD
  1110. void hif_offld_flush_cb_register(struct hif_opaque_softc *scn,
  1111. void (offld_flush_handler)(void *))
  1112. {
  1113. if (hif_napi_enabled(scn, -1))
  1114. hif_napi_rx_offld_flush_cb_register(scn, offld_flush_handler);
  1115. else
  1116. hif_err("NAPI not enabled");
  1117. }
  1118. qdf_export_symbol(hif_offld_flush_cb_register);
  1119. void hif_offld_flush_cb_deregister(struct hif_opaque_softc *scn)
  1120. {
  1121. if (hif_napi_enabled(scn, -1))
  1122. hif_napi_rx_offld_flush_cb_deregister(scn);
  1123. else
  1124. hif_err("NAPI not enabled");
  1125. }
  1126. qdf_export_symbol(hif_offld_flush_cb_deregister);
  1127. int hif_get_rx_ctx_id(int ctx_id, struct hif_opaque_softc *hif_hdl)
  1128. {
  1129. if (hif_napi_enabled(hif_hdl, -1))
  1130. return NAPI_PIPE2ID(ctx_id);
  1131. else
  1132. return ctx_id;
  1133. }
  1134. #else /* RECEIVE_OFFLOAD */
  1135. int hif_get_rx_ctx_id(int ctx_id, struct hif_opaque_softc *hif_hdl)
  1136. {
  1137. return 0;
  1138. }
  1139. qdf_export_symbol(hif_get_rx_ctx_id);
  1140. #endif /* RECEIVE_OFFLOAD */
  1141. #if defined(FEATURE_LRO)
  1142. /**
  1143. * hif_get_lro_info - Returns LRO instance for instance ID
  1144. * @ctx_id: LRO instance ID
  1145. * @hif_hdl: HIF Context
  1146. *
  1147. * Return: Pointer to LRO instance.
  1148. */
  1149. void *hif_get_lro_info(int ctx_id, struct hif_opaque_softc *hif_hdl)
  1150. {
  1151. void *data;
  1152. if (hif_napi_enabled(hif_hdl, -1))
  1153. data = hif_napi_get_lro_info(hif_hdl, ctx_id);
  1154. else
  1155. data = hif_ce_get_lro_ctx(hif_hdl, ctx_id);
  1156. return data;
  1157. }
  1158. #endif
  1159. /**
  1160. * hif_get_target_status - API to get target status
  1161. * @hif_ctx: HIF Context
  1162. *
  1163. * Return: enum hif_target_status
  1164. */
  1165. enum hif_target_status hif_get_target_status(struct hif_opaque_softc *hif_ctx)
  1166. {
  1167. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  1168. return scn->target_status;
  1169. }
  1170. qdf_export_symbol(hif_get_target_status);
  1171. /**
  1172. * hif_set_target_status() - API to set target status
  1173. * @hif_ctx: HIF Context
  1174. * @status: Target Status
  1175. *
  1176. * Return: void
  1177. */
  1178. void hif_set_target_status(struct hif_opaque_softc *hif_ctx, enum
  1179. hif_target_status status)
  1180. {
  1181. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  1182. scn->target_status = status;
  1183. }
  1184. /**
  1185. * hif_init_ini_config() - API to initialize HIF configuration parameters
  1186. * @hif_ctx: HIF Context
  1187. * @cfg: HIF Configuration
  1188. *
  1189. * Return: void
  1190. */
  1191. void hif_init_ini_config(struct hif_opaque_softc *hif_ctx,
  1192. struct hif_config_info *cfg)
  1193. {
  1194. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  1195. qdf_mem_copy(&scn->hif_config, cfg, sizeof(struct hif_config_info));
  1196. }
  1197. /**
  1198. * hif_get_conparam() - API to get driver mode in HIF
  1199. * @scn: HIF Context
  1200. *
  1201. * Return: driver mode of operation
  1202. */
  1203. uint32_t hif_get_conparam(struct hif_softc *scn)
  1204. {
  1205. if (!scn)
  1206. return 0;
  1207. return scn->hif_con_param;
  1208. }
  1209. /**
  1210. * hif_get_callbacks_handle() - API to get callbacks Handle
  1211. * @scn: HIF Context
  1212. *
  1213. * Return: pointer to HIF Callbacks
  1214. */
  1215. struct hif_driver_state_callbacks *hif_get_callbacks_handle(
  1216. struct hif_softc *scn)
  1217. {
  1218. return &scn->callbacks;
  1219. }
  1220. /**
  1221. * hif_is_driver_unloading() - API to query upper layers if driver is unloading
  1222. * @scn: HIF Context
  1223. *
  1224. * Return: True/False
  1225. */
  1226. bool hif_is_driver_unloading(struct hif_softc *scn)
  1227. {
  1228. struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn);
  1229. if (cbk && cbk->is_driver_unloading)
  1230. return cbk->is_driver_unloading(cbk->context);
  1231. return false;
  1232. }
  1233. /**
  1234. * hif_is_load_or_unload_in_progress() - API to query upper layers if
  1235. * load/unload in progress
  1236. * @scn: HIF Context
  1237. *
  1238. * Return: True/False
  1239. */
  1240. bool hif_is_load_or_unload_in_progress(struct hif_softc *scn)
  1241. {
  1242. struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn);
  1243. if (cbk && cbk->is_load_unload_in_progress)
  1244. return cbk->is_load_unload_in_progress(cbk->context);
  1245. return false;
  1246. }
  1247. /**
  1248. * hif_is_recovery_in_progress() - API to query upper layers if recovery in
  1249. * progress
  1250. * @scn: HIF Context
  1251. *
  1252. * Return: True/False
  1253. */
  1254. bool hif_is_recovery_in_progress(struct hif_softc *scn)
  1255. {
  1256. struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn);
  1257. if (cbk && cbk->is_recovery_in_progress)
  1258. return cbk->is_recovery_in_progress(cbk->context);
  1259. return false;
  1260. }
  1261. #if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \
  1262. defined(HIF_IPCI)
  1263. /**
  1264. * hif_update_pipe_callback() - API to register pipe specific callbacks
  1265. * @osc: Opaque softc
  1266. * @pipeid: pipe id
  1267. * @callbacks: callbacks to register
  1268. *
  1269. * Return: void
  1270. */
  1271. void hif_update_pipe_callback(struct hif_opaque_softc *osc,
  1272. u_int8_t pipeid,
  1273. struct hif_msg_callbacks *callbacks)
  1274. {
  1275. struct hif_softc *scn = HIF_GET_SOFTC(osc);
  1276. struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
  1277. struct HIF_CE_pipe_info *pipe_info;
  1278. QDF_BUG(pipeid < CE_COUNT_MAX);
  1279. hif_debug("pipeid: %d", pipeid);
  1280. pipe_info = &hif_state->pipe_info[pipeid];
  1281. qdf_mem_copy(&pipe_info->pipe_callbacks,
  1282. callbacks, sizeof(pipe_info->pipe_callbacks));
  1283. }
  1284. qdf_export_symbol(hif_update_pipe_callback);
  1285. /**
  1286. * hif_is_target_ready() - API to query if target is in ready state
  1287. * progress
  1288. * @scn: HIF Context
  1289. *
  1290. * Return: True/False
  1291. */
  1292. bool hif_is_target_ready(struct hif_softc *scn)
  1293. {
  1294. struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn);
  1295. if (cbk && cbk->is_target_ready)
  1296. return cbk->is_target_ready(cbk->context);
  1297. /*
  1298. * if callback is not registered then there is no way to determine
  1299. * if target is ready. In-such case return true to indicate that
  1300. * target is ready.
  1301. */
  1302. return true;
  1303. }
  1304. qdf_export_symbol(hif_is_target_ready);
  1305. int hif_get_bandwidth_level(struct hif_opaque_softc *hif_handle)
  1306. {
  1307. struct hif_softc *scn = HIF_GET_SOFTC(hif_handle);
  1308. struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn);
  1309. if (cbk && cbk->get_bandwidth_level)
  1310. return cbk->get_bandwidth_level(cbk->context);
  1311. return 0;
  1312. }
  1313. qdf_export_symbol(hif_get_bandwidth_level);
  1314. #ifdef DP_MEM_PRE_ALLOC
  1315. void *hif_mem_alloc_consistent_unaligned(struct hif_softc *scn,
  1316. qdf_size_t size,
  1317. qdf_dma_addr_t *paddr,
  1318. uint32_t ring_type,
  1319. uint8_t *is_mem_prealloc)
  1320. {
  1321. void *vaddr = NULL;
  1322. struct hif_driver_state_callbacks *cbk =
  1323. hif_get_callbacks_handle(scn);
  1324. *is_mem_prealloc = false;
  1325. if (cbk && cbk->prealloc_get_consistent_mem_unaligned) {
  1326. vaddr = cbk->prealloc_get_consistent_mem_unaligned(size,
  1327. paddr,
  1328. ring_type);
  1329. if (vaddr) {
  1330. *is_mem_prealloc = true;
  1331. goto end;
  1332. }
  1333. }
  1334. vaddr = qdf_mem_alloc_consistent(scn->qdf_dev,
  1335. scn->qdf_dev->dev,
  1336. size,
  1337. paddr);
  1338. end:
  1339. dp_info("%s va_unaligned %pK pa_unaligned %pK size %d ring_type %d",
  1340. *is_mem_prealloc ? "pre-alloc" : "dynamic-alloc", vaddr,
  1341. (void *)*paddr, (int)size, ring_type);
  1342. return vaddr;
  1343. }
  1344. void hif_mem_free_consistent_unaligned(struct hif_softc *scn,
  1345. qdf_size_t size,
  1346. void *vaddr,
  1347. qdf_dma_addr_t paddr,
  1348. qdf_dma_context_t memctx,
  1349. uint8_t is_mem_prealloc)
  1350. {
  1351. struct hif_driver_state_callbacks *cbk =
  1352. hif_get_callbacks_handle(scn);
  1353. if (is_mem_prealloc) {
  1354. if (cbk && cbk->prealloc_put_consistent_mem_unaligned) {
  1355. cbk->prealloc_put_consistent_mem_unaligned(vaddr);
  1356. } else {
  1357. dp_warn("dp_prealloc_put_consistent_unligned NULL");
  1358. QDF_BUG(0);
  1359. }
  1360. } else {
  1361. qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev,
  1362. size, vaddr, paddr, memctx);
  1363. }
  1364. }
  1365. #endif
  1366. /**
  1367. * hif_batch_send() - API to access hif specific function
  1368. * ce_batch_send.
  1369. * @osc: HIF Context
  1370. * @msdu : list of msdus to be sent
  1371. * @transfer_id : transfer id
  1372. * @len : donwloaded length
  1373. *
  1374. * Return: list of msds not sent
  1375. */
  1376. qdf_nbuf_t hif_batch_send(struct hif_opaque_softc *osc, qdf_nbuf_t msdu,
  1377. uint32_t transfer_id, u_int32_t len, uint32_t sendhead)
  1378. {
  1379. void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE);
  1380. return ce_batch_send((struct CE_handle *)ce_tx_hdl, msdu, transfer_id,
  1381. len, sendhead);
  1382. }
  1383. qdf_export_symbol(hif_batch_send);
  1384. /**
  1385. * hif_update_tx_ring() - API to access hif specific function
  1386. * ce_update_tx_ring.
  1387. * @osc: HIF Context
  1388. * @num_htt_cmpls : number of htt compl received.
  1389. *
  1390. * Return: void
  1391. */
  1392. void hif_update_tx_ring(struct hif_opaque_softc *osc, u_int32_t num_htt_cmpls)
  1393. {
  1394. void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE);
  1395. ce_update_tx_ring(ce_tx_hdl, num_htt_cmpls);
  1396. }
  1397. qdf_export_symbol(hif_update_tx_ring);
  1398. /**
  1399. * hif_send_single() - API to access hif specific function
  1400. * ce_send_single.
  1401. * @osc: HIF Context
  1402. * @msdu : msdu to be sent
  1403. * @transfer_id: transfer id
  1404. * @len : downloaded length
  1405. *
  1406. * Return: msdu sent status
  1407. */
  1408. QDF_STATUS hif_send_single(struct hif_opaque_softc *osc, qdf_nbuf_t msdu,
  1409. uint32_t transfer_id, u_int32_t len)
  1410. {
  1411. void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE);
  1412. if (!ce_tx_hdl)
  1413. return QDF_STATUS_E_NULL_VALUE;
  1414. return ce_send_single((struct CE_handle *)ce_tx_hdl, msdu, transfer_id,
  1415. len);
  1416. }
  1417. qdf_export_symbol(hif_send_single);
  1418. #endif
  1419. /**
  1420. * hif_reg_write() - API to access hif specific function
  1421. * hif_write32_mb.
  1422. * @hif_ctx : HIF Context
  1423. * @offset : offset on which value has to be written
  1424. * @value : value to be written
  1425. *
  1426. * Return: None
  1427. */
  1428. void hif_reg_write(struct hif_opaque_softc *hif_ctx, uint32_t offset,
  1429. uint32_t value)
  1430. {
  1431. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  1432. hif_write32_mb(scn, scn->mem + offset, value);
  1433. }
  1434. qdf_export_symbol(hif_reg_write);
  1435. /**
  1436. * hif_reg_read() - API to access hif specific function
  1437. * hif_read32_mb.
  1438. * @hif_ctx : HIF Context
  1439. * @offset : offset from which value has to be read
  1440. *
  1441. * Return: Read value
  1442. */
  1443. uint32_t hif_reg_read(struct hif_opaque_softc *hif_ctx, uint32_t offset)
  1444. {
  1445. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  1446. return hif_read32_mb(scn, scn->mem + offset);
  1447. }
  1448. qdf_export_symbol(hif_reg_read);
  1449. /**
  1450. * hif_ramdump_handler(): generic ramdump handler
  1451. * @scn: struct hif_opaque_softc
  1452. *
  1453. * Return: None
  1454. */
  1455. void hif_ramdump_handler(struct hif_opaque_softc *scn)
  1456. {
  1457. if (hif_get_bus_type(scn) == QDF_BUS_TYPE_USB)
  1458. hif_usb_ramdump_handler(scn);
  1459. }
  1460. irqreturn_t hif_wake_interrupt_handler(int irq, void *context)
  1461. {
  1462. struct hif_softc *scn = context;
  1463. struct hif_opaque_softc *hif_ctx = GET_HIF_OPAQUE_HDL(scn);
  1464. hif_info("wake interrupt received on irq %d", irq);
  1465. if (hif_pm_runtime_get_monitor_wake_intr(hif_ctx)) {
  1466. hif_pm_runtime_set_monitor_wake_intr(hif_ctx, 0);
  1467. hif_pm_runtime_request_resume(hif_ctx);
  1468. }
  1469. if (scn->initial_wakeup_cb)
  1470. scn->initial_wakeup_cb(scn->initial_wakeup_priv);
  1471. if (hif_is_ut_suspended(scn))
  1472. hif_ut_fw_resume(scn);
  1473. qdf_pm_system_wakeup();
  1474. return IRQ_HANDLED;
  1475. }
  1476. void hif_set_initial_wakeup_cb(struct hif_opaque_softc *hif_ctx,
  1477. void (*callback)(void *),
  1478. void *priv)
  1479. {
  1480. struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
  1481. scn->initial_wakeup_cb = callback;
  1482. scn->initial_wakeup_priv = priv;
  1483. }
  1484. void hif_set_ce_service_max_yield_time(struct hif_opaque_softc *hif,
  1485. uint32_t ce_service_max_yield_time)
  1486. {
  1487. struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif);
  1488. hif_ctx->ce_service_max_yield_time =
  1489. ce_service_max_yield_time * 1000;
  1490. }
  1491. unsigned long long
  1492. hif_get_ce_service_max_yield_time(struct hif_opaque_softc *hif)
  1493. {
  1494. struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif);
  1495. return hif_ctx->ce_service_max_yield_time;
  1496. }
  1497. void hif_set_ce_service_max_rx_ind_flush(struct hif_opaque_softc *hif,
  1498. uint8_t ce_service_max_rx_ind_flush)
  1499. {
  1500. struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif);
  1501. if (ce_service_max_rx_ind_flush == 0 ||
  1502. ce_service_max_rx_ind_flush > MSG_FLUSH_NUM)
  1503. hif_ctx->ce_service_max_rx_ind_flush = MSG_FLUSH_NUM;
  1504. else
  1505. hif_ctx->ce_service_max_rx_ind_flush =
  1506. ce_service_max_rx_ind_flush;
  1507. }