xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/ipcie/if_ipci.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
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_err("hif_ctx null");
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_err("hif_wlan_enable error = %d", status);
135 		goto timer_free;
136 	}
137 
138 	A_TARGET_ACCESS_LIKELY(hif_sc);
139 
140 	status = hif_config_ce(hif_sc);
141 	if (status)
142 		goto disable_wlan;
143 
144 	status = hif_get_wake_ce_id(hif_sc, &wake_ce_id);
145 	if (status)
146 		goto unconfig_ce;
147 
148 	status = hif_configure_irq(hif_sc);
149 	if (status < 0)
150 		goto unconfig_ce;
151 
152 	hif_sc->wake_irq = hif_ce_msi_map_ce_to_irq(hif_sc, wake_ce_id);
153 
154 	hif_info("expecting wake from ce %d, irq %d",
155 		 wake_ce_id, hif_sc->wake_irq);
156 
157 	A_TARGET_ACCESS_UNLIKELY(hif_sc);
158 
159 	return status;
160 
161 unconfig_ce:
162 	hif_unconfig_ce(hif_sc);
163 disable_wlan:
164 	A_TARGET_ACCESS_UNLIKELY(hif_sc);
165 	hif_wlan_disable(hif_sc);
166 
167 timer_free:
168 	qdf_timer_stop(&hif_state->sleep_timer);
169 	qdf_timer_free(&hif_state->sleep_timer);
170 	hif_state->sleep_timer_init = false;
171 
172 	hif_err("Failed, status = %d", status);
173 	return status;
174 }
175 
176 void hif_ipci_close(struct hif_softc *hif_sc)
177 {
178 	hif_pm_runtime_close(hif_sc);
179 	hif_ce_close(hif_sc);
180 }
181 
182 /**
183  * hif_ce_srng_msi_free_irq(): free CE msi IRQ
184  * @scn: struct hif_softc
185  *
186  * Return: ErrorNo
187  */
188 static int hif_ce_srng_msi_free_irq(struct hif_softc *scn)
189 {
190 	int ret;
191 	int ce_id, irq;
192 	uint32_t msi_data_start;
193 	uint32_t msi_data_count;
194 	uint32_t msi_irq_start;
195 	struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn);
196 
197 	ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
198 					  &msi_data_count, &msi_data_start,
199 					  &msi_irq_start);
200 	if (ret)
201 		return ret;
202 
203 	/* needs to match the ce_id -> irq data mapping
204 	 * used in the srng parameter configuration
205 	 */
206 	for (ce_id = 0; ce_id < scn->ce_count; ce_id++) {
207 		unsigned int msi_data;
208 
209 		if (!ce_sc->tasklets[ce_id].inited)
210 			continue;
211 
212 		msi_data = (ce_id % msi_data_count) + msi_irq_start;
213 		irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data);
214 
215 		hif_debug("%s: (ce_id %d, msi_data %d, irq %d)", __func__,
216 			  ce_id, msi_data, irq);
217 
218 		pfrm_free_irq(scn->qdf_dev->dev, irq, &ce_sc->tasklets[ce_id]);
219 	}
220 
221 	return ret;
222 }
223 
224 /**
225  * hif_ipci_deconfigure_grp_irq(): deconfigure HW block IRQ
226  * @scn: struct hif_softc
227  *
228  * Return: none
229  */
230 static void hif_ipci_deconfigure_grp_irq(struct hif_softc *scn)
231 {
232 	int i, j, irq;
233 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
234 	struct hif_exec_context *hif_ext_group;
235 
236 	for (i = 0; i < hif_state->hif_num_extgroup; i++) {
237 		hif_ext_group = hif_state->hif_ext_group[i];
238 		if (hif_ext_group->irq_requested) {
239 			hif_ext_group->irq_requested = false;
240 			for (j = 0; j < hif_ext_group->numirq; j++) {
241 				irq = hif_ext_group->os_irq[j];
242 				pfrm_free_irq(scn->qdf_dev->dev,
243 					      irq, hif_ext_group);
244 			}
245 			hif_ext_group->numirq = 0;
246 		}
247 	}
248 }
249 
250 void hif_ipci_nointrs(struct hif_softc *scn)
251 {
252 	int ret;
253 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
254 
255 	ce_unregister_irq(hif_state, CE_ALL_BITMAP);
256 
257 	if (scn->request_irq_done == false)
258 		return;
259 
260 	hif_ipci_deconfigure_grp_irq(scn);
261 
262 	ret = hif_ce_srng_msi_free_irq(scn);
263 
264 	scn->request_irq_done = false;
265 }
266 
267 void hif_ipci_disable_bus(struct hif_softc *scn)
268 {
269 	struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(scn);
270 	void __iomem *mem;
271 
272 	/* Attach did not succeed, all resources have been
273 	 * freed in error handler
274 	 */
275 	if (!sc)
276 		return;
277 
278 	mem = (void __iomem *)sc->mem;
279 	if (mem) {
280 		hif_dump_pipe_debug_count(scn);
281 		if (scn->athdiag_procfs_inited) {
282 			athdiag_procfs_remove();
283 			scn->athdiag_procfs_inited = false;
284 		}
285 		scn->mem = NULL;
286 	}
287 	hif_info("X");
288 }
289 
290 #if defined(CONFIG_PCI_MSM)
291 void hif_ipci_prevent_linkdown(struct hif_softc *scn, bool flag)
292 {
293 	int errno;
294 
295 	hif_info("wlan: %s pcie power collapse", flag ? "disable" : "enable");
296 	hif_runtime_prevent_linkdown(scn, flag);
297 
298 	errno = pld_wlan_pm_control(scn->qdf_dev->dev, flag);
299 	if (errno)
300 		hif_err("Failed pld_wlan_pm_control; errno %d", errno);
301 }
302 #else
303 void hif_ipci_prevent_linkdown(struct hif_softc *scn, bool flag)
304 {
305 	hif_info("wlan: %s pcie power collapse", (flag ? "disable" : "enable"));
306 	hif_runtime_prevent_linkdown(scn, flag);
307 }
308 #endif
309 
310 int hif_ipci_bus_suspend(struct hif_softc *scn)
311 {
312 	int ret;
313 
314 	ret = hif_apps_enable_irq_wake(GET_HIF_OPAQUE_HDL(scn));
315 
316 	if (!ret)
317 		scn->bus_suspended = true;
318 
319 	return ret;
320 }
321 
322 int hif_ipci_bus_resume(struct hif_softc *scn)
323 {
324 	scn->bus_suspended = false;
325 
326 	return hif_apps_disable_irq_wake(GET_HIF_OPAQUE_HDL(scn));
327 }
328 
329 int hif_ipci_bus_suspend_noirq(struct hif_softc *scn)
330 {
331 	QDF_STATUS ret;
332 
333 	ret = hif_try_complete_tasks(scn);
334 	if (QDF_IS_STATUS_ERROR(ret))
335 		return -EBUSY;
336 
337 	return 0;
338 }
339 
340 int hif_ipci_bus_resume_noirq(struct hif_softc *scn)
341 {
342 	return 0;
343 }
344 
345 void hif_ipci_disable_isr(struct hif_softc *scn)
346 {
347 	struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(scn);
348 
349 	hif_exec_kill(&scn->osc);
350 	hif_nointrs(scn);
351 	/* Cancel the pending tasklet */
352 	ce_tasklet_kill(scn);
353 	tasklet_kill(&sc->intr_tq);
354 	qdf_atomic_set(&scn->active_tasklet_cnt, 0);
355 	qdf_atomic_set(&scn->active_grp_tasklet_cnt, 0);
356 }
357 
358 int hif_ipci_dump_registers(struct hif_softc *hif_ctx)
359 {
360 	int status;
361 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ctx);
362 
363 	status = hif_dump_ce_registers(scn);
364 
365 	if (status)
366 		hif_err("Dump CE Registers Failed");
367 
368 	return 0;
369 }
370 
371 /**
372  * hif_ce_interrupt_handler() - interrupt handler for copy engine
373  * @irq: irq number
374  * @context: tasklet context
375  *
376  * Return: irqreturn_t
377  */
378 static irqreturn_t hif_ce_interrupt_handler(int irq, void *context)
379 {
380 	struct ce_tasklet_entry *tasklet_entry = context;
381 
382 	hif_pm_runtime_check_and_request_resume(
383 			GET_HIF_OPAQUE_HDL(tasklet_entry->hif_ce_state));
384 	return ce_dispatch_interrupt(tasklet_entry->ce_id, tasklet_entry);
385 }
386 
387 extern const char *ce_name[];
388 
389 /* hif_ce_srng_msi_irq_disable() - disable the irq for msi
390  * @hif_sc: hif context
391  * @ce_id: which ce to disable copy complete interrupts for
392  *
393  * @Return: none
394  */
395 static void hif_ce_srng_msi_irq_disable(struct hif_softc *hif_sc, int ce_id)
396 {
397 	pfrm_disable_irq_nosync(hif_sc->qdf_dev->dev,
398 				hif_ce_msi_map_ce_to_irq(hif_sc, ce_id));
399 
400 }
401 
402 /* hif_ce_srng_msi_irq_enable() - enable the irq for msi
403  * @hif_sc: hif context
404  * @ce_id: which ce to enable copy complete interrupts for
405  *
406  * @Return: none
407  */
408 static void hif_ce_srng_msi_irq_enable(struct hif_softc *hif_sc, int ce_id)
409 {
410 	pfrm_enable_irq(hif_sc->qdf_dev->dev,
411 			hif_ce_msi_map_ce_to_irq(hif_sc, ce_id));
412 
413 }
414 
415 /* hif_ce_msi_configure_irq() - configure the irq
416  * @scn: hif context
417  *
418  * @Return: none
419  */
420 static int hif_ce_msi_configure_irq(struct hif_softc *scn)
421 {
422 	int ret;
423 	int ce_id, irq;
424 	uint32_t msi_data_start;
425 	uint32_t msi_data_count;
426 	uint32_t msi_irq_start;
427 	struct HIF_CE_state *ce_sc = HIF_GET_CE_STATE(scn);
428 	struct hif_ipci_softc *ipci_sc = HIF_GET_IPCI_SOFTC(scn);
429 	uint8_t wake_ce_id;
430 
431 	ret = hif_get_wake_ce_id(scn, &wake_ce_id);
432 	if (ret)
433 		return ret;
434 
435 	/* do ce irq assignments */
436 	ret = pld_get_user_msi_assignment(scn->qdf_dev->dev, "CE",
437 					  &msi_data_count, &msi_data_start,
438 					  &msi_irq_start);
439 	if (ret)
440 		return ret;
441 
442 	scn->bus_ops.hif_irq_disable = &hif_ce_srng_msi_irq_disable;
443 	scn->bus_ops.hif_irq_enable = &hif_ce_srng_msi_irq_enable;
444 	scn->bus_ops.hif_map_ce_to_irq = &hif_ce_msi_map_ce_to_irq;
445 
446 	/* needs to match the ce_id -> irq data mapping
447 	 * used in the srng parameter configuration
448 	 */
449 	for (ce_id = 0; ce_id < scn->ce_count; ce_id++) {
450 		unsigned long irqflags = IRQF_SHARED;
451 		unsigned int msi_data = (ce_id % msi_data_count) +
452 			msi_irq_start;
453 		irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data);
454 		hif_debug("(ce_id %d, msi_data %d, irq %d tasklet %pK)",
455 			 ce_id, msi_data, irq,
456 			 &ce_sc->tasklets[ce_id]);
457 
458 		/* implies the ce is also initialized */
459 		if (!ce_sc->tasklets[ce_id].inited)
460 			continue;
461 
462 		ipci_sc->ce_msi_irq_num[ce_id] = irq;
463 		ret = pfrm_request_irq(scn->qdf_dev->dev,
464 				       irq, hif_ce_interrupt_handler,
465 				       irqflags,
466 				       ce_name[ce_id],
467 				       &ce_sc->tasklets[ce_id]);
468 		if (ret)
469 			goto free_irq;
470 	}
471 
472 	return ret;
473 
474 free_irq:
475 	/* the request_irq for the last ce_id failed so skip it. */
476 	while (ce_id > 0 && ce_id < scn->ce_count) {
477 		unsigned int msi_data;
478 
479 		ce_id--;
480 		msi_data = (ce_id % msi_data_count) + msi_irq_start;
481 		irq = pld_get_msi_irq(scn->qdf_dev->dev, msi_data);
482 		pfrm_free_irq(scn->qdf_dev->dev, irq, &ce_sc->tasklets[ce_id]);
483 	}
484 
485 	return ret;
486 }
487 
488 /**
489  * hif_exec_grp_irq_disable() - disable the irq for group
490  * @hif_ext_group: hif exec context
491  *
492  * Return: none
493  */
494 static void hif_exec_grp_irq_disable(struct hif_exec_context *hif_ext_group)
495 {
496 	int i;
497 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ext_group->hif);
498 
499 	for (i = 0; i < hif_ext_group->numirq; i++)
500 		pfrm_disable_irq_nosync(scn->qdf_dev->dev,
501 					hif_ext_group->os_irq[i]);
502 }
503 
504 /**
505  * hif_exec_grp_irq_enable() - enable the irq for group
506  * @hif_ext_group: hif exec context
507  *
508  * Return: none
509  */
510 static void hif_exec_grp_irq_enable(struct hif_exec_context *hif_ext_group)
511 {
512 	int i;
513 	struct hif_softc *scn = HIF_GET_SOFTC(hif_ext_group->hif);
514 
515 	for (i = 0; i < hif_ext_group->numirq; i++)
516 		pfrm_enable_irq(scn->qdf_dev->dev, hif_ext_group->os_irq[i]);
517 }
518 
519 const char *hif_ipci_get_irq_name(int irq_no)
520 {
521 	return "pci-dummy";
522 }
523 
524 int hif_ipci_configure_grp_irq(struct hif_softc *scn,
525 			       struct hif_exec_context *hif_ext_group)
526 {
527 	int ret = 0;
528 	int irq = 0;
529 	int j;
530 
531 	hif_ext_group->irq_enable = &hif_exec_grp_irq_enable;
532 	hif_ext_group->irq_disable = &hif_exec_grp_irq_disable;
533 	hif_ext_group->irq_name = &hif_ipci_get_irq_name;
534 	hif_ext_group->work_complete = &hif_dummy_grp_done;
535 
536 	for (j = 0; j < hif_ext_group->numirq; j++) {
537 		irq = hif_ext_group->irq[j];
538 
539 		hif_info("request_irq = %d for grp %d",
540 			 irq, hif_ext_group->grp_id);
541 		ret = pfrm_request_irq(scn->qdf_dev->dev, irq,
542 				       hif_ext_group_interrupt_handler,
543 				       IRQF_SHARED | IRQF_NO_SUSPEND,
544 				       "wlan_EXT_GRP",
545 				       hif_ext_group);
546 		if (ret) {
547 			hif_err("request_irq failed ret = %d", ret);
548 			return -EFAULT;
549 		}
550 		hif_ext_group->os_irq[j] = irq;
551 	}
552 	hif_ext_group->irq_requested = true;
553 	return 0;
554 }
555 
556 int hif_configure_irq(struct hif_softc *scn)
557 {
558 	int ret = 0;
559 
560 	hif_info("E");
561 
562 	if (hif_is_polled_mode_enabled(GET_HIF_OPAQUE_HDL(scn))) {
563 		scn->request_irq_done = false;
564 		return 0;
565 	}
566 
567 	ret = hif_ce_msi_configure_irq(scn);
568 	if (ret == 0)
569 		goto end;
570 
571 	if (ret < 0) {
572 		hif_err("hif_ipci_configure_irq error = %d", ret);
573 		return ret;
574 	}
575 end:
576 	scn->request_irq_done = true;
577 	return 0;
578 }
579 
580 /**
581  * hif_ipci_get_soc_info_pld() - get soc info for ipcie bus from pld target
582  * @sc: ipci context
583  * @dev: device structure
584  *
585  * Return: none
586  */
587 static void hif_ipci_get_soc_info_pld(struct hif_ipci_softc *sc,
588 				      struct device *dev)
589 {
590 	struct pld_soc_info info;
591 
592 	pld_get_soc_info(dev, &info);
593 	sc->mem = info.v_addr;
594 	sc->ce_sc.ol_sc.mem    = info.v_addr;
595 	sc->ce_sc.ol_sc.mem_pa = info.p_addr;
596 }
597 
598 /**
599  * hif_ipci_get_soc_info_nopld() - get soc info for ipcie bus for non pld target
600  * @sc: ipci context
601  * @dev: device structure
602  *
603  * Return: none
604  */
605 static void hif_ipci_get_soc_info_nopld(struct hif_ipci_softc *sc,
606 					struct device *dev)
607 {}
608 
609 /**
610  * hif_is_pld_based_target() - verify if the target is pld based
611  * @sc: ipci context
612  * @device_id: device id
613  *
614  * Return: none
615  */
616 static bool hif_is_pld_based_target(struct hif_ipci_softc *sc,
617 				    int device_id)
618 {
619 	if (!pld_have_platform_driver_support(sc->dev))
620 		return false;
621 
622 	switch (device_id) {
623 #ifdef QCA_WIFI_QCA6750
624 	case QCA6750_DEVICE_ID:
625 #endif
626 		return true;
627 	}
628 	return false;
629 }
630 
631 /**
632  * hif_ipci_init_deinit_ops_attach() - attach ops for ipci
633  * @sc: ipci context
634  * @device_id: device id
635  *
636  * Return: none
637  */
638 static void hif_ipci_init_deinit_ops_attach(struct hif_ipci_softc *sc,
639 					    int device_id)
640 {
641 	if (hif_is_pld_based_target(sc, device_id))
642 		sc->hif_ipci_get_soc_info = hif_ipci_get_soc_info_pld;
643 	else
644 		sc->hif_ipci_get_soc_info = hif_ipci_get_soc_info_nopld;
645 }
646 
647 QDF_STATUS hif_ipci_enable_bus(struct hif_softc *ol_sc,
648 			       struct device *dev, void *bdev,
649 			       const struct hif_bus_id *bid,
650 			       enum hif_enable_type type)
651 {
652 	int ret = 0;
653 	uint32_t hif_type, target_type;
654 	struct hif_ipci_softc *sc = HIF_GET_IPCI_SOFTC(ol_sc);
655 	struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(ol_sc);
656 	uint16_t revision_id = 0;
657 	struct hif_target_info *tgt_info;
658 	int device_id = QCA6750_DEVICE_ID;
659 
660 	if (!ol_sc) {
661 		hif_err("hif_ctx is NULL");
662 		return QDF_STATUS_E_NOMEM;
663 	}
664 
665 	ret = qdf_set_dma_coherent_mask(dev,
666 					DMA_COHERENT_MASK_DEFAULT);
667 	if (ret) {
668 		hif_err("Failed to set dma mask error = %d", ret);
669 		return qdf_status_from_os_return(ret);
670 	}
671 
672 	sc->dev = dev;
673 	tgt_info = hif_get_target_info_handle(hif_hdl);
674 	hif_ipci_init_deinit_ops_attach(sc, device_id);
675 	sc->hif_ipci_get_soc_info(sc, dev);
676 	hif_debug("hif_enable_pci done");
677 
678 	ret = hif_get_device_type(device_id, revision_id,
679 				  &hif_type, &target_type);
680 	if (ret < 0) {
681 		hif_err("Invalid device id/revision_id");
682 		return QDF_STATUS_E_ABORTED;
683 	}
684 	hif_debug("hif_type = 0x%x, target_type = 0x%x",
685 		 hif_type, target_type);
686 
687 	hif_register_tbl_attach(ol_sc, hif_type);
688 	hif_target_register_tbl_attach(ol_sc, target_type);
689 	sc->use_register_windowing = false;
690 	tgt_info->target_type = target_type;
691 
692 	if (!ol_sc->mem_pa) {
693 		hif_err("BAR0 uninitialized");
694 		return QDF_STATUS_E_ABORTED;
695 	}
696 
697 	return QDF_STATUS_SUCCESS;
698 }
699 
700 bool hif_ipci_needs_bmi(struct hif_softc *scn)
701 {
702 	return !ce_srng_based(scn);
703 }
704 
705 #ifdef FORCE_WAKE
706 int hif_force_wake_request(struct hif_opaque_softc *hif_handle)
707 {
708 	uint32_t timeout = 0;
709 	struct hif_softc *scn = (struct hif_softc *)hif_handle;
710 	struct hif_ipci_softc *ipci_scn = HIF_GET_IPCI_SOFTC(scn);
711 
712 	if (pld_force_wake_request(scn->qdf_dev->dev)) {
713 		hif_err_rl("force wake request send failed");
714 		return -EINVAL;
715 	}
716 
717 	HIF_STATS_INC(ipci_scn, mhi_force_wake_request_vote, 1);
718 	while (!pld_is_device_awake(scn->qdf_dev->dev) &&
719 	       timeout <= FORCE_WAKE_DELAY_TIMEOUT_MS) {
720 		qdf_mdelay(FORCE_WAKE_DELAY_MS);
721 		timeout += FORCE_WAKE_DELAY_MS;
722 	}
723 
724 	if (pld_is_device_awake(scn->qdf_dev->dev) <= 0) {
725 		hif_err("Unable to wake up mhi");
726 		HIF_STATS_INC(ipci_scn, mhi_force_wake_failure, 1);
727 		return -EINVAL;
728 	}
729 	HIF_STATS_INC(ipci_scn, mhi_force_wake_success, 1);
730 
731 	HIF_STATS_INC(ipci_scn, soc_force_wake_success, 1);
732 
733 	return 0;
734 }
735 
736 int hif_force_wake_release(struct hif_opaque_softc *hif_handle)
737 {
738 	int ret;
739 	struct hif_softc *scn = (struct hif_softc *)hif_handle;
740 	struct hif_ipci_softc *ipci_scn = HIF_GET_IPCI_SOFTC(scn);
741 
742 	ret = pld_force_wake_release(scn->qdf_dev->dev);
743 	if (ret) {
744 		hif_err("force wake release failure");
745 		HIF_STATS_INC(ipci_scn, mhi_force_wake_release_failure, 1);
746 		return ret;
747 	}
748 
749 	HIF_STATS_INC(ipci_scn, mhi_force_wake_release_success, 1);
750 
751 	HIF_STATS_INC(ipci_scn, soc_force_wake_release_success, 1);
752 	return 0;
753 }
754 
755 void hif_print_ipci_stats(struct hif_ipci_softc *ipci_handle)
756 {
757 	hif_debug("mhi_force_wake_request_vote: %d",
758 		  ipci_handle->stats.mhi_force_wake_request_vote);
759 	hif_debug("mhi_force_wake_failure: %d",
760 		  ipci_handle->stats.mhi_force_wake_failure);
761 	hif_debug("mhi_force_wake_success: %d",
762 		  ipci_handle->stats.mhi_force_wake_success);
763 	hif_debug("soc_force_wake_register_write_success: %d",
764 		  ipci_handle->stats.soc_force_wake_register_write_success);
765 	hif_debug("soc_force_wake_failure: %d",
766 		  ipci_handle->stats.soc_force_wake_failure);
767 	hif_debug("soc_force_wake_success: %d",
768 		  ipci_handle->stats.soc_force_wake_success);
769 	hif_debug("mhi_force_wake_release_failure: %d",
770 		  ipci_handle->stats.mhi_force_wake_release_failure);
771 	hif_debug("mhi_force_wake_release_success: %d",
772 		  ipci_handle->stats.mhi_force_wake_release_success);
773 	hif_debug("oc_force_wake_release_success: %d",
774 		  ipci_handle->stats.soc_force_wake_release_success);
775 }
776 #endif /* FORCE_WAKE */
777