xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/hif_main.c (revision 8b3dca18206e1a0461492f082fa6e270b092c035)
1 /*
2  * Copyright (c) 2015-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-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 
20 #include "targcfg.h"
21 #include "qdf_lock.h"
22 #include "qdf_status.h"
23 #include "qdf_status.h"
24 #include <qdf_atomic.h>         /* qdf_atomic_read */
25 #include <targaddrs.h>
26 #include "hif_io32.h"
27 #include <hif.h>
28 #include <target_type.h>
29 #include "regtable.h"
30 #define ATH_MODULE_NAME hif
31 #include <a_debug.h>
32 #include "hif_main.h"
33 #include "hif_hw_version.h"
34 #if (defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \
35      defined(HIF_IPCI))
36 #include "ce_tasklet.h"
37 #include "ce_api.h"
38 #endif
39 #include "qdf_trace.h"
40 #include "qdf_status.h"
41 #include "hif_debug.h"
42 #include "mp_dev.h"
43 #if defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) || \
44 	defined(QCA_WIFI_QCA5018) || defined(QCA_WIFI_QCA9574) || \
45 	defined(QCA_WIFI_QCA5332)
46 #include "hal_api.h"
47 #endif
48 #include "hif_napi.h"
49 #include "hif_unit_test_suspend_i.h"
50 #include "qdf_module.h"
51 #ifdef HIF_CE_LOG_INFO
52 #include <qdf_notifier.h>
53 #include <qdf_hang_event_notifier.h>
54 #endif
55 #include <linux/cpumask.h>
56 
57 #if defined(HIF_IPCI) && defined(FEATURE_HAL_DELAYED_REG_WRITE)
58 #include <pld_common.h>
59 #endif
60 
61 void hif_dump(struct hif_opaque_softc *hif_ctx, uint8_t cmd_id, bool start)
62 {
63 	hif_trigger_dump(hif_ctx, cmd_id, start);
64 }
65 
66 /**
67  * hif_get_target_id(): hif_get_target_id
68  *
69  * Return the virtual memory base address to the caller
70  *
71  * @scn: hif_softc
72  *
73  * Return: A_target_id_t
74  */
75 A_target_id_t hif_get_target_id(struct hif_softc *scn)
76 {
77 	return scn->mem;
78 }
79 
80 /**
81  * hif_get_targetdef(): hif_get_targetdef
82  * @scn: scn
83  *
84  * Return: void *
85  */
86 void *hif_get_targetdef(struct hif_opaque_softc *hif_ctx)
87 {
88 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
89 
90 	return scn->targetdef;
91 }
92 
93 #ifdef FORCE_WAKE
94 void hif_srng_init_phase(struct hif_opaque_softc *hif_ctx,
95 			 bool init_phase)
96 {
97 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
98 
99 	if (ce_srng_based(scn))
100 		hal_set_init_phase(scn->hal_soc, init_phase);
101 }
102 #endif /* FORCE_WAKE */
103 
104 #ifdef HIF_IPCI
105 void hif_shutdown_notifier_cb(void *hif_ctx)
106 {
107 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
108 
109 	scn->recovery = true;
110 }
111 #endif
112 
113 /**
114  * hif_vote_link_down(): unvote for link up
115  *
116  * Call hif_vote_link_down to release a previous request made using
117  * hif_vote_link_up. A hif_vote_link_down call should only be made
118  * after a corresponding hif_vote_link_up, otherwise you could be
119  * negating a vote from another source. When no votes are present
120  * hif will not guarantee the linkstate after hif_bus_suspend.
121  *
122  * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread
123  * and initialization deinitialization sequencences.
124  *
125  * Return: n/a
126  */
127 void hif_vote_link_down(struct hif_opaque_softc *hif_ctx)
128 {
129 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
130 
131 	QDF_BUG(scn);
132 	if (scn->linkstate_vote == 0)
133 		QDF_DEBUG_PANIC("linkstate_vote(%d) has already been 0",
134 				scn->linkstate_vote);
135 
136 	scn->linkstate_vote--;
137 	hif_info("Down_linkstate_vote %d", scn->linkstate_vote);
138 	if (scn->linkstate_vote == 0)
139 		hif_bus_prevent_linkdown(scn, false);
140 }
141 
142 /**
143  * hif_vote_link_up(): vote to prevent bus from suspending
144  *
145  * Makes hif guarantee that fw can message the host normally
146  * durring suspend.
147  *
148  * SYNCHRONIZE WITH hif_vote_link_up by only calling in MC thread
149  * and initialization deinitialization sequencences.
150  *
151  * Return: n/a
152  */
153 void hif_vote_link_up(struct hif_opaque_softc *hif_ctx)
154 {
155 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
156 
157 	QDF_BUG(scn);
158 	scn->linkstate_vote++;
159 	hif_info("Up_linkstate_vote %d", scn->linkstate_vote);
160 	if (scn->linkstate_vote == 1)
161 		hif_bus_prevent_linkdown(scn, true);
162 }
163 
164 /**
165  * hif_can_suspend_link(): query if hif is permitted to suspend the link
166  *
167  * Hif will ensure that the link won't be suspended if the upperlayers
168  * don't want it to.
169  *
170  * SYNCHRONIZATION: MC thread is stopped before bus suspend thus
171  * we don't need extra locking to ensure votes dont change while
172  * we are in the process of suspending or resuming.
173  *
174  * Return: false if hif will guarantee link up durring suspend.
175  */
176 bool hif_can_suspend_link(struct hif_opaque_softc *hif_ctx)
177 {
178 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
179 
180 	QDF_BUG(scn);
181 	return scn->linkstate_vote == 0;
182 }
183 
184 /**
185  * hif_hia_item_address(): hif_hia_item_address
186  * @target_type: target_type
187  * @item_offset: item_offset
188  *
189  * Return: n/a
190  */
191 uint32_t hif_hia_item_address(uint32_t target_type, uint32_t item_offset)
192 {
193 	switch (target_type) {
194 	case TARGET_TYPE_AR6002:
195 		return AR6002_HOST_INTEREST_ADDRESS + item_offset;
196 	case TARGET_TYPE_AR6003:
197 		return AR6003_HOST_INTEREST_ADDRESS + item_offset;
198 	case TARGET_TYPE_AR6004:
199 		return AR6004_HOST_INTEREST_ADDRESS + item_offset;
200 	case TARGET_TYPE_AR6006:
201 		return AR6006_HOST_INTEREST_ADDRESS + item_offset;
202 	case TARGET_TYPE_AR9888:
203 		return AR9888_HOST_INTEREST_ADDRESS + item_offset;
204 	case TARGET_TYPE_AR6320:
205 	case TARGET_TYPE_AR6320V2:
206 		return AR6320_HOST_INTEREST_ADDRESS + item_offset;
207 	case TARGET_TYPE_ADRASTEA:
208 		/* ADRASTEA doesn't have a host interest address */
209 		ASSERT(0);
210 		return 0;
211 	case TARGET_TYPE_AR900B:
212 		return AR900B_HOST_INTEREST_ADDRESS + item_offset;
213 	case TARGET_TYPE_QCA9984:
214 		return QCA9984_HOST_INTEREST_ADDRESS + item_offset;
215 	case TARGET_TYPE_QCA9888:
216 		return QCA9888_HOST_INTEREST_ADDRESS + item_offset;
217 
218 	default:
219 		ASSERT(0);
220 		return 0;
221 	}
222 }
223 
224 /**
225  * hif_max_num_receives_reached() - check max receive is reached
226  * @scn: HIF Context
227  * @count: unsigned int.
228  *
229  * Output check status as bool
230  *
231  * Return: bool
232  */
233 bool hif_max_num_receives_reached(struct hif_softc *scn, unsigned int count)
234 {
235 	if (QDF_IS_EPPING_ENABLED(hif_get_conparam(scn)))
236 		return count > 120;
237 	else
238 		return count > MAX_NUM_OF_RECEIVES;
239 }
240 
241 /**
242  * init_buffer_count() - initial buffer count
243  * @maxSize: qdf_size_t
244  *
245  * routine to modify the initial buffer count to be allocated on an os
246  * platform basis. Platform owner will need to modify this as needed
247  *
248  * Return: qdf_size_t
249  */
250 qdf_size_t init_buffer_count(qdf_size_t maxSize)
251 {
252 	return maxSize;
253 }
254 
255 /**
256  * hif_save_htc_htt_config_endpoint() - save htt_tx_endpoint
257  * @hif_ctx: hif context
258  * @htc_htt_tx_endpoint: htt_tx_endpoint
259  *
260  * Return: void
261  */
262 void hif_save_htc_htt_config_endpoint(struct hif_opaque_softc *hif_ctx,
263 							int htc_htt_tx_endpoint)
264 {
265 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
266 
267 	if (!scn) {
268 		hif_err("scn or scn->hif_sc is NULL!");
269 		return;
270 	}
271 
272 	scn->htc_htt_tx_endpoint = htc_htt_tx_endpoint;
273 }
274 qdf_export_symbol(hif_save_htc_htt_config_endpoint);
275 
276 static const struct qwlan_hw qwlan_hw_list[] = {
277 	{
278 		.id = AR6320_REV1_VERSION,
279 		.subid = 0,
280 		.name = "QCA6174_REV1",
281 	},
282 	{
283 		.id = AR6320_REV1_1_VERSION,
284 		.subid = 0x1,
285 		.name = "QCA6174_REV1_1",
286 	},
287 	{
288 		.id = AR6320_REV1_3_VERSION,
289 		.subid = 0x2,
290 		.name = "QCA6174_REV1_3",
291 	},
292 	{
293 		.id = AR6320_REV2_1_VERSION,
294 		.subid = 0x4,
295 		.name = "QCA6174_REV2_1",
296 	},
297 	{
298 		.id = AR6320_REV2_1_VERSION,
299 		.subid = 0x5,
300 		.name = "QCA6174_REV2_2",
301 	},
302 	{
303 		.id = AR6320_REV3_VERSION,
304 		.subid = 0x6,
305 		.name = "QCA6174_REV2.3",
306 	},
307 	{
308 		.id = AR6320_REV3_VERSION,
309 		.subid = 0x8,
310 		.name = "QCA6174_REV3",
311 	},
312 	{
313 		.id = AR6320_REV3_VERSION,
314 		.subid = 0x9,
315 		.name = "QCA6174_REV3_1",
316 	},
317 	{
318 		.id = AR6320_REV3_2_VERSION,
319 		.subid = 0xA,
320 		.name = "AR6320_REV3_2_VERSION",
321 	},
322 	{
323 		.id = QCA6390_V1,
324 		.subid = 0x0,
325 		.name = "QCA6390_V1",
326 	},
327 	{
328 		.id = QCA6490_V1,
329 		.subid = 0x0,
330 		.name = "QCA6490_V1",
331 	},
332 	{
333 		.id = WCN3990_v1,
334 		.subid = 0x0,
335 		.name = "WCN3990_V1",
336 	},
337 	{
338 		.id = WCN3990_v2,
339 		.subid = 0x0,
340 		.name = "WCN3990_V2",
341 	},
342 	{
343 		.id = WCN3990_v2_1,
344 		.subid = 0x0,
345 		.name = "WCN3990_V2.1",
346 	},
347 	{
348 		.id = WCN3998,
349 		.subid = 0x0,
350 		.name = "WCN3998",
351 	},
352 	{
353 		.id = QCA9379_REV1_VERSION,
354 		.subid = 0xC,
355 		.name = "QCA9379_REV1",
356 	},
357 	{
358 		.id = QCA9379_REV1_VERSION,
359 		.subid = 0xD,
360 		.name = "QCA9379_REV1_1",
361 	},
362 	{
363 		.id = MANGO_V1,
364 		.subid = 0xF,
365 		.name = "MANGO_V1",
366 	},
367 	{
368 		.id = KIWI_V1,
369 		.subid = 0,
370 		.name = "KIWI_V1",
371 	},
372 	{
373 		.id = KIWI_V2,
374 		.subid = 0,
375 		.name = "KIWI_V2",
376 	},
377 	{
378 		.id = WCN6750_V1,
379 		.subid = 0,
380 		.name = "WCN6750_V1",
381 	},
382 	{
383 		.id = QCA6490_v2_1,
384 		.subid = 0,
385 		.name = "QCA6490",
386 	},
387 	{
388 		.id = QCA6490_v2,
389 		.subid = 0,
390 		.name = "QCA6490",
391 	},
392 	{
393 		.id = WCN3990_v2_2,
394 		.subid = 0,
395 		.name = "WCN3990_v2_2",
396 	}
397 };
398 
399 /**
400  * hif_get_hw_name(): get a human readable name for the hardware
401  * @info: Target Info
402  *
403  * Return: human readable name for the underlying wifi hardware.
404  */
405 static const char *hif_get_hw_name(struct hif_target_info *info)
406 {
407 	int i;
408 
409 	hif_debug("target version = %d, target revision = %d",
410 		  info->target_version,
411 		  info->target_revision);
412 
413 	if (info->hw_name)
414 		return info->hw_name;
415 
416 	for (i = 0; i < ARRAY_SIZE(qwlan_hw_list); i++) {
417 		if (info->target_version == qwlan_hw_list[i].id &&
418 		    info->target_revision == qwlan_hw_list[i].subid) {
419 			return qwlan_hw_list[i].name;
420 		}
421 	}
422 
423 	info->hw_name = qdf_mem_malloc(64);
424 	if (!info->hw_name)
425 		return "Unknown Device (nomem)";
426 
427 	i = qdf_snprint(info->hw_name, 64, "HW_VERSION=%x.",
428 			info->target_version);
429 	if (i < 0)
430 		return "Unknown Device (snprintf failure)";
431 	else
432 		return info->hw_name;
433 }
434 
435 /**
436  * hif_get_hw_info(): hif_get_hw_info
437  * @scn: scn
438  * @version: version
439  * @revision: revision
440  *
441  * Return: n/a
442  */
443 void hif_get_hw_info(struct hif_opaque_softc *scn, u32 *version, u32 *revision,
444 			const char **target_name)
445 {
446 	struct hif_target_info *info = hif_get_target_info_handle(scn);
447 	struct hif_softc *sc = HIF_GET_SOFTC(scn);
448 
449 	if (sc->bus_type == QDF_BUS_TYPE_USB)
450 		hif_usb_get_hw_info(sc);
451 
452 	*version = info->target_version;
453 	*revision = info->target_revision;
454 	*target_name = hif_get_hw_name(info);
455 }
456 
457 /**
458  * hif_get_dev_ba(): API to get device base address.
459  * @scn: scn
460  * @version: version
461  * @revision: revision
462  *
463  * Return: n/a
464  */
465 void *hif_get_dev_ba(struct hif_opaque_softc *hif_handle)
466 {
467 	struct hif_softc *scn = (struct hif_softc *)hif_handle;
468 
469 	return scn->mem;
470 }
471 qdf_export_symbol(hif_get_dev_ba);
472 
473 /**
474  * hif_get_dev_ba_ce(): API to get device ce base address.
475  * @scn: scn
476  *
477  * Return: dev mem base address for CE
478  */
479 void *hif_get_dev_ba_ce(struct hif_opaque_softc *hif_handle)
480 {
481 	struct hif_softc *scn = (struct hif_softc *)hif_handle;
482 
483 	return scn->mem_ce;
484 }
485 
486 qdf_export_symbol(hif_get_dev_ba_ce);
487 
488 uint32_t hif_get_soc_version(struct hif_opaque_softc *hif_handle)
489 {
490 	struct hif_softc *scn = (struct hif_softc *)hif_handle;
491 
492 	return scn->target_info.soc_version;
493 }
494 
495 qdf_export_symbol(hif_get_soc_version);
496 
497 /**
498  * hif_get_dev_ba_cmem(): API to get device ce base address.
499  * @scn: scn
500  *
501  * Return: dev mem base address for CMEM
502  */
503 void *hif_get_dev_ba_cmem(struct hif_opaque_softc *hif_handle)
504 {
505 	struct hif_softc *scn = (struct hif_softc *)hif_handle;
506 
507 	return scn->mem_cmem;
508 }
509 
510 qdf_export_symbol(hif_get_dev_ba_cmem);
511 
512 #ifdef FEATURE_RUNTIME_PM
513 void hif_runtime_prevent_linkdown(struct hif_softc *scn, bool is_get)
514 {
515 	if (is_get)
516 		qdf_runtime_pm_prevent_suspend(&scn->prevent_linkdown_lock);
517 	else
518 		qdf_runtime_pm_allow_suspend(&scn->prevent_linkdown_lock);
519 }
520 
521 static inline
522 void hif_rtpm_lock_init(struct hif_softc *scn)
523 {
524 	qdf_runtime_lock_init(&scn->prevent_linkdown_lock);
525 }
526 
527 static inline
528 void hif_rtpm_lock_deinit(struct hif_softc *scn)
529 {
530 	qdf_runtime_lock_deinit(&scn->prevent_linkdown_lock);
531 }
532 #else
533 static inline
534 void hif_rtpm_lock_init(struct hif_softc *scn)
535 {
536 }
537 
538 static inline
539 void hif_rtpm_lock_deinit(struct hif_softc *scn)
540 {
541 }
542 #endif
543 
544 #ifdef WLAN_CE_INTERRUPT_THRESHOLD_CONFIG
545 /**
546  * hif_get_cfg_from_psoc() - Retrieve ini cfg from psoc
547  * @scn: hif context
548  * @psoc: psoc objmgr handle
549  *
550  * Return: None
551  */
552 static inline
553 void hif_get_cfg_from_psoc(struct hif_softc *scn,
554 			   struct wlan_objmgr_psoc *psoc)
555 {
556 	if (psoc) {
557 		scn->ini_cfg.ce_status_ring_timer_threshold =
558 			cfg_get(psoc,
559 				CFG_CE_STATUS_RING_TIMER_THRESHOLD);
560 		scn->ini_cfg.ce_status_ring_batch_count_threshold =
561 			cfg_get(psoc,
562 				CFG_CE_STATUS_RING_BATCH_COUNT_THRESHOLD);
563 	}
564 }
565 #else
566 static inline
567 void hif_get_cfg_from_psoc(struct hif_softc *scn,
568 			   struct wlan_objmgr_psoc *psoc)
569 {
570 }
571 #endif /* WLAN_CE_INTERRUPT_THRESHOLD_CONFIG */
572 
573 #if defined(HIF_CE_LOG_INFO) || defined(HIF_BUS_LOG_INFO)
574 /**
575  * hif_recovery_notifier_cb - Recovery notifier callback to log
576  *  hang event data
577  * @block: notifier block
578  * @state: state
579  * @data: notifier data
580  *
581  * Return: status
582  */
583 static
584 int hif_recovery_notifier_cb(struct notifier_block *block, unsigned long state,
585 			     void *data)
586 {
587 	struct qdf_notifer_data *notif_data = data;
588 	qdf_notif_block *notif_block;
589 	struct hif_softc *hif_handle;
590 	bool bus_id_invalid;
591 
592 	if (!data || !block)
593 		return -EINVAL;
594 
595 	notif_block = qdf_container_of(block, qdf_notif_block, notif_block);
596 
597 	hif_handle = notif_block->priv_data;
598 	if (!hif_handle)
599 		return -EINVAL;
600 
601 	bus_id_invalid = hif_log_bus_info(hif_handle, notif_data->hang_data,
602 					  &notif_data->offset);
603 	if (bus_id_invalid)
604 		return NOTIFY_STOP_MASK;
605 
606 	hif_log_ce_info(hif_handle, notif_data->hang_data,
607 			&notif_data->offset);
608 
609 	return 0;
610 }
611 
612 /**
613  * hif_register_recovery_notifier - Register hif recovery notifier
614  * @hif_handle: hif handle
615  *
616  * Return: status
617  */
618 static
619 QDF_STATUS hif_register_recovery_notifier(struct hif_softc *hif_handle)
620 {
621 	qdf_notif_block *hif_notifier;
622 
623 	if (!hif_handle)
624 		return QDF_STATUS_E_FAILURE;
625 
626 	hif_notifier = &hif_handle->hif_recovery_notifier;
627 
628 	hif_notifier->notif_block.notifier_call = hif_recovery_notifier_cb;
629 	hif_notifier->priv_data = hif_handle;
630 	return qdf_hang_event_register_notifier(hif_notifier);
631 }
632 
633 /**
634  * hif_unregister_recovery_notifier - Un-register hif recovery notifier
635  * @hif_handle: hif handle
636  *
637  * Return: status
638  */
639 static
640 QDF_STATUS hif_unregister_recovery_notifier(struct hif_softc *hif_handle)
641 {
642 	qdf_notif_block *hif_notifier = &hif_handle->hif_recovery_notifier;
643 
644 	return qdf_hang_event_unregister_notifier(hif_notifier);
645 }
646 #else
647 static inline
648 QDF_STATUS hif_register_recovery_notifier(struct hif_softc *hif_handle)
649 {
650 	return QDF_STATUS_SUCCESS;
651 }
652 
653 static inline
654 QDF_STATUS hif_unregister_recovery_notifier(struct hif_softc *hif_handle)
655 {
656 	return QDF_STATUS_SUCCESS;
657 }
658 #endif
659 
660 #ifdef HIF_CPU_PERF_AFFINE_MASK
661 /**
662  * __hif_cpu_hotplug_notify() - CPU hotplug event handler
663  * @cpu: CPU Id of the CPU generating the event
664  * @cpu_up: true if the CPU is online
665  *
666  * Return: None
667  */
668 static void __hif_cpu_hotplug_notify(void *context,
669 				     uint32_t cpu, bool cpu_up)
670 {
671 	struct hif_softc *scn = context;
672 
673 	if (!scn)
674 		return;
675 	if (hif_is_driver_unloading(scn) || hif_is_recovery_in_progress(scn))
676 		return;
677 
678 	if (cpu_up) {
679 		hif_config_irq_set_perf_affinity_hint(GET_HIF_OPAQUE_HDL(scn));
680 		hif_debug("Setting affinity for online CPU: %d", cpu);
681 	} else {
682 		hif_debug("Skip setting affinity for offline CPU: %d", cpu);
683 	}
684 }
685 
686 /**
687  * hif_cpu_hotplug_notify - cpu core up/down notification
688  * handler
689  * @cpu: CPU generating the event
690  * @cpu_up: true if the CPU is online
691  *
692  * Return: None
693  */
694 static void hif_cpu_hotplug_notify(void *context, uint32_t cpu, bool cpu_up)
695 {
696 	struct qdf_op_sync *op_sync;
697 
698 	if (qdf_op_protect(&op_sync))
699 		return;
700 
701 	__hif_cpu_hotplug_notify(context, cpu, cpu_up);
702 
703 	qdf_op_unprotect(op_sync);
704 }
705 
706 static void hif_cpu_online_cb(void *context, uint32_t cpu)
707 {
708 	hif_cpu_hotplug_notify(context, cpu, true);
709 }
710 
711 static void hif_cpu_before_offline_cb(void *context, uint32_t cpu)
712 {
713 	hif_cpu_hotplug_notify(context, cpu, false);
714 }
715 
716 static void hif_cpuhp_register(struct hif_softc *scn)
717 {
718 	if (!scn) {
719 		hif_info_high("cannot register hotplug notifiers");
720 		return;
721 	}
722 	qdf_cpuhp_register(&scn->cpuhp_event_handle,
723 			   scn,
724 			   hif_cpu_online_cb,
725 			   hif_cpu_before_offline_cb);
726 }
727 
728 static void hif_cpuhp_unregister(struct hif_softc *scn)
729 {
730 	if (!scn) {
731 		hif_info_high("cannot unregister hotplug notifiers");
732 		return;
733 	}
734 	qdf_cpuhp_unregister(&scn->cpuhp_event_handle);
735 }
736 
737 #else
738 static void hif_cpuhp_register(struct hif_softc *scn)
739 {
740 }
741 
742 static void hif_cpuhp_unregister(struct hif_softc *scn)
743 {
744 }
745 #endif /* ifdef HIF_CPU_PERF_AFFINE_MASK */
746 
747 #ifdef HIF_DETECTION_LATENCY_ENABLE
748 
749 void hif_tasklet_latency(struct hif_softc *scn, bool from_timer)
750 {
751 	qdf_time_t ce2_tasklet_sched_time =
752 		scn->latency_detect.ce2_tasklet_sched_time;
753 	qdf_time_t ce2_tasklet_exec_time =
754 		scn->latency_detect.ce2_tasklet_exec_time;
755 	qdf_time_t curr_jiffies = qdf_system_ticks();
756 	uint32_t detect_latency_threshold =
757 		scn->latency_detect.detect_latency_threshold;
758 	int cpu_id = qdf_get_cpu();
759 
760 	/* 2 kinds of check here.
761 	 * from_timer==true:  check if tasklet stall
762 	 * from_timer==false: check tasklet execute comes late
763 	 */
764 
765 	if ((from_timer ?
766 	    qdf_system_time_after(ce2_tasklet_sched_time,
767 				  ce2_tasklet_exec_time) :
768 	    qdf_system_time_after(ce2_tasklet_exec_time,
769 				  ce2_tasklet_sched_time)) &&
770 	    qdf_system_time_after(
771 		curr_jiffies,
772 		ce2_tasklet_sched_time +
773 		qdf_system_msecs_to_ticks(detect_latency_threshold))) {
774 		hif_err("tasklet ce2 latency: from_timer %d, curr_jiffies %lu, ce2_tasklet_sched_time %lu,ce2_tasklet_exec_time %lu, detect_latency_threshold %ums detect_latency_timer_timeout %ums, cpu_id %d, called: %ps",
775 			from_timer, curr_jiffies, ce2_tasklet_sched_time,
776 			ce2_tasklet_exec_time, detect_latency_threshold,
777 			scn->latency_detect.detect_latency_timer_timeout,
778 			cpu_id, (void *)_RET_IP_);
779 		goto latency;
780 	}
781 	return;
782 
783 latency:
784 	qdf_trigger_self_recovery(NULL, QDF_TASKLET_CREDIT_LATENCY_DETECT);
785 }
786 
787 void hif_credit_latency(struct hif_softc *scn, bool from_timer)
788 {
789 	qdf_time_t credit_request_time =
790 		scn->latency_detect.credit_request_time;
791 	qdf_time_t credit_report_time =
792 		scn->latency_detect.credit_report_time;
793 	qdf_time_t curr_jiffies = qdf_system_ticks();
794 	uint32_t detect_latency_threshold =
795 		scn->latency_detect.detect_latency_threshold;
796 	int cpu_id = qdf_get_cpu();
797 
798 	/* 2 kinds of check here.
799 	 * from_timer==true:  check if credit report stall
800 	 * from_timer==false: check credit report comes late
801 	 */
802 
803 	if ((from_timer ?
804 	    qdf_system_time_after(credit_request_time,
805 				  credit_report_time) :
806 	    qdf_system_time_after(credit_report_time,
807 				  credit_request_time)) &&
808 	    qdf_system_time_after(
809 		curr_jiffies,
810 		credit_request_time +
811 		qdf_system_msecs_to_ticks(detect_latency_threshold))) {
812 		hif_err("credit report latency: from timer %d, curr_jiffies %lu, credit_request_time %lu,credit_report_time %lu, detect_latency_threshold %ums, detect_latency_timer_timeout %ums, cpu_id %d, called: %ps",
813 			from_timer, curr_jiffies, credit_request_time,
814 			credit_report_time, detect_latency_threshold,
815 			scn->latency_detect.detect_latency_timer_timeout,
816 			cpu_id, (void *)_RET_IP_);
817 		goto latency;
818 	}
819 	return;
820 
821 latency:
822 	qdf_trigger_self_recovery(NULL, QDF_TASKLET_CREDIT_LATENCY_DETECT);
823 }
824 
825 /**
826  * hif_check_detection_latency(): to check if latency for tasklet/credit
827  *
828  * @scn: hif context
829  * @from_timer: if called from timer handler
830  * @bitmap_type: indicate if check tasklet or credit
831  *
832  * Return: none
833  */
834 void hif_check_detection_latency(struct hif_softc *scn,
835 				 bool from_timer,
836 				 uint32_t bitmap_type)
837 {
838 	if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn))
839 		return;
840 
841 	if (!scn->latency_detect.enable_detection)
842 		return;
843 
844 	if (bitmap_type & BIT(HIF_DETECT_TASKLET))
845 		hif_tasklet_latency(scn, from_timer);
846 
847 	if (bitmap_type & BIT(HIF_DETECT_CREDIT))
848 		hif_credit_latency(scn, from_timer);
849 }
850 
851 static void hif_latency_detect_timeout_handler(void *arg)
852 {
853 	struct hif_softc *scn = (struct hif_softc *)arg;
854 	int next_cpu;
855 
856 	hif_check_detection_latency(scn, true,
857 				    BIT(HIF_DETECT_TASKLET) |
858 				    BIT(HIF_DETECT_CREDIT));
859 
860 	/* it need to make sure timer start on a differnt cpu,
861 	 * so it can detect the tasklet schedule stall, but there
862 	 * is still chance that, after timer has been started, then
863 	 * irq/tasklet happens on the same cpu, then tasklet will
864 	 * execute before softirq timer, if this tasklet stall, the
865 	 * timer can't detect it, we can accept this as a limition,
866 	 * if tasklet stall, anyway other place will detect it, just
867 	 * a little later.
868 	 */
869 	next_cpu = cpumask_any_but(
870 			cpu_active_mask,
871 			scn->latency_detect.ce2_tasklet_sched_cpuid);
872 
873 	if (qdf_unlikely(next_cpu >= nr_cpu_ids)) {
874 		hif_debug("start timer on local");
875 		/* it doesn't found a available cpu, start on local cpu*/
876 		qdf_timer_mod(
877 			&scn->latency_detect.detect_latency_timer,
878 			scn->latency_detect.detect_latency_timer_timeout);
879 	} else {
880 		qdf_timer_start_on(
881 			&scn->latency_detect.detect_latency_timer,
882 			scn->latency_detect.detect_latency_timer_timeout,
883 			next_cpu);
884 	}
885 }
886 
887 static void hif_latency_detect_timer_init(struct hif_softc *scn)
888 {
889 	if (!scn) {
890 		hif_info_high("scn is null");
891 		return;
892 	}
893 
894 	if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn))
895 		return;
896 
897 	scn->latency_detect.detect_latency_timer_timeout =
898 		DETECTION_TIMER_TIMEOUT;
899 	scn->latency_detect.detect_latency_threshold =
900 		DETECTION_LATENCY_THRESHOLD;
901 
902 	hif_info("timer timeout %u, latency threshold %u",
903 		 scn->latency_detect.detect_latency_timer_timeout,
904 		 scn->latency_detect.detect_latency_threshold);
905 
906 	scn->latency_detect.is_timer_started = false;
907 
908 	qdf_timer_init(NULL,
909 		       &scn->latency_detect.detect_latency_timer,
910 		       &hif_latency_detect_timeout_handler,
911 		       scn,
912 		       QDF_TIMER_TYPE_SW_SPIN);
913 }
914 
915 static void hif_latency_detect_timer_deinit(struct hif_softc *scn)
916 {
917 	if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn))
918 		return;
919 
920 	hif_info("deinit timer");
921 	qdf_timer_free(&scn->latency_detect.detect_latency_timer);
922 }
923 
924 void hif_latency_detect_timer_start(struct hif_opaque_softc *hif_ctx)
925 {
926 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
927 
928 	if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn))
929 		return;
930 
931 	hif_debug_rl("start timer");
932 	if (scn->latency_detect.is_timer_started) {
933 		hif_info("timer has been started");
934 		return;
935 	}
936 
937 	qdf_timer_start(&scn->latency_detect.detect_latency_timer,
938 			scn->latency_detect.detect_latency_timer_timeout);
939 	scn->latency_detect.is_timer_started = true;
940 }
941 
942 void hif_latency_detect_timer_stop(struct hif_opaque_softc *hif_ctx)
943 {
944 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
945 
946 	if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn))
947 		return;
948 
949 	hif_debug_rl("stop timer");
950 
951 	qdf_timer_sync_cancel(&scn->latency_detect.detect_latency_timer);
952 	scn->latency_detect.is_timer_started = false;
953 }
954 
955 void hif_latency_detect_credit_record_time(
956 	enum hif_credit_exchange_type type,
957 	struct hif_opaque_softc *hif_ctx)
958 {
959 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
960 
961 	if (!scn) {
962 		hif_err("Could not do runtime put, scn is null");
963 		return;
964 	}
965 
966 	if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn))
967 		return;
968 
969 	if (HIF_REQUEST_CREDIT == type)
970 		scn->latency_detect.credit_request_time = qdf_system_ticks();
971 	else if (HIF_PROCESS_CREDIT_REPORT == type)
972 		scn->latency_detect.credit_report_time = qdf_system_ticks();
973 
974 	hif_check_detection_latency(scn, false, BIT(HIF_DETECT_CREDIT));
975 }
976 
977 void hif_set_enable_detection(struct hif_opaque_softc *hif_ctx, bool value)
978 {
979 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
980 
981 	if (!scn) {
982 		hif_err("Could not do runtime put, scn is null");
983 		return;
984 	}
985 
986 	if (QDF_GLOBAL_MISSION_MODE != hif_get_conparam(scn))
987 		return;
988 
989 	scn->latency_detect.enable_detection = value;
990 }
991 #else
992 static void hif_latency_detect_timer_init(struct hif_softc *scn)
993 {}
994 
995 static void hif_latency_detect_timer_deinit(struct hif_softc *scn)
996 {}
997 #endif
998 struct hif_opaque_softc *hif_open(qdf_device_t qdf_ctx,
999 				  uint32_t mode,
1000 				  enum qdf_bus_type bus_type,
1001 				  struct hif_driver_state_callbacks *cbk,
1002 				  struct wlan_objmgr_psoc *psoc)
1003 {
1004 	struct hif_softc *scn;
1005 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1006 	int bus_context_size = hif_bus_get_context_size(bus_type);
1007 
1008 	if (bus_context_size == 0) {
1009 		hif_err("context size 0 not allowed");
1010 		return NULL;
1011 	}
1012 
1013 	scn = (struct hif_softc *)qdf_mem_malloc(bus_context_size);
1014 	if (!scn)
1015 		return GET_HIF_OPAQUE_HDL(scn);
1016 
1017 	scn->qdf_dev = qdf_ctx;
1018 	scn->hif_con_param = mode;
1019 	qdf_atomic_init(&scn->active_tasklet_cnt);
1020 
1021 	qdf_atomic_init(&scn->active_grp_tasklet_cnt);
1022 	qdf_atomic_init(&scn->link_suspended);
1023 	qdf_atomic_init(&scn->tasklet_from_intr);
1024 	hif_system_pm_set_state_on(GET_HIF_OPAQUE_HDL(scn));
1025 	qdf_mem_copy(&scn->callbacks, cbk,
1026 		     sizeof(struct hif_driver_state_callbacks));
1027 	scn->bus_type  = bus_type;
1028 
1029 	hif_allow_ep_vote_access(GET_HIF_OPAQUE_HDL(scn));
1030 	hif_get_cfg_from_psoc(scn, psoc);
1031 
1032 	hif_set_event_hist_mask(GET_HIF_OPAQUE_HDL(scn));
1033 	status = hif_bus_open(scn, bus_type);
1034 	if (status != QDF_STATUS_SUCCESS) {
1035 		hif_err("hif_bus_open error = %d, bus_type = %d",
1036 			status, bus_type);
1037 		qdf_mem_free(scn);
1038 		scn = NULL;
1039 		goto out;
1040 	}
1041 
1042 	hif_rtpm_lock_init(scn);
1043 
1044 	hif_cpuhp_register(scn);
1045 	hif_latency_detect_timer_init(scn);
1046 
1047 out:
1048 	return GET_HIF_OPAQUE_HDL(scn);
1049 }
1050 
1051 #ifdef ADRASTEA_RRI_ON_DDR
1052 /**
1053  * hif_uninit_rri_on_ddr(): free consistent memory allocated for rri
1054  * @scn: hif context
1055  *
1056  * Return: none
1057  */
1058 void hif_uninit_rri_on_ddr(struct hif_softc *scn)
1059 {
1060 	if (scn->vaddr_rri_on_ddr)
1061 		qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev,
1062 					(CE_COUNT * sizeof(uint32_t)),
1063 					scn->vaddr_rri_on_ddr,
1064 					scn->paddr_rri_on_ddr, 0);
1065 	scn->vaddr_rri_on_ddr = NULL;
1066 }
1067 #endif
1068 
1069 /**
1070  * hif_close(): hif_close
1071  * @hif_ctx: hif_ctx
1072  *
1073  * Return: n/a
1074  */
1075 void hif_close(struct hif_opaque_softc *hif_ctx)
1076 {
1077 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
1078 
1079 	if (!scn) {
1080 		hif_err("hif_opaque_softc is NULL");
1081 		return;
1082 	}
1083 
1084 	hif_latency_detect_timer_deinit(scn);
1085 
1086 	if (scn->athdiag_procfs_inited) {
1087 		athdiag_procfs_remove();
1088 		scn->athdiag_procfs_inited = false;
1089 	}
1090 
1091 	if (scn->target_info.hw_name) {
1092 		char *hw_name = scn->target_info.hw_name;
1093 
1094 		scn->target_info.hw_name = "ErrUnloading";
1095 		qdf_mem_free(hw_name);
1096 	}
1097 
1098 	hif_uninit_rri_on_ddr(scn);
1099 	hif_cleanup_static_buf_to_target(scn);
1100 	hif_cpuhp_unregister(scn);
1101 	hif_rtpm_lock_deinit(scn);
1102 
1103 	hif_bus_close(scn);
1104 
1105 	qdf_mem_free(scn);
1106 }
1107 
1108 /**
1109  * hif_get_num_active_grp_tasklets() - get the number of active
1110  *		datapath group tasklets pending to be completed.
1111  * @scn: HIF context
1112  *
1113  * Returns: the number of datapath group tasklets which are active
1114  */
1115 static inline int hif_get_num_active_grp_tasklets(struct hif_softc *scn)
1116 {
1117 	return qdf_atomic_read(&scn->active_grp_tasklet_cnt);
1118 }
1119 
1120 #if (defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) || \
1121 	defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) || \
1122 	defined(QCA_WIFI_QCN9000) || defined(QCA_WIFI_QCA6490) || \
1123 	defined(QCA_WIFI_QCA6750) || defined(QCA_WIFI_QCA5018) || \
1124 	defined(QCA_WIFI_KIWI) || defined(QCA_WIFI_QCN9224) || \
1125 	defined(QCA_WIFI_QCA9574)) || defined(QCA_WIFI_QCA5332)
1126 /**
1127  * hif_get_num_pending_work() - get the number of entries in
1128  *		the workqueue pending to be completed.
1129  * @scn: HIF context
1130  *
1131  * Returns: the number of tasklets which are active
1132  */
1133 static inline int hif_get_num_pending_work(struct hif_softc *scn)
1134 {
1135 	return hal_get_reg_write_pending_work(scn->hal_soc);
1136 }
1137 #else
1138 
1139 static inline int hif_get_num_pending_work(struct hif_softc *scn)
1140 {
1141 	return 0;
1142 }
1143 #endif
1144 
1145 QDF_STATUS hif_try_complete_tasks(struct hif_softc *scn)
1146 {
1147 	uint32_t task_drain_wait_cnt = 0;
1148 	int tasklet = 0, grp_tasklet = 0, work = 0;
1149 
1150 	while ((tasklet = hif_get_num_active_tasklets(scn)) ||
1151 	       (grp_tasklet = hif_get_num_active_grp_tasklets(scn)) ||
1152 	       (work = hif_get_num_pending_work(scn))) {
1153 		if (++task_drain_wait_cnt > HIF_TASK_DRAIN_WAIT_CNT) {
1154 			hif_err("pending tasklets %d grp tasklets %d work %d",
1155 				tasklet, grp_tasklet, work);
1156 			return QDF_STATUS_E_FAULT;
1157 		}
1158 		hif_info("waiting for tasklets %d grp tasklets %d work %d",
1159 			 tasklet, grp_tasklet, work);
1160 		msleep(10);
1161 	}
1162 
1163 	return QDF_STATUS_SUCCESS;
1164 }
1165 
1166 #if defined(HIF_IPCI) && defined(FEATURE_HAL_DELAYED_REG_WRITE)
1167 QDF_STATUS hif_try_prevent_ep_vote_access(struct hif_opaque_softc *hif_ctx)
1168 {
1169 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
1170 	uint32_t work_drain_wait_cnt = 0;
1171 	uint32_t wait_cnt = 0;
1172 	int work = 0;
1173 
1174 	qdf_atomic_set(&scn->dp_ep_vote_access,
1175 		       HIF_EP_VOTE_ACCESS_DISABLE);
1176 	qdf_atomic_set(&scn->ep_vote_access,
1177 		       HIF_EP_VOTE_ACCESS_DISABLE);
1178 
1179 	while ((work = hif_get_num_pending_work(scn))) {
1180 		if (++work_drain_wait_cnt > HIF_WORK_DRAIN_WAIT_CNT) {
1181 			qdf_atomic_set(&scn->dp_ep_vote_access,
1182 				       HIF_EP_VOTE_ACCESS_ENABLE);
1183 			qdf_atomic_set(&scn->ep_vote_access,
1184 				       HIF_EP_VOTE_ACCESS_ENABLE);
1185 			hif_err("timeout wait for pending work %d ", work);
1186 			return QDF_STATUS_E_FAULT;
1187 		}
1188 		qdf_sleep(10);
1189 	}
1190 
1191 	if (pld_is_pci_ep_awake(scn->qdf_dev->dev) == -ENOTSUPP)
1192 	return QDF_STATUS_SUCCESS;
1193 
1194 	while (pld_is_pci_ep_awake(scn->qdf_dev->dev)) {
1195 		if (++wait_cnt > HIF_EP_WAKE_RESET_WAIT_CNT) {
1196 			hif_err("Release EP vote is not proceed by Fw");
1197 			return QDF_STATUS_E_FAULT;
1198 		}
1199 		qdf_sleep(5);
1200 	}
1201 
1202 	return QDF_STATUS_SUCCESS;
1203 }
1204 
1205 void hif_set_ep_intermediate_vote_access(struct hif_opaque_softc *hif_ctx)
1206 {
1207 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
1208 	uint8_t vote_access;
1209 
1210 	vote_access = qdf_atomic_read(&scn->ep_vote_access);
1211 
1212 	if (vote_access != HIF_EP_VOTE_ACCESS_DISABLE)
1213 		hif_info("EP vote changed from:%u to intermediate state",
1214 			 vote_access);
1215 
1216 	if (QDF_IS_STATUS_ERROR(hif_try_prevent_ep_vote_access(hif_ctx)))
1217 		QDF_BUG(0);
1218 
1219 	qdf_atomic_set(&scn->ep_vote_access,
1220 		       HIF_EP_VOTE_INTERMEDIATE_ACCESS);
1221 }
1222 
1223 void hif_allow_ep_vote_access(struct hif_opaque_softc *hif_ctx)
1224 {
1225 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
1226 
1227 	qdf_atomic_set(&scn->dp_ep_vote_access,
1228 		       HIF_EP_VOTE_ACCESS_ENABLE);
1229 	qdf_atomic_set(&scn->ep_vote_access,
1230 		       HIF_EP_VOTE_ACCESS_ENABLE);
1231 }
1232 
1233 void hif_set_ep_vote_access(struct hif_opaque_softc *hif_ctx,
1234 			    uint8_t type, uint8_t access)
1235 {
1236 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
1237 
1238 	if (type == HIF_EP_VOTE_DP_ACCESS)
1239 		qdf_atomic_set(&scn->dp_ep_vote_access, access);
1240 	else
1241 		qdf_atomic_set(&scn->ep_vote_access, access);
1242 }
1243 
1244 uint8_t hif_get_ep_vote_access(struct hif_opaque_softc *hif_ctx,
1245 			       uint8_t type)
1246 {
1247 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
1248 
1249 	if (type == HIF_EP_VOTE_DP_ACCESS)
1250 		return qdf_atomic_read(&scn->dp_ep_vote_access);
1251 	else
1252 		return qdf_atomic_read(&scn->ep_vote_access);
1253 }
1254 #endif
1255 
1256 #if (defined(QCA_WIFI_QCA8074) || defined(QCA_WIFI_QCA6018) || \
1257 	defined(QCA_WIFI_QCA6290) || defined(QCA_WIFI_QCA6390) || \
1258 	defined(QCA_WIFI_QCN9000) || defined(QCA_WIFI_QCA6490) || \
1259 	defined(QCA_WIFI_QCA6750) || defined(QCA_WIFI_QCA5018) || \
1260 	defined(QCA_WIFI_KIWI) || defined(QCA_WIFI_QCN9224) || \
1261 	defined(QCA_WIFI_QCA9574)) || defined(QCA_WIFI_QCA5332)
1262 static QDF_STATUS hif_hal_attach(struct hif_softc *scn)
1263 {
1264 	if (ce_srng_based(scn)) {
1265 		scn->hal_soc = hal_attach(
1266 					hif_softc_to_hif_opaque_softc(scn),
1267 					scn->qdf_dev);
1268 		if (!scn->hal_soc)
1269 			return QDF_STATUS_E_FAILURE;
1270 	}
1271 
1272 	return QDF_STATUS_SUCCESS;
1273 }
1274 
1275 static QDF_STATUS hif_hal_detach(struct hif_softc *scn)
1276 {
1277 	if (ce_srng_based(scn)) {
1278 		hal_detach(scn->hal_soc);
1279 		scn->hal_soc = NULL;
1280 	}
1281 
1282 	return QDF_STATUS_SUCCESS;
1283 }
1284 #else
1285 static QDF_STATUS hif_hal_attach(struct hif_softc *scn)
1286 {
1287 	return QDF_STATUS_SUCCESS;
1288 }
1289 
1290 static QDF_STATUS hif_hal_detach(struct hif_softc *scn)
1291 {
1292 	return QDF_STATUS_SUCCESS;
1293 }
1294 #endif
1295 
1296 int hif_init_dma_mask(struct device *dev, enum qdf_bus_type bus_type)
1297 {
1298 	int ret;
1299 
1300 	switch (bus_type) {
1301 	case QDF_BUS_TYPE_IPCI:
1302 		ret = qdf_set_dma_coherent_mask(dev,
1303 						DMA_COHERENT_MASK_DEFAULT);
1304 		if (ret) {
1305 			hif_err("Failed to set dma mask error = %d", ret);
1306 			return ret;
1307 		}
1308 
1309 		break;
1310 	default:
1311 		/* Follow the existing sequence for other targets */
1312 		break;
1313 	}
1314 
1315 	return 0;
1316 }
1317 
1318 /**
1319  * hif_enable(): hif_enable
1320  * @hif_ctx: hif_ctx
1321  * @dev: dev
1322  * @bdev: bus dev
1323  * @bid: bus ID
1324  * @bus_type: bus type
1325  * @type: enable type
1326  *
1327  * Return: QDF_STATUS
1328  */
1329 QDF_STATUS hif_enable(struct hif_opaque_softc *hif_ctx, struct device *dev,
1330 					  void *bdev,
1331 					  const struct hif_bus_id *bid,
1332 					  enum qdf_bus_type bus_type,
1333 					  enum hif_enable_type type)
1334 {
1335 	QDF_STATUS status;
1336 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
1337 
1338 	if (!scn) {
1339 		hif_err("hif_ctx = NULL");
1340 		return QDF_STATUS_E_NULL_VALUE;
1341 	}
1342 
1343 	status = hif_enable_bus(scn, dev, bdev, bid, type);
1344 	if (status != QDF_STATUS_SUCCESS) {
1345 		hif_err("hif_enable_bus error = %d", status);
1346 		return status;
1347 	}
1348 
1349 	status = hif_hal_attach(scn);
1350 	if (status != QDF_STATUS_SUCCESS) {
1351 		hif_err("hal attach failed");
1352 		goto disable_bus;
1353 	}
1354 
1355 	if (hif_bus_configure(scn)) {
1356 		hif_err("Target probe failed");
1357 		status = QDF_STATUS_E_FAILURE;
1358 		goto hal_detach;
1359 	}
1360 
1361 	hif_ut_suspend_init(scn);
1362 	hif_register_recovery_notifier(scn);
1363 	hif_latency_detect_timer_start(hif_ctx);
1364 
1365 	/*
1366 	 * Flag to avoid potential unallocated memory access from MSI
1367 	 * interrupt handler which could get scheduled as soon as MSI
1368 	 * is enabled, i.e to take care of the race due to the order
1369 	 * in where MSI is enabled before the memory, that will be
1370 	 * in interrupt handlers, is allocated.
1371 	 */
1372 
1373 	scn->hif_init_done = true;
1374 
1375 	hif_debug("OK");
1376 
1377 	return QDF_STATUS_SUCCESS;
1378 
1379 hal_detach:
1380 	hif_hal_detach(scn);
1381 disable_bus:
1382 	hif_disable_bus(scn);
1383 	return status;
1384 }
1385 
1386 void hif_disable(struct hif_opaque_softc *hif_ctx, enum hif_disable_type type)
1387 {
1388 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
1389 
1390 	if (!scn)
1391 		return;
1392 
1393 	hif_set_enable_detection(hif_ctx, false);
1394 	hif_latency_detect_timer_stop(hif_ctx);
1395 
1396 	hif_unregister_recovery_notifier(scn);
1397 
1398 	hif_nointrs(scn);
1399 	if (scn->hif_init_done == false)
1400 		hif_shutdown_device(hif_ctx);
1401 	else
1402 		hif_stop(hif_ctx);
1403 
1404 	hif_hal_detach(scn);
1405 
1406 	hif_disable_bus(scn);
1407 
1408 	hif_wlan_disable(scn);
1409 
1410 	scn->notice_send = false;
1411 
1412 	hif_debug("X");
1413 }
1414 
1415 #ifdef CE_TASKLET_DEBUG_ENABLE
1416 void hif_enable_ce_latency_stats(struct hif_opaque_softc *hif_ctx, uint8_t val)
1417 {
1418 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
1419 
1420 	if (!scn)
1421 		return;
1422 
1423 	scn->ce_latency_stats = val;
1424 }
1425 #endif
1426 
1427 void hif_display_stats(struct hif_opaque_softc *hif_ctx)
1428 {
1429 	hif_display_bus_stats(hif_ctx);
1430 }
1431 
1432 qdf_export_symbol(hif_display_stats);
1433 
1434 void hif_clear_stats(struct hif_opaque_softc *hif_ctx)
1435 {
1436 	hif_clear_bus_stats(hif_ctx);
1437 }
1438 
1439 /**
1440  * hif_crash_shutdown_dump_bus_register() - dump bus registers
1441  * @hif_ctx: hif_ctx
1442  *
1443  * Return: n/a
1444  */
1445 #if defined(TARGET_RAMDUMP_AFTER_KERNEL_PANIC) && defined(WLAN_FEATURE_BMI)
1446 
1447 static void hif_crash_shutdown_dump_bus_register(void *hif_ctx)
1448 {
1449 	struct hif_opaque_softc *scn = hif_ctx;
1450 
1451 	if (hif_check_soc_status(scn))
1452 		return;
1453 
1454 	if (hif_dump_registers(scn))
1455 		hif_err("Failed to dump bus registers!");
1456 }
1457 
1458 /**
1459  * hif_crash_shutdown(): hif_crash_shutdown
1460  *
1461  * This function is called by the platform driver to dump CE registers
1462  *
1463  * @hif_ctx: hif_ctx
1464  *
1465  * Return: n/a
1466  */
1467 void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx)
1468 {
1469 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
1470 
1471 	if (!hif_ctx)
1472 		return;
1473 
1474 	if (scn->bus_type == QDF_BUS_TYPE_SNOC) {
1475 		hif_warn("RAM dump disabled for bustype %d", scn->bus_type);
1476 		return;
1477 	}
1478 
1479 	if (TARGET_STATUS_RESET == scn->target_status) {
1480 		hif_warn("Target is already asserted, ignore!");
1481 		return;
1482 	}
1483 
1484 	if (hif_is_load_or_unload_in_progress(scn)) {
1485 		hif_err("Load/unload is in progress, ignore!");
1486 		return;
1487 	}
1488 
1489 	hif_crash_shutdown_dump_bus_register(hif_ctx);
1490 	hif_set_target_status(hif_ctx, TARGET_STATUS_RESET);
1491 
1492 	if (ol_copy_ramdump(hif_ctx))
1493 		goto out;
1494 
1495 	hif_info("RAM dump collecting completed!");
1496 
1497 out:
1498 	return;
1499 }
1500 #else
1501 void hif_crash_shutdown(struct hif_opaque_softc *hif_ctx)
1502 {
1503 	hif_debug("Collecting target RAM dump disabled");
1504 }
1505 #endif /* TARGET_RAMDUMP_AFTER_KERNEL_PANIC */
1506 
1507 #ifdef QCA_WIFI_3_0
1508 /**
1509  * hif_check_fw_reg(): hif_check_fw_reg
1510  * @scn: scn
1511  * @state:
1512  *
1513  * Return: int
1514  */
1515 int hif_check_fw_reg(struct hif_opaque_softc *scn)
1516 {
1517 	return 0;
1518 }
1519 #endif
1520 
1521 /**
1522  * hif_read_phy_mem_base(): hif_read_phy_mem_base
1523  * @scn: scn
1524  * @phy_mem_base: physical mem base
1525  *
1526  * Return: n/a
1527  */
1528 void hif_read_phy_mem_base(struct hif_softc *scn, qdf_dma_addr_t *phy_mem_base)
1529 {
1530 	*phy_mem_base = scn->mem_pa;
1531 }
1532 qdf_export_symbol(hif_read_phy_mem_base);
1533 
1534 /**
1535  * hif_get_device_type(): hif_get_device_type
1536  * @device_id: device_id
1537  * @revision_id: revision_id
1538  * @hif_type: returned hif_type
1539  * @target_type: returned target_type
1540  *
1541  * Return: int
1542  */
1543 int hif_get_device_type(uint32_t device_id,
1544 			uint32_t revision_id,
1545 			uint32_t *hif_type, uint32_t *target_type)
1546 {
1547 	int ret = 0;
1548 
1549 	switch (device_id) {
1550 	case ADRASTEA_DEVICE_ID_P2_E12:
1551 
1552 		*hif_type = HIF_TYPE_ADRASTEA;
1553 		*target_type = TARGET_TYPE_ADRASTEA;
1554 		break;
1555 
1556 	case AR9888_DEVICE_ID:
1557 		*hif_type = HIF_TYPE_AR9888;
1558 		*target_type = TARGET_TYPE_AR9888;
1559 		break;
1560 
1561 	case AR6320_DEVICE_ID:
1562 		switch (revision_id) {
1563 		case AR6320_FW_1_1:
1564 		case AR6320_FW_1_3:
1565 			*hif_type = HIF_TYPE_AR6320;
1566 			*target_type = TARGET_TYPE_AR6320;
1567 			break;
1568 
1569 		case AR6320_FW_2_0:
1570 		case AR6320_FW_3_0:
1571 		case AR6320_FW_3_2:
1572 			*hif_type = HIF_TYPE_AR6320V2;
1573 			*target_type = TARGET_TYPE_AR6320V2;
1574 			break;
1575 
1576 		default:
1577 			hif_err("dev_id = 0x%x, rev_id = 0x%x",
1578 				device_id, revision_id);
1579 			ret = -ENODEV;
1580 			goto end;
1581 		}
1582 		break;
1583 
1584 	case AR9887_DEVICE_ID:
1585 		*hif_type = HIF_TYPE_AR9888;
1586 		*target_type = TARGET_TYPE_AR9888;
1587 		hif_info(" *********** AR9887 **************");
1588 		break;
1589 
1590 	case QCA9984_DEVICE_ID:
1591 		*hif_type = HIF_TYPE_QCA9984;
1592 		*target_type = TARGET_TYPE_QCA9984;
1593 		hif_info(" *********** QCA9984 *************");
1594 		break;
1595 
1596 	case QCA9888_DEVICE_ID:
1597 		*hif_type = HIF_TYPE_QCA9888;
1598 		*target_type = TARGET_TYPE_QCA9888;
1599 		hif_info(" *********** QCA9888 *************");
1600 		break;
1601 
1602 	case AR900B_DEVICE_ID:
1603 		*hif_type = HIF_TYPE_AR900B;
1604 		*target_type = TARGET_TYPE_AR900B;
1605 		hif_info(" *********** AR900B *************");
1606 		break;
1607 
1608 	case QCA8074_DEVICE_ID:
1609 		*hif_type = HIF_TYPE_QCA8074;
1610 		*target_type = TARGET_TYPE_QCA8074;
1611 		hif_info(" *********** QCA8074  *************");
1612 		break;
1613 
1614 	case QCA6290_EMULATION_DEVICE_ID:
1615 	case QCA6290_DEVICE_ID:
1616 		*hif_type = HIF_TYPE_QCA6290;
1617 		*target_type = TARGET_TYPE_QCA6290;
1618 		hif_info(" *********** QCA6290EMU *************");
1619 		break;
1620 
1621 	case QCN9000_DEVICE_ID:
1622 		*hif_type = HIF_TYPE_QCN9000;
1623 		*target_type = TARGET_TYPE_QCN9000;
1624 		hif_info(" *********** QCN9000 *************");
1625 		break;
1626 
1627 	case QCN9224_DEVICE_ID:
1628 		*hif_type = HIF_TYPE_QCN9224;
1629 		*target_type = TARGET_TYPE_QCN9224;
1630 		hif_info(" *********** QCN9224 *************");
1631 		break;
1632 
1633 	case QCN6122_DEVICE_ID:
1634 		*hif_type = HIF_TYPE_QCN6122;
1635 		*target_type = TARGET_TYPE_QCN6122;
1636 		hif_info(" *********** QCN6122 *************");
1637 		break;
1638 
1639 	case QCN7605_DEVICE_ID:
1640 	case QCN7605_COMPOSITE:
1641 	case QCN7605_STANDALONE:
1642 	case QCN7605_STANDALONE_V2:
1643 	case QCN7605_COMPOSITE_V2:
1644 		*hif_type = HIF_TYPE_QCN7605;
1645 		*target_type = TARGET_TYPE_QCN7605;
1646 		hif_info(" *********** QCN7605 *************");
1647 		break;
1648 
1649 	case QCA6390_DEVICE_ID:
1650 	case QCA6390_EMULATION_DEVICE_ID:
1651 		*hif_type = HIF_TYPE_QCA6390;
1652 		*target_type = TARGET_TYPE_QCA6390;
1653 		hif_info(" *********** QCA6390 *************");
1654 		break;
1655 
1656 	case QCA6490_DEVICE_ID:
1657 	case QCA6490_EMULATION_DEVICE_ID:
1658 		*hif_type = HIF_TYPE_QCA6490;
1659 		*target_type = TARGET_TYPE_QCA6490;
1660 		hif_info(" *********** QCA6490 *************");
1661 		break;
1662 
1663 	case QCA6750_DEVICE_ID:
1664 	case QCA6750_EMULATION_DEVICE_ID:
1665 		*hif_type = HIF_TYPE_QCA6750;
1666 		*target_type = TARGET_TYPE_QCA6750;
1667 		hif_info(" *********** QCA6750 *************");
1668 		break;
1669 
1670 	case KIWI_DEVICE_ID:
1671 		*hif_type = HIF_TYPE_KIWI;
1672 		*target_type = TARGET_TYPE_KIWI;
1673 		hif_info(" *********** KIWI *************");
1674 		break;
1675 
1676 	case MANGO_DEVICE_ID:
1677 		*hif_type = HIF_TYPE_MANGO;
1678 		*target_type = TARGET_TYPE_MANGO;
1679 		hif_info(" *********** MANGO *************");
1680 		break;
1681 
1682 	case QCA8074V2_DEVICE_ID:
1683 		*hif_type = HIF_TYPE_QCA8074V2;
1684 		*target_type = TARGET_TYPE_QCA8074V2;
1685 		hif_info(" *********** QCA8074V2 *************");
1686 		break;
1687 
1688 	case QCA6018_DEVICE_ID:
1689 	case RUMIM2M_DEVICE_ID_NODE0:
1690 	case RUMIM2M_DEVICE_ID_NODE1:
1691 	case RUMIM2M_DEVICE_ID_NODE2:
1692 	case RUMIM2M_DEVICE_ID_NODE3:
1693 	case RUMIM2M_DEVICE_ID_NODE4:
1694 	case RUMIM2M_DEVICE_ID_NODE5:
1695 		*hif_type = HIF_TYPE_QCA6018;
1696 		*target_type = TARGET_TYPE_QCA6018;
1697 		hif_info(" *********** QCA6018 *************");
1698 		break;
1699 
1700 	case QCA5018_DEVICE_ID:
1701 		*hif_type = HIF_TYPE_QCA5018;
1702 		*target_type = TARGET_TYPE_QCA5018;
1703 		hif_info(" *********** qca5018 *************");
1704 		break;
1705 
1706 	case QCA5332_DEVICE_ID:
1707 		*hif_type = HIF_TYPE_QCA5332;
1708 		*target_type = TARGET_TYPE_QCA5332;
1709 		hif_info(" *********** QCA5332 *************");
1710 		break;
1711 
1712 	case QCA9574_DEVICE_ID:
1713 		*hif_type = HIF_TYPE_QCA9574;
1714 		*target_type = TARGET_TYPE_QCA9574;
1715 		hif_info(" *********** QCA9574 *************");
1716 		break;
1717 
1718 	default:
1719 		hif_err("Unsupported device ID = 0x%x!", device_id);
1720 		ret = -ENODEV;
1721 		break;
1722 	}
1723 
1724 	if (*target_type == TARGET_TYPE_UNKNOWN) {
1725 		hif_err("Unsupported target_type!");
1726 		ret = -ENODEV;
1727 	}
1728 end:
1729 	return ret;
1730 }
1731 
1732 /**
1733  * hif_get_bus_type() - return the bus type
1734  *
1735  * Return: enum qdf_bus_type
1736  */
1737 enum qdf_bus_type hif_get_bus_type(struct hif_opaque_softc *hif_hdl)
1738 {
1739 	struct hif_softc *scn = HIF_GET_SOFTC(hif_hdl);
1740 
1741 	return scn->bus_type;
1742 }
1743 
1744 /**
1745  * Target info and ini parameters are global to the driver
1746  * Hence these structures are exposed to all the modules in
1747  * the driver and they don't need to maintains multiple copies
1748  * of the same info, instead get the handle from hif and
1749  * modify them in hif
1750  */
1751 
1752 /**
1753  * hif_get_ini_handle() - API to get hif_config_param handle
1754  * @hif_ctx: HIF Context
1755  *
1756  * Return: pointer to hif_config_info
1757  */
1758 struct hif_config_info *hif_get_ini_handle(struct hif_opaque_softc *hif_ctx)
1759 {
1760 	struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx);
1761 
1762 	return &sc->hif_config;
1763 }
1764 
1765 /**
1766  * hif_get_target_info_handle() - API to get hif_target_info handle
1767  * @hif_ctx: HIF context
1768  *
1769  * Return: Pointer to hif_target_info
1770  */
1771 struct hif_target_info *hif_get_target_info_handle(
1772 					struct hif_opaque_softc *hif_ctx)
1773 {
1774 	struct hif_softc *sc = HIF_GET_SOFTC(hif_ctx);
1775 
1776 	return &sc->target_info;
1777 
1778 }
1779 qdf_export_symbol(hif_get_target_info_handle);
1780 
1781 #ifdef RECEIVE_OFFLOAD
1782 void hif_offld_flush_cb_register(struct hif_opaque_softc *scn,
1783 				 void (offld_flush_handler)(void *))
1784 {
1785 	if (hif_napi_enabled(scn, -1))
1786 		hif_napi_rx_offld_flush_cb_register(scn, offld_flush_handler);
1787 	else
1788 		hif_err("NAPI not enabled");
1789 }
1790 qdf_export_symbol(hif_offld_flush_cb_register);
1791 
1792 void hif_offld_flush_cb_deregister(struct hif_opaque_softc *scn)
1793 {
1794 	if (hif_napi_enabled(scn, -1))
1795 		hif_napi_rx_offld_flush_cb_deregister(scn);
1796 	else
1797 		hif_err("NAPI not enabled");
1798 }
1799 qdf_export_symbol(hif_offld_flush_cb_deregister);
1800 
1801 int hif_get_rx_ctx_id(int ctx_id, struct hif_opaque_softc *hif_hdl)
1802 {
1803 	if (hif_napi_enabled(hif_hdl, -1))
1804 		return NAPI_PIPE2ID(ctx_id);
1805 	else
1806 		return ctx_id;
1807 }
1808 #else /* RECEIVE_OFFLOAD */
1809 int hif_get_rx_ctx_id(int ctx_id, struct hif_opaque_softc *hif_hdl)
1810 {
1811 	return 0;
1812 }
1813 qdf_export_symbol(hif_get_rx_ctx_id);
1814 #endif /* RECEIVE_OFFLOAD */
1815 
1816 #if defined(FEATURE_LRO)
1817 
1818 /**
1819  * hif_get_lro_info - Returns LRO instance for instance ID
1820  * @ctx_id: LRO instance ID
1821  * @hif_hdl: HIF Context
1822  *
1823  * Return: Pointer to LRO instance.
1824  */
1825 void *hif_get_lro_info(int ctx_id, struct hif_opaque_softc *hif_hdl)
1826 {
1827 	void *data;
1828 
1829 	if (hif_napi_enabled(hif_hdl, -1))
1830 		data = hif_napi_get_lro_info(hif_hdl, ctx_id);
1831 	else
1832 		data = hif_ce_get_lro_ctx(hif_hdl, ctx_id);
1833 
1834 	return data;
1835 }
1836 #endif
1837 
1838 /**
1839  * hif_get_target_status - API to get target status
1840  * @hif_ctx: HIF Context
1841  *
1842  * Return: enum hif_target_status
1843  */
1844 enum hif_target_status hif_get_target_status(struct hif_opaque_softc *hif_ctx)
1845 {
1846 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
1847 
1848 	return scn->target_status;
1849 }
1850 qdf_export_symbol(hif_get_target_status);
1851 
1852 /**
1853  * hif_set_target_status() - API to set target status
1854  * @hif_ctx: HIF Context
1855  * @status: Target Status
1856  *
1857  * Return: void
1858  */
1859 void hif_set_target_status(struct hif_opaque_softc *hif_ctx, enum
1860 			   hif_target_status status)
1861 {
1862 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
1863 
1864 	scn->target_status = status;
1865 }
1866 
1867 /**
1868  * hif_init_ini_config() - API to initialize HIF configuration parameters
1869  * @hif_ctx: HIF Context
1870  * @cfg: HIF Configuration
1871  *
1872  * Return: void
1873  */
1874 void hif_init_ini_config(struct hif_opaque_softc *hif_ctx,
1875 			 struct hif_config_info *cfg)
1876 {
1877 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
1878 
1879 	qdf_mem_copy(&scn->hif_config, cfg, sizeof(struct hif_config_info));
1880 }
1881 
1882 /**
1883  * hif_get_conparam() - API to get driver mode in HIF
1884  * @scn: HIF Context
1885  *
1886  * Return: driver mode of operation
1887  */
1888 uint32_t hif_get_conparam(struct hif_softc *scn)
1889 {
1890 	if (!scn)
1891 		return 0;
1892 
1893 	return scn->hif_con_param;
1894 }
1895 
1896 /**
1897  * hif_get_callbacks_handle() - API to get callbacks Handle
1898  * @scn: HIF Context
1899  *
1900  * Return: pointer to HIF Callbacks
1901  */
1902 struct hif_driver_state_callbacks *hif_get_callbacks_handle(
1903 							struct hif_softc *scn)
1904 {
1905 	return &scn->callbacks;
1906 }
1907 
1908 /**
1909  * hif_is_driver_unloading() - API to query upper layers if driver is unloading
1910  * @scn: HIF Context
1911  *
1912  * Return: True/False
1913  */
1914 bool hif_is_driver_unloading(struct hif_softc *scn)
1915 {
1916 	struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn);
1917 
1918 	if (cbk && cbk->is_driver_unloading)
1919 		return cbk->is_driver_unloading(cbk->context);
1920 
1921 	return false;
1922 }
1923 
1924 /**
1925  * hif_is_load_or_unload_in_progress() - API to query upper layers if
1926  * load/unload in progress
1927  * @scn: HIF Context
1928  *
1929  * Return: True/False
1930  */
1931 bool hif_is_load_or_unload_in_progress(struct hif_softc *scn)
1932 {
1933 	struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn);
1934 
1935 	if (cbk && cbk->is_load_unload_in_progress)
1936 		return cbk->is_load_unload_in_progress(cbk->context);
1937 
1938 	return false;
1939 }
1940 
1941 /**
1942  * hif_is_recovery_in_progress() - API to query upper layers if recovery in
1943  * progress
1944  * @scn: HIF Context
1945  *
1946  * Return: True/False
1947  */
1948 bool hif_is_recovery_in_progress(struct hif_softc *scn)
1949 {
1950 	struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn);
1951 
1952 	if (cbk && cbk->is_recovery_in_progress)
1953 		return cbk->is_recovery_in_progress(cbk->context);
1954 
1955 	return false;
1956 }
1957 
1958 #if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \
1959     defined(HIF_IPCI)
1960 
1961 /**
1962  * hif_update_pipe_callback() - API to register pipe specific callbacks
1963  * @osc: Opaque softc
1964  * @pipeid: pipe id
1965  * @callbacks: callbacks to register
1966  *
1967  * Return: void
1968  */
1969 
1970 void hif_update_pipe_callback(struct hif_opaque_softc *osc,
1971 					u_int8_t pipeid,
1972 					struct hif_msg_callbacks *callbacks)
1973 {
1974 	struct hif_softc *scn = HIF_GET_SOFTC(osc);
1975 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
1976 	struct HIF_CE_pipe_info *pipe_info;
1977 
1978 	QDF_BUG(pipeid < CE_COUNT_MAX);
1979 
1980 	hif_debug("pipeid: %d", pipeid);
1981 
1982 	pipe_info = &hif_state->pipe_info[pipeid];
1983 
1984 	qdf_mem_copy(&pipe_info->pipe_callbacks,
1985 			callbacks, sizeof(pipe_info->pipe_callbacks));
1986 }
1987 qdf_export_symbol(hif_update_pipe_callback);
1988 
1989 /**
1990  * hif_is_target_ready() - API to query if target is in ready state
1991  * progress
1992  * @scn: HIF Context
1993  *
1994  * Return: True/False
1995  */
1996 bool hif_is_target_ready(struct hif_softc *scn)
1997 {
1998 	struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn);
1999 
2000 	if (cbk && cbk->is_target_ready)
2001 		return cbk->is_target_ready(cbk->context);
2002 	/*
2003 	 * if callback is not registered then there is no way to determine
2004 	 * if target is ready. In-such case return true to indicate that
2005 	 * target is ready.
2006 	 */
2007 	return true;
2008 }
2009 qdf_export_symbol(hif_is_target_ready);
2010 
2011 int hif_get_bandwidth_level(struct hif_opaque_softc *hif_handle)
2012 {
2013 	struct hif_softc *scn = HIF_GET_SOFTC(hif_handle);
2014 	struct hif_driver_state_callbacks *cbk = hif_get_callbacks_handle(scn);
2015 
2016 	if (cbk && cbk->get_bandwidth_level)
2017 		return cbk->get_bandwidth_level(cbk->context);
2018 
2019 	return 0;
2020 }
2021 
2022 qdf_export_symbol(hif_get_bandwidth_level);
2023 
2024 #ifdef DP_MEM_PRE_ALLOC
2025 void *hif_mem_alloc_consistent_unaligned(struct hif_softc *scn,
2026 					 qdf_size_t size,
2027 					 qdf_dma_addr_t *paddr,
2028 					 uint32_t ring_type,
2029 					 uint8_t *is_mem_prealloc)
2030 {
2031 	void *vaddr = NULL;
2032 	struct hif_driver_state_callbacks *cbk =
2033 				hif_get_callbacks_handle(scn);
2034 
2035 	*is_mem_prealloc = false;
2036 	if (cbk && cbk->prealloc_get_consistent_mem_unaligned) {
2037 		vaddr = cbk->prealloc_get_consistent_mem_unaligned(size,
2038 								   paddr,
2039 								   ring_type);
2040 		if (vaddr) {
2041 			*is_mem_prealloc = true;
2042 			goto end;
2043 		}
2044 	}
2045 
2046 	vaddr = qdf_mem_alloc_consistent(scn->qdf_dev,
2047 					 scn->qdf_dev->dev,
2048 					 size,
2049 					 paddr);
2050 end:
2051 	dp_info("%s va_unaligned %pK pa_unaligned %pK size %d ring_type %d",
2052 		*is_mem_prealloc ? "pre-alloc" : "dynamic-alloc", vaddr,
2053 		(void *)*paddr, (int)size, ring_type);
2054 
2055 	return vaddr;
2056 }
2057 
2058 void hif_mem_free_consistent_unaligned(struct hif_softc *scn,
2059 				       qdf_size_t size,
2060 				       void *vaddr,
2061 				       qdf_dma_addr_t paddr,
2062 				       qdf_dma_context_t memctx,
2063 				       uint8_t is_mem_prealloc)
2064 {
2065 	struct hif_driver_state_callbacks *cbk =
2066 				hif_get_callbacks_handle(scn);
2067 
2068 	if (is_mem_prealloc) {
2069 		if (cbk && cbk->prealloc_put_consistent_mem_unaligned) {
2070 			cbk->prealloc_put_consistent_mem_unaligned(vaddr);
2071 		} else {
2072 			dp_warn("dp_prealloc_put_consistent_unligned NULL");
2073 			QDF_BUG(0);
2074 		}
2075 	} else {
2076 		qdf_mem_free_consistent(scn->qdf_dev, scn->qdf_dev->dev,
2077 					size, vaddr, paddr, memctx);
2078 	}
2079 }
2080 #endif
2081 
2082 /**
2083  * hif_batch_send() - API to access hif specific function
2084  * ce_batch_send.
2085  * @osc: HIF Context
2086  * @msdu : list of msdus to be sent
2087  * @transfer_id : transfer id
2088  * @len : donwloaded length
2089  *
2090  * Return: list of msds not sent
2091  */
2092 qdf_nbuf_t hif_batch_send(struct hif_opaque_softc *osc, qdf_nbuf_t msdu,
2093 		uint32_t transfer_id, u_int32_t len, uint32_t sendhead)
2094 {
2095 	void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE);
2096 
2097 	if (!ce_tx_hdl)
2098 		return NULL;
2099 
2100 	return ce_batch_send((struct CE_handle *)ce_tx_hdl, msdu, transfer_id,
2101 			len, sendhead);
2102 }
2103 qdf_export_symbol(hif_batch_send);
2104 
2105 /**
2106  * hif_update_tx_ring() - API to access hif specific function
2107  * ce_update_tx_ring.
2108  * @osc: HIF Context
2109  * @num_htt_cmpls : number of htt compl received.
2110  *
2111  * Return: void
2112  */
2113 void hif_update_tx_ring(struct hif_opaque_softc *osc, u_int32_t num_htt_cmpls)
2114 {
2115 	void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE);
2116 
2117 	ce_update_tx_ring(ce_tx_hdl, num_htt_cmpls);
2118 }
2119 qdf_export_symbol(hif_update_tx_ring);
2120 
2121 
2122 /**
2123  * hif_send_single() - API to access hif specific function
2124  * ce_send_single.
2125  * @osc: HIF Context
2126  * @msdu : msdu to be sent
2127  * @transfer_id: transfer id
2128  * @len : downloaded length
2129  *
2130  * Return: msdu sent status
2131  */
2132 QDF_STATUS hif_send_single(struct hif_opaque_softc *osc, qdf_nbuf_t msdu,
2133 			   uint32_t transfer_id, u_int32_t len)
2134 {
2135 	void *ce_tx_hdl = hif_get_ce_handle(osc, CE_HTT_TX_CE);
2136 
2137 	if (!ce_tx_hdl)
2138 		return QDF_STATUS_E_NULL_VALUE;
2139 
2140 	return ce_send_single((struct CE_handle *)ce_tx_hdl, msdu, transfer_id,
2141 			len);
2142 }
2143 qdf_export_symbol(hif_send_single);
2144 #endif
2145 
2146 /**
2147  * hif_reg_write() - API to access hif specific function
2148  * hif_write32_mb.
2149  * @hif_ctx : HIF Context
2150  * @offset : offset on which value has to be written
2151  * @value : value to be written
2152  *
2153  * Return: None
2154  */
2155 void hif_reg_write(struct hif_opaque_softc *hif_ctx, uint32_t offset,
2156 		uint32_t value)
2157 {
2158 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
2159 
2160 	hif_write32_mb(scn, scn->mem + offset, value);
2161 
2162 }
2163 qdf_export_symbol(hif_reg_write);
2164 
2165 /**
2166  * hif_reg_read() - API to access hif specific function
2167  * hif_read32_mb.
2168  * @hif_ctx : HIF Context
2169  * @offset : offset from which value has to be read
2170  *
2171  * Return: Read value
2172  */
2173 uint32_t hif_reg_read(struct hif_opaque_softc *hif_ctx, uint32_t offset)
2174 {
2175 
2176 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
2177 
2178 	return hif_read32_mb(scn, scn->mem + offset);
2179 }
2180 qdf_export_symbol(hif_reg_read);
2181 
2182 /**
2183  * hif_ramdump_handler(): generic ramdump handler
2184  * @scn: struct hif_opaque_softc
2185  *
2186  * Return: None
2187  */
2188 void hif_ramdump_handler(struct hif_opaque_softc *scn)
2189 {
2190 	if (hif_get_bus_type(scn) == QDF_BUS_TYPE_USB)
2191 		hif_usb_ramdump_handler(scn);
2192 }
2193 
2194 hif_pm_wake_irq_type hif_pm_get_wake_irq_type(struct hif_opaque_softc *hif_ctx)
2195 {
2196 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
2197 
2198 	return scn->wake_irq_type;
2199 }
2200 
2201 irqreturn_t hif_wake_interrupt_handler(int irq, void *context)
2202 {
2203 	struct hif_softc *scn = context;
2204 
2205 	hif_info("wake interrupt received on irq %d", irq);
2206 
2207 	hif_rtpm_set_monitor_wake_intr(0);
2208 	hif_rtpm_request_resume();
2209 
2210 	if (scn->initial_wakeup_cb)
2211 		scn->initial_wakeup_cb(scn->initial_wakeup_priv);
2212 
2213 	if (hif_is_ut_suspended(scn))
2214 		hif_ut_fw_resume(scn);
2215 
2216 	qdf_pm_system_wakeup();
2217 
2218 	return IRQ_HANDLED;
2219 }
2220 
2221 void hif_set_initial_wakeup_cb(struct hif_opaque_softc *hif_ctx,
2222 			       void (*callback)(void *),
2223 			       void *priv)
2224 {
2225 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
2226 
2227 	scn->initial_wakeup_cb = callback;
2228 	scn->initial_wakeup_priv = priv;
2229 }
2230 
2231 void hif_set_ce_service_max_yield_time(struct hif_opaque_softc *hif,
2232 				       uint32_t ce_service_max_yield_time)
2233 {
2234 	struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif);
2235 
2236 	hif_ctx->ce_service_max_yield_time =
2237 		ce_service_max_yield_time * 1000;
2238 }
2239 
2240 unsigned long long
2241 hif_get_ce_service_max_yield_time(struct hif_opaque_softc *hif)
2242 {
2243 	struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif);
2244 
2245 	return hif_ctx->ce_service_max_yield_time;
2246 }
2247 
2248 void hif_set_ce_service_max_rx_ind_flush(struct hif_opaque_softc *hif,
2249 				       uint8_t ce_service_max_rx_ind_flush)
2250 {
2251 	struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif);
2252 
2253 	if (ce_service_max_rx_ind_flush == 0 ||
2254 	    ce_service_max_rx_ind_flush > MSG_FLUSH_NUM)
2255 		hif_ctx->ce_service_max_rx_ind_flush = MSG_FLUSH_NUM;
2256 	else
2257 		hif_ctx->ce_service_max_rx_ind_flush =
2258 						ce_service_max_rx_ind_flush;
2259 }
2260 
2261 #ifdef SYSTEM_PM_CHECK
2262 void __hif_system_pm_set_state(struct hif_opaque_softc *hif,
2263 			       enum hif_system_pm_state state)
2264 {
2265 	struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif);
2266 
2267 	qdf_atomic_set(&hif_ctx->sys_pm_state, state);
2268 }
2269 
2270 int32_t hif_system_pm_get_state(struct hif_opaque_softc *hif)
2271 {
2272 	struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif);
2273 
2274 	return qdf_atomic_read(&hif_ctx->sys_pm_state);
2275 }
2276 
2277 int hif_system_pm_state_check(struct hif_opaque_softc *hif)
2278 {
2279 	struct hif_softc *hif_ctx = HIF_GET_SOFTC(hif);
2280 	int32_t sys_pm_state;
2281 
2282 	if (!hif_ctx) {
2283 		hif_err("hif context is null");
2284 		return -EFAULT;
2285 	}
2286 
2287 	sys_pm_state = qdf_atomic_read(&hif_ctx->sys_pm_state);
2288 	if (sys_pm_state == HIF_SYSTEM_PM_STATE_BUS_SUSPENDING ||
2289 	    sys_pm_state == HIF_SYSTEM_PM_STATE_BUS_SUSPENDED) {
2290 		hif_info("Triggering system wakeup");
2291 		qdf_pm_system_wakeup();
2292 		return -EAGAIN;
2293 	}
2294 
2295 	return 0;
2296 }
2297 #endif
2298