xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/ipcie/if_ipci.c (revision 45a38684b07295822dc8eba39e293408f203eec8)
1 /*
2  * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7 
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <linux/slab.h>
18 #include <linux/interrupt.h>
19 #include <linux/if_arp.h>
20 #ifdef CONFIG_PCI_MSM
21 #include <linux/msm_pcie.h>
22 #endif
23 #include "hif_io32.h"
24 #include "if_ipci.h"
25 #include "hif.h"
26 #include "target_type.h"
27 #include "hif_main.h"
28 #include "ce_main.h"
29 #include "ce_api.h"
30 #include "ce_internal.h"
31 #include "ce_reg.h"
32 #include "ce_bmi.h"
33 #include "regtable.h"
34 #include "hif_hw_version.h"
35 #include <linux/debugfs.h>
36 #include <linux/seq_file.h>
37 #include "qdf_status.h"
38 #include "qdf_atomic.h"
39 #include "pld_common.h"
40 #include "mp_dev.h"
41 #include "hif_debug.h"
42 
43 #include "ce_tasklet.h"
44 #include "targaddrs.h"
45 #include "hif_exec.h"
46 
47 #include "ipci_api.h"
48 
49 #ifdef FEATURE_RUNTIME_PM
50 inline struct hif_runtime_pm_ctx *hif_ipci_get_rpm_ctx(struct hif_softc *scn)
51 {
52 	struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(scn);
53 
54 	return &sc->rpm_ctx;
55 }
56 
57 inline struct device *hif_ipci_get_dev(struct hif_softc *scn)
58 {
59 	struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(scn);
60 
61 	return sc->dev;
62 }
63 #endif
64 
65 void hif_ipci_enable_power_management(struct hif_softc *hif_sc,
66 				      bool is_packet_log_enabled)
67 {
68 	hif_pm_runtime_start(hif_sc);
69 }
70 
71 void hif_ipci_disable_power_management(struct hif_softc *hif_ctx)
72 {
73 	hif_pm_runtime_stop(hif_ctx);
74 }
75 
76 void hif_ipci_display_stats(struct hif_softc *hif_ctx)
77 {
78 	hif_display_ce_stats(hif_ctx);
79 }
80 
81 void hif_ipci_clear_stats(struct hif_softc *hif_ctx)
82 {
83 	struct hif_ipci_softc *ipci_ctx = HIF_GET_IPCI_SOFTC(hif_ctx);
84 
85 	if (!ipci_ctx) {
86 		HIF_ERROR("%s, hif_ctx null", __func__);
87 		return;
88 	}
89 	hif_clear_ce_stats(&ipci_ctx->ce_sc);
90 }
91 
92 QDF_STATUS hif_ipci_open(struct hif_softc *hif_ctx, enum qdf_bus_type bus_type)
93 {
94 	struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(hif_ctx);
95 
96 	hif_ctx->bus_type = bus_type;
97 	hif_pm_runtime_open(hif_ctx);
98 
99 	qdf_spinlock_create(&sc->irq_lock);
100 
101 	return hif_ce_open(hif_ctx);
102 }
103 
104 /**
105  * hif_ce_msi_map_ce_to_irq() - map CE to IRQ
106  * @scn: hif context
107  * @ce_id: CE Id
108  *
109  * Return: IRQ number
110  */
111 static int hif_ce_msi_map_ce_to_irq(struct hif_softc *scn, int ce_id)
112 {
113 	struct hif_ipci_softc *ipci_scn = HIF_GET_IPCI_SOFTC(scn);
114 
115 	return ipci_scn->ce_msi_irq_num[ce_id];
116 }
117 
118 int hif_ipci_bus_configure(struct hif_softc *hif_sc)
119 {
120 	int status = 0;
121 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(hif_sc);
122 	uint8_t wake_ce_id;
123 
124 	hif_ce_prepare_config(hif_sc);
125 
126 	/* initialize sleep state adjust variables */
127 	hif_state->sleep_timer_init = true;
128 	hif_state->keep_awake_count = 0;
129 	hif_state->fake_sleep = false;
130 	hif_state->sleep_ticks = 0;
131 
132 	status = hif_wlan_enable(hif_sc);
133 	if (status) {
134 		HIF_ERROR("%s: hif_wlan_enable error = %d",
135 			  __func__, status);
136 		goto timer_free;
137 	}
138 
139 	A_TARGET_ACCESS_LIKELY(hif_sc);
140 
141 	status = hif_config_ce(hif_sc);
142 	if (status)
143 		goto disable_wlan;
144 
145 	status = hif_get_wake_ce_id(hif_sc, &wake_ce_id);
146 	if (status)
147 		goto unconfig_ce;
148 
149 	status = hif_configure_irq(hif_sc);
150 	if (status < 0)
151 		goto unconfig_ce;
152 
153 	hif_sc->wake_irq = hif_ce_msi_map_ce_to_irq(hif_sc, wake_ce_id);
154 
155 	HIF_INFO("expecting wake from ce %d, irq %d",
156 		 wake_ce_id, hif_sc->wake_irq);
157 
158 	A_TARGET_ACCESS_UNLIKELY(hif_sc);
159 
160 	return status;
161 
162 unconfig_ce:
163 	hif_unconfig_ce(hif_sc);
164 disable_wlan:
165 	A_TARGET_ACCESS_UNLIKELY(hif_sc);
166 	hif_wlan_disable(hif_sc);
167 
168 timer_free:
169 	qdf_timer_stop(&hif_state->sleep_timer);
170 	qdf_timer_free(&hif_state->sleep_timer);
171 	hif_state->sleep_timer_init = false;
172 
173 	HIF_ERROR("%s: failed, status = %d", __func__, status);
174 	return status;
175 }
176 
177 void hif_ipci_close(struct hif_softc *hif_sc)
178 {
179 	hif_pm_runtime_close(hif_sc);
180 	hif_ce_close(hif_sc);
181 }
182 
183 /**
184  * hif_ce_srng_msi_free_irq(): free CE msi IRQ
185  * @scn: struct hif_softc
186  *
187  * Return: ErrorNo
188  */
189 static int hif_ce_srng_msi_free_irq(struct hif_softc *scn)
190 {
191 	int ret;
192 	int ce_id, irq;
193 	uint32_t msi_data_start;
194 	uint32_t msi_data_count;
195 	uint32_t msi_irq_start;
196 	struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn);
197 
198 	ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
199 					  &msi_data_count, &msi_data_start,
200 					  &msi_irq_start);
201 	if (ret)
202 		return ret;
203 
204 	/* needs to match the ce_id -> irq data mapping
205 	 * used in the srng parameter configuration
206 	 */
207 	for (ce_id = 0; ce_id < scn->ce_count; ce_id++) {
208 		unsigned int msi_data;
209 
210 		if (!ce_sc->tasklets[ce_id].inited)
211 			continue;
212 
213 		msi_data = (ce_id % msi_data_count) + msi_irq_start;
214 		irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data);
215 
216 		hif_debug("%s: (ce_id %d, msi_data %d, irq %d)", __func__,
217 			  ce_id, msi_data, irq);
218 
219 		pfrm_free_irq(scn->qdf_dev->dev, irq, &ce_sc->tasklets[ce_id]);
220 	}
221 
222 	return ret;
223 }
224 
225 /**
226  * hif_ipci_deconfigure_grp_irq(): deconfigure HW block IRQ
227  * @scn: struct hif_softc
228  *
229  * Return: none
230  */
231 static void hif_ipci_deconfigure_grp_irq(struct hif_softc *scn)
232 {
233 	int i, j, irq;
234 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
235 	struct hif_exec_context *hif_ext_group;
236 
237 	for (i = 0; i < hif_state->hif_num_extgroup; i++) {
238 		hif_ext_group = hif_state->hif_ext_group[i];
239 		if (hif_ext_group->irq_requested) {
240 			hif_ext_group->irq_requested = false;
241 			for (j = 0; j < hif_ext_group->numirq; j++) {
242 				irq = hif_ext_group->os_irq[j];
243 				pfrm_free_irq(scn->qdf_dev->dev,
244 					      irq, hif_ext_group);
245 			}
246 			hif_ext_group->numirq = 0;
247 		}
248 	}
249 }
250 
251 void hif_ipci_nointrs(struct hif_softc *scn)
252 {
253 	int ret;
254 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
255 
256 	ce_unregister_irq(hif_state, CE_ALL_BITMAP);
257 
258 	if (scn->request_irq_done == false)
259 		return;
260 
261 	hif_ipci_deconfigure_grp_irq(scn);
262 
263 	ret = hif_ce_srng_msi_free_irq(scn);
264 
265 	scn->request_irq_done = false;
266 }
267 
268 void hif_ipci_disable_bus(struct hif_softc *scn)
269 {
270 	struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(scn);
271 	void __iomem *mem;
272 
273 	/* Attach did not succeed, all resources have been
274 	 * freed in error handler
275 	 */
276 	if (!sc)
277 		return;
278 
279 	mem = (void __iomem *)sc->mem;
280 	if (mem) {
281 		hif_dump_pipe_debug_count(scn);
282 		if (scn->athdiag_procfs_inited) {
283 			athdiag_procfs_remove();
284 			scn->athdiag_procfs_inited = false;
285 		}
286 		scn->mem = NULL;
287 	}
288 	HIF_INFO("%s: X", __func__);
289 }
290 
291 #if defined(CONFIG_PCI_MSM)
292 void hif_ipci_prevent_linkdown(struct hif_softc *scn, bool flag)
293 {
294 	int errno;
295 
296 	HIF_INFO("wlan: %s pcie power collapse", flag ? "disable" : "enable");
297 	hif_runtime_prevent_linkdown(scn, flag);
298 
299 	errno = pld_wlan_pm_control(scn->qdf_dev->dev, flag);
300 	if (errno)
301 		HIF_ERROR("%s: Failed pld_wlan_pm_control; errno %d",
302 			  __func__, errno);
303 }
304 #else
305 void hif_ipci_prevent_linkdown(struct hif_softc *scn, bool flag)
306 {
307 	HIF_INFO("wlan: %s pcie power collapse", (flag ? "disable" : "enable"));
308 	hif_runtime_prevent_linkdown(scn, flag);
309 }
310 #endif
311 
312 int hif_ipci_bus_suspend(struct hif_softc *scn)
313 {
314 	return hif_apps_enable_irq_wake(GET_HIF_OPAQUE_HDL(scn));
315 }
316 
317 int hif_ipci_bus_resume(struct hif_softc *scn)
318 {
319 	return hif_apps_disable_irq_wake(GET_HIF_OPAQUE_HDL(scn));
320 }
321 
322 int hif_ipci_bus_suspend_noirq(struct hif_softc *scn)
323 {
324 	QDF_STATUS ret;
325 
326 	ret = hif_try_complete_tasks(scn);
327 	if (QDF_IS_STATUS_ERROR(ret))
328 		return -EBUSY;
329 
330 	return 0;
331 }
332 
333 int hif_ipci_bus_resume_noirq(struct hif_softc *scn)
334 {
335 	return 0;
336 }
337 
338 void hif_ipci_disable_isr(struct hif_softc *scn)
339 {
340 	struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(scn);
341 
342 	hif_exec_kill(&scn->osc);
343 	hif_nointrs(scn);
344 	/* Cancel the pending tasklet */
345 	ce_tasklet_kill(scn);
346 	tasklet_kill(&sc->intr_tq);
347 	qdf_atomic_set(&scn->active_tasklet_cnt, 0);
348 	qdf_atomic_set(&scn->active_grp_tasklet_cnt, 0);
349 }
350 
351 int hif_ipci_dump_registers(struct hif_softc *hif_ctx)
352 {
353 	int status;
354 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
355 
356 	status = hif_dump_ce_registers(scn);
357 
358 	if (status)
359 		HIF_ERROR("%s: Dump CE Registers Failed", __func__);
360 
361 	return 0;
362 }
363 
364 /**
365  * hif_ce_interrupt_handler() - interrupt handler for copy engine
366  * @irq: irq number
367  * @context: tasklet context
368  *
369  * Return: irqreturn_t
370  */
371 static irqreturn_t hif_ce_interrupt_handler(int irq, void *context)
372 {
373 	struct ce_tasklet_entry *tasklet_entry = context;
374 
375 	hif_pm_runtime_check_and_request_resume(
376 			GET_HIF_OPAQUE_HDL(tasklet_entry->hif_ce_state));
377 	return ce_dispatch_interrupt(tasklet_entry->ce_id, tasklet_entry);
378 }
379 
380 extern const char *ce_name[];
381 
382 /* hif_ce_srng_msi_irq_disable() - disable the irq for msi
383  * @hif_sc: hif context
384  * @ce_id: which ce to disable copy complete interrupts for
385  *
386  * @Return: none
387  */
388 static void hif_ce_srng_msi_irq_disable(struct hif_softc *hif_sc, int ce_id)
389 {
390 	pfrm_disable_irq_nosync(hif_sc->qdf_dev->dev,
391 				hif_ce_msi_map_ce_to_irq(hif_sc, ce_id));
392 
393 }
394 
395 /* hif_ce_srng_msi_irq_enable() - enable the irq for msi
396  * @hif_sc: hif context
397  * @ce_id: which ce to enable copy complete interrupts for
398  *
399  * @Return: none
400  */
401 static void hif_ce_srng_msi_irq_enable(struct hif_softc *hif_sc, int ce_id)
402 {
403 	pfrm_enable_irq(hif_sc->qdf_dev->dev,
404 			hif_ce_msi_map_ce_to_irq(hif_sc, ce_id));
405 
406 }
407 
408 /* hif_ce_msi_configure_irq() - configure the irq
409  * @scn: hif context
410  *
411  * @Return: none
412  */
413 static int hif_ce_msi_configure_irq(struct hif_softc *scn)
414 {
415 	int ret;
416 	int ce_id, irq;
417 	uint32_t msi_data_start;
418 	uint32_t msi_data_count;
419 	uint32_t msi_irq_start;
420 	struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn);
421 	struct hif_ipci_softc *ipci_sc = HIF_GET_IPCI_SOFTC(scn);
422 	uint8_t wake_ce_id;
423 
424 	ret = hif_get_wake_ce_id(scn, &wake_ce_id);
425 	if (ret)
426 		return ret;
427 
428 	/* do ce irq assignments */
429 	ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
430 					  &msi_data_count, &msi_data_start,
431 					  &msi_irq_start);
432 	if (ret)
433 		return ret;
434 
435 	scn->bus_ops.hif_irq_disable = &hif_ce_srng_msi_irq_disable;
436 	scn->bus_ops.hif_irq_enable = &hif_ce_srng_msi_irq_enable;
437 	scn->bus_ops.hif_map_ce_to_irq = &hif_ce_msi_map_ce_to_irq;
438 
439 	/* needs to match the ce_id -> irq data mapping
440 	 * used in the srng parameter configuration
441 	 */
442 	for (ce_id = 0; ce_id < scn->ce_count; ce_id++) {
443 		unsigned long irqflags = IRQF_SHARED;
444 		unsigned int msi_data = (ce_id % msi_data_count) +
445 			msi_irq_start;
446 		irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data);
447 		HIF_DBG("%s: (ce_id %d, msi_data %d, irq %d tasklet %pK)",
448 			__func__, ce_id, msi_data, irq,
449 			&ce_sc->tasklets[ce_id]);
450 
451 		/* implies the ce is also initialized */
452 		if (!ce_sc->tasklets[ce_id].inited)
453 			continue;
454 
455 		ipci_sc->ce_msi_irq_num[ce_id] = irq;
456 		ret = pfrm_request_irq(scn->qdf_dev->dev,
457 				       irq, hif_ce_interrupt_handler,
458 				       irqflags,
459 				       ce_name[ce_id],
460 				       &ce_sc->tasklets[ce_id]);
461 		if (ret)
462 			goto free_irq;
463 	}
464 
465 	return ret;
466 
467 free_irq:
468 	/* the request_irq for the last ce_id failed so skip it. */
469 	while (ce_id > 0 && ce_id < scn->ce_count) {
470 		unsigned int msi_data;
471 
472 		ce_id--;
473 		msi_data = (ce_id % msi_data_count) + msi_irq_start;
474 		irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data);
475 		pfrm_free_irq(scn->qdf_dev->dev, irq, &ce_sc->tasklets[ce_id]);
476 	}
477 
478 	return ret;
479 }
480 
481 /**
482  * hif_exec_grp_irq_disable() - disable the irq for group
483  * @hif_ext_group: hif exec context
484  *
485  * Return: none
486  */
487 static void hif_exec_grp_irq_disable(struct hif_exec_context *hif_ext_group)
488 {
489 	int i;
490 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ext_group->hif);
491 
492 	for (i = 0; i < hif_ext_group->numirq; i++)
493 		pfrm_disable_irq_nosync(scn->qdf_dev->dev,
494 					hif_ext_group->os_irq[i]);
495 }
496 
497 /**
498  * hif_exec_grp_irq_enable() - enable the irq for group
499  * @hif_ext_group: hif exec context
500  *
501  * Return: none
502  */
503 static void hif_exec_grp_irq_enable(struct hif_exec_context *hif_ext_group)
504 {
505 	int i;
506 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ext_group->hif);
507 
508 	for (i = 0; i < hif_ext_group->numirq; i++)
509 		pfrm_enable_irq(scn->qdf_dev->dev, hif_ext_group->os_irq[i]);
510 }
511 
512 const char *hif_ipci_get_irq_name(int irq_no)
513 {
514 	return "pci-dummy";
515 }
516 
517 int hif_ipci_configure_grp_irq(struct hif_softc *scn,
518 			       struct hif_exec_context *hif_ext_group)
519 {
520 	int ret = 0;
521 	int irq = 0;
522 	int j;
523 
524 	hif_ext_group->irq_enable = &hif_exec_grp_irq_enable;
525 	hif_ext_group->irq_disable = &hif_exec_grp_irq_disable;
526 	hif_ext_group->irq_name = &hif_ipci_get_irq_name;
527 	hif_ext_group->work_complete = &hif_dummy_grp_done;
528 
529 	for (j = 0; j < hif_ext_group->numirq; j++) {
530 		irq = hif_ext_group->irq[j];
531 
532 		hif_info("request_irq = %d for grp %d",
533 			 irq, hif_ext_group->grp_id);
534 		ret = pfrm_request_irq(scn->qdf_dev->dev, irq,
535 				       hif_ext_group_interrupt_handler,
536 				       IRQF_SHARED | IRQF_NO_SUSPEND,
537 				       "wlan_EXT_GRP",
538 				       hif_ext_group);
539 		if (ret) {
540 			HIF_ERROR("%s: request_irq failed ret = %d",
541 				  __func__, ret);
542 			return -EFAULT;
543 		}
544 		hif_ext_group->os_irq[j] = irq;
545 	}
546 	hif_ext_group->irq_requested = true;
547 	return 0;
548 }
549 
550 int hif_configure_irq(struct hif_softc *scn)
551 {
552 	int ret = 0;
553 
554 	HIF_TRACE("%s: E", __func__);
555 
556 	if (hif_is_polled_mode_enabled(GET_HIF_OPAQUE_HDL(scn))) {
557 		scn->request_irq_done = false;
558 		return 0;
559 	}
560 
561 	ret = hif_ce_msi_configure_irq(scn);
562 	if (ret == 0)
563 		goto end;
564 
565 	if (ret < 0) {
566 		HIF_ERROR("%s: hif_ipci_configure_irq error = %d",
567 			  __func__, ret);
568 		return ret;
569 	}
570 end:
571 	scn->request_irq_done = true;
572 	return 0;
573 }
574 
575 /**
576  * hif_ipci_get_soc_info_pld() - get soc info for ipcie bus from pld target
577  * @sc: ipci context
578  * @dev: device structure
579  *
580  * Return: none
581  */
582 static void hif_ipci_get_soc_info_pld(struct hif_ipci_softc *sc,
583 				      struct device *dev)
584 {
585 	struct pld_soc_info info;
586 
587 	pld_get_soc_info(dev, &info);
588 	sc->mem = info.v_addr;
589 	sc->ce_sc.ol_sc.mem    = info.v_addr;
590 	sc->ce_sc.ol_sc.mem_pa = info.p_addr;
591 }
592 
593 /**
594  * hif_ipci_get_soc_info_nopld() - get soc info for ipcie bus for non pld target
595  * @sc: ipci context
596  * @dev: device structure
597  *
598  * Return: none
599  */
600 static void hif_ipci_get_soc_info_nopld(struct hif_ipci_softc *sc,
601 					struct device *dev)
602 {}
603 
604 /**
605  * hif_is_pld_based_target() - verify if the target is pld based
606  * @sc: ipci context
607  * @device_id: device id
608  *
609  * Return: none
610  */
611 static bool hif_is_pld_based_target(struct hif_ipci_softc *sc,
612 				    int device_id)
613 {
614 	if (!pld_have_platform_driver_support(sc->dev))
615 		return false;
616 
617 	switch (device_id) {
618 #ifdef QCA_WIFI_QCA6750
619 	case QCA6750_DEVICE_ID:
620 #endif
621 		return true;
622 	}
623 	return false;
624 }
625 
626 /**
627  * hif_ipci_init_deinit_ops_attach() - attach ops for ipci
628  * @sc: ipci context
629  * @device_id: device id
630  *
631  * Return: none
632  */
633 static void hif_ipci_init_deinit_ops_attach(struct hif_ipci_softc *sc,
634 					    int device_id)
635 {
636 	if (hif_is_pld_based_target(sc, device_id))
637 		sc->hif_ipci_get_soc_info = hif_ipci_get_soc_info_pld;
638 	else
639 		sc->hif_ipci_get_soc_info = hif_ipci_get_soc_info_nopld;
640 }
641 
642 QDF_STATUS hif_ipci_enable_bus(struct hif_softc *ol_sc,
643 			       struct device *dev, void *bdev,
644 			       const struct hif_bus_id *bid,
645 			       enum hif_enable_type type)
646 {
647 	int ret = 0;
648 	uint32_t hif_type, target_type;
649 	struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(ol_sc);
650 	struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(ol_sc);
651 	uint16_t revision_id = 0;
652 	struct hif_target_info *tgt_info;
653 	int device_id = QCA6750_DEVICE_ID;
654 
655 	if (!ol_sc) {
656 		HIF_ERROR("%s: hif_ctx is NULL", __func__);
657 		return QDF_STATUS_E_NOMEM;
658 	}
659 
660 	ret = qdf_set_dma_coherent_mask(dev,
661 					DMA_COHERENT_MASK_DEFAULT);
662 	if (ret) {
663 		HIF_ERROR("%s: failed to set dma mask error = %d",
664 			  __func__, ret);
665 		return qdf_status_from_os_return(ret);
666 	}
667 
668 	sc->dev = dev;
669 	tgt_info = hif_get_target_info_handle(hif_hdl);
670 	hif_ipci_init_deinit_ops_attach(sc, device_id);
671 	sc->hif_ipci_get_soc_info(sc, dev);
672 	HIF_TRACE("%s: hif_enable_pci done", __func__);
673 
674 	ret = hif_get_device_type(device_id, revision_id,
675 				  &hif_type, &target_type);
676 	if (ret < 0) {
677 		HIF_ERROR("%s: invalid device id/revision_id", __func__);
678 		return QDF_STATUS_E_ABORTED;
679 	}
680 	HIF_TRACE("%s: hif_type = 0x%x, target_type = 0x%x",
681 		  __func__, hif_type, target_type);
682 
683 	hif_register_tbl_attach(ol_sc, hif_type);
684 	hif_target_register_tbl_attach(ol_sc, target_type);
685 	sc->use_register_windowing = false;
686 	tgt_info->target_type = target_type;
687 
688 	if (!ol_sc->mem_pa) {
689 		HIF_ERROR("%s: ERROR - BAR0 uninitialized", __func__);
690 		return QDF_STATUS_E_ABORTED;
691 	}
692 
693 	return QDF_STATUS_SUCCESS;
694 }
695 
696 bool hif_ipci_needs_bmi(struct hif_softc *scn)
697 {
698 	return !ce_srng_based(scn);
699 }
700 
701 #ifdef FORCE_WAKE
702 int hif_force_wake_request(struct hif_opaque_softc *hif_handle)
703 {
704 	uint32_t timeout = 0;
705 	struct hif_softc *scn = (struct hif_softc *)hif_handle;
706 	struct hif_ipci_softc *ipci_scn = HIF_GET_IPCI_SOFTC(scn);
707 
708 	if (pld_force_wake_request(scn->qdf_dev->dev)) {
709 		hif_err("force wake request send failed");
710 		return -EINVAL;
711 	}
712 
713 	HIF_STATS_INC(ipci_scn, mhi_force_wake_request_vote, 1);
714 	while (!pld_is_device_awake(scn->qdf_dev->dev) &&
715 	       timeout <= FORCE_WAKE_DELAY_TIMEOUT_MS) {
716 		qdf_mdelay(FORCE_WAKE_DELAY_MS);
717 		timeout += FORCE_WAKE_DELAY_MS;
718 	}
719 
720 	if (pld_is_device_awake(scn->qdf_dev->dev) <= 0) {
721 		hif_err("Unable to wake up mhi");
722 		HIF_STATS_INC(ipci_scn, mhi_force_wake_failure, 1);
723 		return -EINVAL;
724 	}
725 	HIF_STATS_INC(ipci_scn, mhi_force_wake_success, 1);
726 
727 	HIF_STATS_INC(ipci_scn, soc_force_wake_success, 1);
728 
729 	return 0;
730 }
731 
732 int hif_force_wake_release(struct hif_opaque_softc *hif_handle)
733 {
734 	int ret;
735 	struct hif_softc *scn = (struct hif_softc *)hif_handle;
736 	struct hif_ipci_softc *ipci_scn = HIF_GET_IPCI_SOFTC(scn);
737 
738 	ret = pld_force_wake_release(scn->qdf_dev->dev);
739 	if (ret) {
740 		hif_err("force wake release failure");
741 		HIF_STATS_INC(ipci_scn, mhi_force_wake_release_failure, 1);
742 		return ret;
743 	}
744 
745 	HIF_STATS_INC(ipci_scn, mhi_force_wake_release_success, 1);
746 
747 	HIF_STATS_INC(ipci_scn, soc_force_wake_release_success, 1);
748 	return 0;
749 }
750 
751 void hif_print_ipci_stats(struct hif_ipci_softc *ipci_handle)
752 {
753 	hif_debug("mhi_force_wake_request_vote: %d",
754 		  ipci_handle->stats.mhi_force_wake_request_vote);
755 	hif_debug("mhi_force_wake_failure: %d",
756 		  ipci_handle->stats.mhi_force_wake_failure);
757 	hif_debug("mhi_force_wake_success: %d",
758 		  ipci_handle->stats.mhi_force_wake_success);
759 	hif_debug("soc_force_wake_register_write_success: %d",
760 		  ipci_handle->stats.soc_force_wake_register_write_success);
761 	hif_debug("soc_force_wake_failure: %d",
762 		  ipci_handle->stats.soc_force_wake_failure);
763 	hif_debug("soc_force_wake_success: %d",
764 		  ipci_handle->stats.soc_force_wake_success);
765 	hif_debug("mhi_force_wake_release_failure: %d",
766 		  ipci_handle->stats.mhi_force_wake_release_failure);
767 	hif_debug("mhi_force_wake_release_success: %d",
768 		  ipci_handle->stats.mhi_force_wake_release_success);
769 	hif_debug("oc_force_wake_release_success: %d",
770 		  ipci_handle->stats.soc_force_wake_release_success);
771 }
772 #endif /* FORCE_WAKE */
773