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