1 /*
2  * Copyright (c) 2016-2018, 2020-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 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 /* this file dispatches functions to bus specific definitions */
21 #include "hif_debug.h"
22 #include "hif.h"
23 #include "hif_main.h"
24 #include "hif_io32.h"
25 #include "multibus.h"
26 #include "dummy.h"
27 #if defined(HIF_PCI) || defined(HIF_SNOC) || defined(HIF_AHB) || \
28     defined(HIF_IPCI)
29 #include "ce_main.h"
30 #include "ce_api.h"
31 #include "ce_internal.h"
32 #endif
33 #include "htc_services.h"
34 #include "a_types.h"
35 #include "dummy.h"
36 #include "qdf_module.h"
37 
38 /**
39  * hif_initialize_default_ops() - initializes default operations values
40  * @hif_sc: hif_context
41  *
42  * bus specific features should assign their dummy implementations here.
43  */
hif_initialize_default_ops(struct hif_softc * hif_sc)44 static void hif_initialize_default_ops(struct hif_softc *hif_sc)
45 {
46 	struct hif_bus_ops *bus_ops = &hif_sc->bus_ops;
47 
48 	/* must be filled in by hif_bus_open */
49 	bus_ops->hif_bus_close = NULL;
50 	/* dummy implementations */
51 	bus_ops->hif_display_stats =
52 		&hif_dummy_display_stats;
53 	bus_ops->hif_clear_stats =
54 		&hif_dummy_clear_stats;
55 	bus_ops->hif_set_bundle_mode = &hif_dummy_set_bundle_mode;
56 	bus_ops->hif_bus_reset_resume = &hif_dummy_bus_reset_resume;
57 	bus_ops->hif_bus_suspend_noirq = &hif_dummy_bus_suspend_noirq;
58 	bus_ops->hif_bus_resume_noirq = &hif_dummy_bus_resume_noirq;
59 	bus_ops->hif_bus_early_suspend = &hif_dummy_bus_suspend;
60 	bus_ops->hif_bus_late_resume = &hif_dummy_bus_resume;
61 	bus_ops->hif_map_ce_to_irq = &hif_dummy_map_ce_to_irq;
62 	bus_ops->hif_grp_irq_configure = &hif_dummy_grp_irq_configure;
63 	bus_ops->hif_grp_irq_deconfigure = &hif_dummy_grp_irq_deconfigure;
64 	bus_ops->hif_config_irq_affinity =
65 		&hif_dummy_config_irq_affinity;
66 	bus_ops->hif_config_irq_by_ceid = &hif_dummy_config_irq_by_ceid;
67 	bus_ops->hif_enable_grp_irqs = &hif_dummy_enable_grp_irqs;
68 	bus_ops->hif_disable_grp_irqs = &hif_dummy_enable_grp_irqs;
69 	bus_ops->hif_config_irq_clear_cpu_affinity =
70 		&hif_dummy_config_irq_clear_cpu_affinity;
71 #ifdef FEATURE_IRQ_AFFINITY
72 	bus_ops->hif_set_grp_intr_affinity = &hif_dummy_set_grp_intr_affinity;
73 #endif
74 	bus_ops->hif_affinity_mgr_set_affinity =
75 		&hif_dummy_affinity_mgr_set_affinity;
76 }
77 
78 #define NUM_OPS (sizeof(struct hif_bus_ops) / sizeof(void *))
79 
80 /**
81  * hif_verify_basic_ops() - ensure required bus apis are defined
82  * @hif_sc: hif_context
83  *
84  * all bus operations must be defined to avoid crashes
85  * iterate over the structure and ensure all function pointers
86  * are non null.
87  *
88  * Return: QDF_STATUS_SUCCESS if all the operations are defined
89  */
hif_verify_basic_ops(struct hif_softc * hif_sc)90 static QDF_STATUS hif_verify_basic_ops(struct hif_softc *hif_sc)
91 {
92 	struct hif_bus_ops *bus_ops = &hif_sc->bus_ops;
93 	void **ops_array = (void *)bus_ops;
94 	QDF_STATUS status = QDF_STATUS_SUCCESS;
95 	int i;
96 
97 	for (i = 0; i < NUM_OPS; i++) {
98 		if (!ops_array[i]) {
99 			hif_err("ops_array[%d] is null", i);
100 			status = QDF_STATUS_E_NOSUPPORT;
101 		}
102 	}
103 	return status;
104 }
105 
106 /**
107  * hif_bus_get_context_size - API to return size of the bus specific structure
108  * @bus_type: bus type
109  *
110  * Return: sizeof of hif_pci_softc
111  */
hif_bus_get_context_size(enum qdf_bus_type bus_type)112 int hif_bus_get_context_size(enum qdf_bus_type bus_type)
113 {
114 	switch (bus_type) {
115 	case QDF_BUS_TYPE_PCI:
116 		return hif_pci_get_context_size();
117 	case QDF_BUS_TYPE_IPCI:
118 		return hif_ipci_get_context_size();
119 	case QDF_BUS_TYPE_AHB:
120 		return hif_ahb_get_context_size();
121 	case QDF_BUS_TYPE_SNOC:
122 		return hif_snoc_get_context_size();
123 	case QDF_BUS_TYPE_SDIO:
124 		return hif_sdio_get_context_size();
125 	case QDF_BUS_TYPE_USB:
126 		return hif_usb_get_context_size();
127 	default:
128 		return 0;
129 	}
130 }
131 
132 /**
133  * hif_bus_open() - initialize the bus_ops and call the bus specific open
134  * @hif_sc: hif_context
135  * @bus_type: type of bus being enumerated
136  *
137  * Return: QDF_STATUS_SUCCESS or error
138  */
hif_bus_open(struct hif_softc * hif_sc,enum qdf_bus_type bus_type)139 QDF_STATUS hif_bus_open(struct hif_softc *hif_sc,
140 			enum qdf_bus_type bus_type)
141 {
142 	QDF_STATUS status = QDF_STATUS_E_INVAL;
143 
144 	hif_initialize_default_ops(hif_sc);
145 
146 	switch (bus_type) {
147 	case QDF_BUS_TYPE_PCI:
148 		status = hif_initialize_pci_ops(hif_sc);
149 		break;
150 	case QDF_BUS_TYPE_IPCI:
151 		status = hif_initialize_ipci_ops(hif_sc);
152 		break;
153 	case QDF_BUS_TYPE_SNOC:
154 		status = hif_initialize_snoc_ops(&hif_sc->bus_ops);
155 		break;
156 	case QDF_BUS_TYPE_AHB:
157 		status = hif_initialize_ahb_ops(&hif_sc->bus_ops);
158 		break;
159 	case QDF_BUS_TYPE_SDIO:
160 		status = hif_initialize_sdio_ops(hif_sc);
161 		break;
162 	case QDF_BUS_TYPE_USB:
163 		status = hif_initialize_usb_ops(&hif_sc->bus_ops);
164 		break;
165 	default:
166 		status = QDF_STATUS_E_NOSUPPORT;
167 		break;
168 	}
169 
170 	if (status != QDF_STATUS_SUCCESS) {
171 		hif_err("bus_type: %d not supported", bus_type);
172 		return status;
173 	}
174 
175 	status = hif_verify_basic_ops(hif_sc);
176 	if (status != QDF_STATUS_SUCCESS)
177 		return status;
178 
179 	return hif_sc->bus_ops.hif_bus_open(hif_sc, bus_type);
180 }
181 
182 /**
183  * hif_bus_close() - close the bus
184  * @hif_sc: hif_context
185  */
hif_bus_close(struct hif_softc * hif_sc)186 void hif_bus_close(struct hif_softc *hif_sc)
187 {
188 	hif_sc->bus_ops.hif_bus_close(hif_sc);
189 }
190 
191 /**
192  * hif_bus_prevent_linkdown() - prevent linkdown
193  * @hif_sc: hif context
194  * @flag: true = keep bus alive false = let bus go to sleep
195  *
196  * Keeps the bus awake during suspend.
197  */
hif_bus_prevent_linkdown(struct hif_softc * hif_sc,bool flag)198 void hif_bus_prevent_linkdown(struct hif_softc *hif_sc, bool flag)
199 {
200 	hif_sc->bus_ops.hif_bus_prevent_linkdown(hif_sc, flag);
201 }
202 
203 
hif_reset_soc(struct hif_opaque_softc * hif_ctx)204 void hif_reset_soc(struct hif_opaque_softc *hif_ctx)
205 {
206 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
207 
208 	hif_sc->bus_ops.hif_reset_soc(hif_sc);
209 }
210 
hif_bus_early_suspend(struct hif_opaque_softc * hif_ctx)211 int hif_bus_early_suspend(struct hif_opaque_softc *hif_ctx)
212 {
213 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
214 
215 	return hif_sc->bus_ops.hif_bus_early_suspend(hif_sc);
216 }
217 
hif_bus_late_resume(struct hif_opaque_softc * hif_ctx)218 int hif_bus_late_resume(struct hif_opaque_softc *hif_ctx)
219 {
220 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
221 
222 	return hif_sc->bus_ops.hif_bus_late_resume(hif_sc);
223 }
224 
hif_bus_suspend(struct hif_opaque_softc * hif_ctx)225 int hif_bus_suspend(struct hif_opaque_softc *hif_ctx)
226 {
227 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
228 
229 	return hif_sc->bus_ops.hif_bus_suspend(hif_sc);
230 }
231 
hif_bus_resume(struct hif_opaque_softc * hif_ctx)232 int hif_bus_resume(struct hif_opaque_softc *hif_ctx)
233 {
234 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
235 
236 	return hif_sc->bus_ops.hif_bus_resume(hif_sc);
237 }
238 
hif_bus_suspend_noirq(struct hif_opaque_softc * hif_ctx)239 int hif_bus_suspend_noirq(struct hif_opaque_softc *hif_ctx)
240 {
241 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
242 
243 	return hif_sc->bus_ops.hif_bus_suspend_noirq(hif_sc);
244 }
245 
hif_bus_resume_noirq(struct hif_opaque_softc * hif_ctx)246 int hif_bus_resume_noirq(struct hif_opaque_softc *hif_ctx)
247 {
248 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
249 
250 	return hif_sc->bus_ops.hif_bus_resume_noirq(hif_sc);
251 }
252 
hif_target_sleep_state_adjust(struct hif_softc * hif_sc,bool sleep_ok,bool wait_for_it)253 int hif_target_sleep_state_adjust(struct hif_softc *hif_sc,
254 			      bool sleep_ok, bool wait_for_it)
255 {
256 	return hif_sc->bus_ops.hif_target_sleep_state_adjust(hif_sc,
257 			sleep_ok, wait_for_it);
258 }
259 qdf_export_symbol(hif_target_sleep_state_adjust);
260 
hif_disable_isr(struct hif_opaque_softc * hif_hdl)261 void hif_disable_isr(struct hif_opaque_softc *hif_hdl)
262 {
263 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl);
264 
265 	hif_sc->bus_ops.hif_disable_isr(hif_sc);
266 }
267 
hif_nointrs(struct hif_softc * hif_sc)268 void hif_nointrs(struct hif_softc *hif_sc)
269 {
270 	hif_sc->bus_ops.hif_nointrs(hif_sc);
271 }
272 
hif_enable_bus(struct hif_softc * hif_sc,struct device * dev,void * bdev,const struct hif_bus_id * bid,enum hif_enable_type type)273 QDF_STATUS hif_enable_bus(struct hif_softc *hif_sc, struct device *dev,
274 			  void *bdev, const struct hif_bus_id *bid,
275 			  enum hif_enable_type type)
276 {
277 	return hif_sc->bus_ops.hif_enable_bus(hif_sc, dev, bdev, bid, type);
278 }
279 
hif_disable_bus(struct hif_softc * hif_sc)280 void hif_disable_bus(struct hif_softc *hif_sc)
281 {
282 	hif_sc->bus_ops.hif_disable_bus(hif_sc);
283 }
284 
hif_bus_configure(struct hif_softc * hif_sc)285 int hif_bus_configure(struct hif_softc *hif_sc)
286 {
287 	return hif_sc->bus_ops.hif_bus_configure(hif_sc);
288 }
289 
hif_get_config_item(struct hif_opaque_softc * hif_ctx,int opcode,void * config,uint32_t config_len)290 QDF_STATUS hif_get_config_item(struct hif_opaque_softc *hif_ctx,
291 		     int opcode, void *config, uint32_t config_len)
292 {
293 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
294 
295 	return hif_sc->bus_ops.hif_get_config_item(hif_sc, opcode, config,
296 						 config_len);
297 }
298 
hif_set_mailbox_swap(struct hif_opaque_softc * hif_ctx)299 void hif_set_mailbox_swap(struct hif_opaque_softc *hif_ctx)
300 {
301 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
302 
303 	hif_sc->bus_ops.hif_set_mailbox_swap(hif_sc);
304 }
305 
hif_claim_device(struct hif_opaque_softc * hif_ctx)306 void hif_claim_device(struct hif_opaque_softc *hif_ctx)
307 {
308 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
309 
310 	hif_sc->bus_ops.hif_claim_device(hif_sc);
311 }
312 
hif_shutdown_device(struct hif_opaque_softc * hif_ctx)313 void hif_shutdown_device(struct hif_opaque_softc *hif_ctx)
314 {
315 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
316 
317 	hif_sc->bus_ops.hif_shutdown_device(hif_sc);
318 }
319 
hif_stop(struct hif_opaque_softc * hif_ctx)320 void hif_stop(struct hif_opaque_softc *hif_ctx)
321 {
322 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_ctx);
323 
324 	hif_sc->bus_ops.hif_stop(hif_sc);
325 }
326 
hif_cancel_deferred_target_sleep(struct hif_softc * hif_sc)327 void hif_cancel_deferred_target_sleep(struct hif_softc *hif_sc)
328 {
329 	return hif_sc->bus_ops.hif_cancel_deferred_target_sleep(hif_sc);
330 }
331 
hif_irq_enable(struct hif_softc * hif_sc,int irq_id)332 void hif_irq_enable(struct hif_softc *hif_sc, int irq_id)
333 {
334 	hif_sc->bus_ops.hif_irq_enable(hif_sc, irq_id);
335 }
336 qdf_export_symbol(hif_irq_enable);
337 
hif_irq_disable(struct hif_softc * hif_sc,int irq_id)338 void hif_irq_disable(struct hif_softc *hif_sc, int irq_id)
339 {
340 	hif_sc->bus_ops.hif_irq_disable(hif_sc, irq_id);
341 }
342 
hif_grp_irq_configure(struct hif_softc * hif_sc,struct hif_exec_context * hif_exec)343 int hif_grp_irq_configure(struct hif_softc *hif_sc,
344 			  struct hif_exec_context *hif_exec)
345 {
346 	return hif_sc->bus_ops.hif_grp_irq_configure(hif_sc, hif_exec);
347 }
348 
hif_grp_irq_deconfigure(struct hif_softc * hif_sc)349 void hif_grp_irq_deconfigure(struct hif_softc *hif_sc)
350 {
351 	hif_sc->bus_ops.hif_grp_irq_deconfigure(hif_sc);
352 }
353 
hif_dump_registers(struct hif_opaque_softc * hif_hdl)354 int hif_dump_registers(struct hif_opaque_softc *hif_hdl)
355 {
356 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl);
357 
358 	return hif_sc->bus_ops.hif_dump_registers(hif_sc);
359 }
360 
hif_dump_target_memory(struct hif_opaque_softc * hif_hdl,void * ramdump_base,uint32_t address,uint32_t size)361 void hif_dump_target_memory(struct hif_opaque_softc *hif_hdl,
362 			    void *ramdump_base,
363 			    uint32_t address, uint32_t size)
364 {
365 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl);
366 
367 	hif_sc->bus_ops.hif_dump_target_memory(hif_sc, ramdump_base,
368 					       address, size);
369 }
370 
hif_ipa_get_ce_resource(struct hif_opaque_softc * hif_hdl,qdf_shared_mem_t ** ce_sr,uint32_t * ce_sr_ring_size,qdf_dma_addr_t * ce_reg_paddr)371 void hif_ipa_get_ce_resource(struct hif_opaque_softc *hif_hdl,
372 			     qdf_shared_mem_t **ce_sr,
373 			     uint32_t *ce_sr_ring_size,
374 			     qdf_dma_addr_t *ce_reg_paddr)
375 {
376 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl);
377 
378 	hif_sc->bus_ops.hif_ipa_get_ce_resource(hif_sc, ce_sr,
379 			ce_sr_ring_size, ce_reg_paddr);
380 }
381 
hif_mask_interrupt_call(struct hif_opaque_softc * hif_hdl)382 void hif_mask_interrupt_call(struct hif_opaque_softc *hif_hdl)
383 {
384 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl);
385 
386 	hif_sc->bus_ops.hif_mask_interrupt_call(hif_sc);
387 }
388 
hif_display_bus_stats(struct hif_opaque_softc * scn)389 void hif_display_bus_stats(struct hif_opaque_softc *scn)
390 {
391 	struct hif_softc *hif_sc = HIF_GET_SOFTC(scn);
392 
393 	hif_sc->bus_ops.hif_display_stats(hif_sc);
394 }
395 
hif_clear_bus_stats(struct hif_opaque_softc * scn)396 void hif_clear_bus_stats(struct hif_opaque_softc *scn)
397 {
398 	struct hif_softc *hif_sc = HIF_GET_SOFTC(scn);
399 
400 	hif_sc->bus_ops.hif_clear_stats(hif_sc);
401 }
402 
403 /**
404  * hif_enable_power_management() - enable power management after driver load
405  * @hif_hdl: opaque pointer to the hif context
406  * @is_packet_log_enabled: true if packet log is enabled
407  *
408  * Driver load and firmware download are done in a high performance mode.
409  * Enable power management after the driver is loaded.
410  * packet log can require fewer power management features to be enabled.
411  */
hif_enable_power_management(struct hif_opaque_softc * hif_hdl,bool is_packet_log_enabled)412 void hif_enable_power_management(struct hif_opaque_softc *hif_hdl,
413 				 bool is_packet_log_enabled)
414 {
415 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl);
416 
417 	hif_sc->bus_ops.hif_enable_power_management(hif_sc,
418 				    is_packet_log_enabled);
419 }
420 
421 /**
422  * hif_disable_power_management() - reset the bus power management
423  * @hif_hdl: opaque pointer to the hif context
424  *
425  * return the power management of the bus to its default state.
426  * This isn't necessarily a complete reversal of its counterpart.
427  * This should be called when unloading the driver.
428  */
hif_disable_power_management(struct hif_opaque_softc * hif_hdl)429 void hif_disable_power_management(struct hif_opaque_softc *hif_hdl)
430 {
431 	struct hif_softc *hif_sc = HIF_GET_SOFTC(hif_hdl);
432 
433 	hif_sc->bus_ops.hif_disable_power_management(hif_sc);
434 }
435 
436 /**
437  * hif_set_bundle_mode() - enable bundling and set default rx bundle cnt
438  * @scn: pointer to hif_opaque_softc structure
439  * @enabled: flag to enable/disable bundling
440  * @rx_bundle_cnt: bundle count to be used for RX
441  *
442  * Return: none
443  */
hif_set_bundle_mode(struct hif_opaque_softc * scn,bool enabled,int rx_bundle_cnt)444 void hif_set_bundle_mode(struct hif_opaque_softc *scn, bool enabled,
445 				int rx_bundle_cnt)
446 {
447 	struct hif_softc *hif_sc = HIF_GET_SOFTC(scn);
448 
449 	hif_sc->bus_ops.hif_set_bundle_mode(hif_sc, enabled, rx_bundle_cnt);
450 }
451 
452 /**
453  * hif_bus_reset_resume() - resume the bus after reset
454  * @scn: struct hif_opaque_softc
455  *
456  * This function is called to tell the driver that USB device has been resumed
457  * and it has also been reset. The driver should redo any necessary
458  * initialization. This function resets WLAN SOC.
459  *
460  * Return: int 0 for success, non zero for failure
461  */
hif_bus_reset_resume(struct hif_opaque_softc * scn)462 int hif_bus_reset_resume(struct hif_opaque_softc *scn)
463 {
464 	struct hif_softc *hif_sc = HIF_GET_SOFTC(scn);
465 
466 	return hif_sc->bus_ops.hif_bus_reset_resume(hif_sc);
467 }
468 
hif_apps_irqs_disable(struct hif_opaque_softc * hif_ctx)469 int hif_apps_irqs_disable(struct hif_opaque_softc *hif_ctx)
470 {
471 	struct hif_softc *scn;
472 	int i;
473 
474 	QDF_BUG(hif_ctx);
475 	scn = HIF_GET_SOFTC(hif_ctx);
476 	if (!scn)
477 		return -EINVAL;
478 
479 	if (pld_is_one_msi(scn->qdf_dev->dev))
480 		return 0;
481 
482 	/* if the wake_irq is shared, don't disable it twice */
483 	for (i = 0; i < scn->ce_count; ++i) {
484 		int irq = scn->bus_ops.hif_map_ce_to_irq(scn, i);
485 
486 		if (irq != scn->wake_irq)
487 			disable_irq(irq);
488 	}
489 
490 	return 0;
491 }
492 
hif_apps_irqs_enable(struct hif_opaque_softc * hif_ctx)493 int hif_apps_irqs_enable(struct hif_opaque_softc *hif_ctx)
494 {
495 	struct hif_softc *scn;
496 	int i;
497 
498 	QDF_BUG(hif_ctx);
499 	scn = HIF_GET_SOFTC(hif_ctx);
500 	if (!scn)
501 		return -EINVAL;
502 
503 	if (pld_is_one_msi(scn->qdf_dev->dev))
504 		return 0;
505 
506 	/* if the wake_irq is shared, don't enable it twice */
507 	for (i = 0; i < scn->ce_count; ++i) {
508 		int irq = scn->bus_ops.hif_map_ce_to_irq(scn, i);
509 
510 		if (irq != scn->wake_irq)
511 			enable_irq(irq);
512 	}
513 
514 	return 0;
515 }
516 
hif_apps_wake_irq_disable(struct hif_opaque_softc * hif_ctx)517 int hif_apps_wake_irq_disable(struct hif_opaque_softc *hif_ctx)
518 {
519 	struct hif_softc *scn;
520 
521 	QDF_BUG(hif_ctx);
522 	scn = HIF_GET_SOFTC(hif_ctx);
523 	if (!scn)
524 		return -EINVAL;
525 
526 	disable_irq(scn->wake_irq);
527 
528 	return 0;
529 }
530 
hif_apps_wake_irq_enable(struct hif_opaque_softc * hif_ctx)531 int hif_apps_wake_irq_enable(struct hif_opaque_softc *hif_ctx)
532 {
533 	struct hif_softc *scn;
534 
535 	QDF_BUG(hif_ctx);
536 	scn = HIF_GET_SOFTC(hif_ctx);
537 	if (!scn)
538 		return -EINVAL;
539 
540 	enable_irq(scn->wake_irq);
541 
542 	return 0;
543 }
544 
hif_apps_disable_irq_wake(struct hif_opaque_softc * hif_ctx)545 int hif_apps_disable_irq_wake(struct hif_opaque_softc *hif_ctx)
546 {
547 	struct hif_softc *scn;
548 
549 	QDF_BUG(hif_ctx);
550 	scn = HIF_GET_SOFTC(hif_ctx);
551 	if (!scn)
552 		return -EINVAL;
553 
554 	return disable_irq_wake(scn->wake_irq);
555 }
556 
hif_apps_enable_irq_wake(struct hif_opaque_softc * hif_ctx)557 int hif_apps_enable_irq_wake(struct hif_opaque_softc *hif_ctx)
558 {
559 	struct hif_softc *scn;
560 
561 	QDF_BUG(hif_ctx);
562 	scn = HIF_GET_SOFTC(hif_ctx);
563 	if (!scn)
564 		return -EINVAL;
565 
566 	return enable_irq_wake(scn->wake_irq);
567 }
568 
hif_apps_disable_irqs_except_wake_irq(struct hif_opaque_softc * hif_ctx)569 int hif_apps_disable_irqs_except_wake_irq(struct hif_opaque_softc *hif_ctx)
570 {
571 	struct hif_softc *scn;
572 	int i;
573 
574 	QDF_BUG(hif_ctx);
575 	scn = HIF_GET_SOFTC(hif_ctx);
576 	if (!scn)
577 		return -EINVAL;
578 
579 	for (i = 0; i < scn->ce_count; ++i) {
580 		int irq = scn->bus_ops.hif_map_ce_to_irq(scn, i);
581 
582 		if (irq != scn->wake_irq)
583 			disable_irq(irq);
584 	}
585 
586 	return 0;
587 }
588 
hif_apps_enable_irqs_except_wake_irq(struct hif_opaque_softc * hif_ctx)589 int hif_apps_enable_irqs_except_wake_irq(struct hif_opaque_softc *hif_ctx)
590 {
591 	struct hif_softc *scn;
592 	int i;
593 
594 	QDF_BUG(hif_ctx);
595 	scn = HIF_GET_SOFTC(hif_ctx);
596 	if (!scn)
597 		return -EINVAL;
598 
599 	for (i = 0; i < scn->ce_count; ++i) {
600 		int irq = scn->bus_ops.hif_map_ce_to_irq(scn, i);
601 
602 		if (irq != scn->wake_irq)
603 			enable_irq(irq);
604 	}
605 
606 	return 0;
607 }
608 
609 #ifdef WLAN_FEATURE_BMI
hif_needs_bmi(struct hif_opaque_softc * scn)610 bool hif_needs_bmi(struct hif_opaque_softc *scn)
611 {
612 	struct hif_softc *hif_sc = HIF_GET_SOFTC(scn);
613 
614 	return hif_sc->bus_ops.hif_needs_bmi(hif_sc);
615 }
616 qdf_export_symbol(hif_needs_bmi);
617 #endif /* WLAN_FEATURE_BMI */
618 
hif_config_irq_affinity(struct hif_softc * hif_sc)619 void hif_config_irq_affinity(struct hif_softc *hif_sc)
620 {
621 	hif_sc->bus_ops.hif_config_irq_affinity(hif_sc);
622 }
623 
hif_config_irq_by_ceid(struct hif_softc * hif_sc,int ce_id)624 int hif_config_irq_by_ceid(struct hif_softc *hif_sc, int ce_id)
625 {
626 	return hif_sc->bus_ops.hif_config_irq_by_ceid(hif_sc, ce_id);
627 }
628 
629 #ifdef HIF_CPU_CLEAR_AFFINITY
hif_config_irq_clear_cpu_affinity(struct hif_opaque_softc * scn,int intr_ctxt_id,int cpu)630 void hif_config_irq_clear_cpu_affinity(struct hif_opaque_softc *scn,
631 				       int intr_ctxt_id, int cpu)
632 {
633 	struct hif_softc *hif_sc = HIF_GET_SOFTC(scn);
634 
635 	hif_sc->bus_ops.hif_config_irq_clear_cpu_affinity(hif_sc,
636 							  intr_ctxt_id, cpu);
637 }
638 
639 qdf_export_symbol(hif_config_irq_clear_cpu_affinity);
640 #endif
641 
642 #ifdef HIF_BUS_LOG_INFO
hif_log_bus_info(struct hif_softc * hif_sc,uint8_t * data,unsigned int * offset)643 bool hif_log_bus_info(struct hif_softc *hif_sc, uint8_t *data,
644 		      unsigned int *offset)
645 {
646 	if (hif_sc->bus_ops.hif_log_bus_info)
647 		return hif_sc->bus_ops.hif_log_bus_info(hif_sc, data, offset);
648 
649 	return false;
650 }
651 #endif
652 
hif_apps_grp_irqs_enable(struct hif_opaque_softc * hif_ctx)653 int hif_apps_grp_irqs_enable(struct hif_opaque_softc *hif_ctx)
654 {
655 	struct hif_exec_context *hif_exec;
656 	struct hif_softc *scn;
657 	int i, j;
658 
659 	QDF_BUG(hif_ctx);
660 	scn = HIF_GET_SOFTC(hif_ctx);
661 	if (!scn)
662 		return -EINVAL;
663 
664 	for (i = 0 ; i < HIF_MAX_GROUP; i++) {
665 		hif_exec = hif_exec_get_ctx(hif_ctx, i);
666 		if (!hif_exec)
667 			continue;
668 
669 		for (j = 0; j < hif_exec->numirq; j++)
670 			pfrm_enable_irq(scn->qdf_dev->dev,
671 					hif_exec->os_irq[j]);
672 	}
673 
674 	return 0;
675 }
676 
hif_apps_grp_irqs_disable(struct hif_opaque_softc * hif_ctx)677 int hif_apps_grp_irqs_disable(struct hif_opaque_softc *hif_ctx)
678 {
679 	struct hif_exec_context *hif_exec;
680 	struct hif_softc *scn;
681 	int i, j;
682 
683 	QDF_BUG(hif_ctx);
684 	scn = HIF_GET_SOFTC(hif_ctx);
685 	if (!scn)
686 		return -EINVAL;
687 
688 	for (i = 0 ; i < HIF_MAX_GROUP; i++) {
689 		hif_exec = hif_exec_get_ctx(hif_ctx, i);
690 		if (!hif_exec)
691 			continue;
692 
693 		for (j = 0; j < hif_exec->numirq; j++)
694 			pfrm_disable_irq(scn->qdf_dev->dev,
695 					 hif_exec->os_irq[j]);
696 	}
697 
698 	return 0;
699 }
700 
hif_disable_grp_irqs(struct hif_opaque_softc * scn)701 int hif_disable_grp_irqs(struct hif_opaque_softc *scn)
702 {
703 	struct hif_softc *hif_sc = HIF_GET_SOFTC(scn);
704 
705 	return hif_sc->bus_ops.hif_disable_grp_irqs(hif_sc);
706 }
707 
hif_enable_grp_irqs(struct hif_opaque_softc * scn)708 int hif_enable_grp_irqs(struct hif_opaque_softc *scn)
709 {
710 	struct hif_softc *hif_sc = HIF_GET_SOFTC(scn);
711 
712 	return hif_sc->bus_ops.hif_enable_grp_irqs(hif_sc);
713 }
714 
715 #ifdef FEATURE_IRQ_AFFINITY
hif_set_grp_intr_affinity(struct hif_opaque_softc * scn,uint32_t grp_intr_bitmask,bool perf)716 void hif_set_grp_intr_affinity(struct hif_opaque_softc *scn,
717 			       uint32_t grp_intr_bitmask, bool perf)
718 {
719 	struct hif_softc *hif_sc = HIF_GET_SOFTC(scn);
720 
721 	if (!hif_sc)
722 		return;
723 
724 	hif_sc->bus_ops.hif_set_grp_intr_affinity(hif_sc, grp_intr_bitmask,
725 						  perf);
726 }
727 #endif
728 
hif_affinity_mgr_set_affinity(struct hif_opaque_softc * scn)729 void hif_affinity_mgr_set_affinity(struct hif_opaque_softc *scn)
730 {
731 	struct hif_softc *hif_sc = HIF_GET_SOFTC(scn);
732 
733 	if (!hif_sc)
734 		return;
735 
736 	if (!hif_sc->bus_ops.hif_affinity_mgr_set_affinity)
737 		return;
738 
739 	hif_sc->bus_ops.hif_affinity_mgr_set_affinity(hif_sc);
740 }
741