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