1  // SPDX-License-Identifier: GPL-2.0-only
2  /*
3   * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
4   * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
5   */
6  
7  #include <linux/delay.h>
8  #include <linux/devcoredump.h>
9  #include <linux/elf.h>
10  #include <linux/jiffies.h>
11  #include <linux/module.h>
12  #include <linux/of.h>
13  #include <linux/of_device.h>
14  #include <linux/of_gpio.h>
15  #include <linux/pm_wakeup.h>
16  #include <linux/reboot.h>
17  #include <linux/rwsem.h>
18  #include <linux/suspend.h>
19  #include <linux/timer.h>
20  #include <linux/thermal.h>
21  #include <linux/version.h>
22  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0))
23  #include <linux/panic_notifier.h>
24  #endif
25  #if IS_ENABLED(CONFIG_QCOM_MINIDUMP)
26  #include <soc/qcom/minidump.h>
27  #endif
28  
29  #include "cnss_plat_ipc_qmi.h"
30  #include "cnss_utils.h"
31  #include "main.h"
32  #include "bus.h"
33  #include "debug.h"
34  #include "genl.h"
35  #include "reg.h"
36  
37  #ifdef CONFIG_CNSS_HW_SECURE_DISABLE
38  #ifdef CONFIG_CNSS_HW_SECURE_SMEM
39  #include <linux/soc/qcom/smem.h>
40  #define PERISEC_SMEM_ID 651
41  #define HW_WIFI_UID 0x508
42  #else
43  #include "smcinvoke.h"
44  #include "smcinvoke_object.h"
45  #include "IClientEnv.h"
46  #define HW_STATE_UID 0x108
47  #define HW_OP_GET_STATE 1
48  #define HW_WIFI_UID 0x508
49  #define FEATURE_NOT_SUPPORTED 12
50  #define PERIPHERAL_NOT_FOUND 10
51  #endif
52  #endif
53  
54  #define CNSS_DUMP_FORMAT_VER		0x11
55  #define CNSS_DUMP_FORMAT_VER_V2		0x22
56  #define CNSS_DUMP_MAGIC_VER_V2		0x42445953
57  #define CNSS_DUMP_NAME			"CNSS_WLAN"
58  #define CNSS_DUMP_DESC_SIZE		0x1000
59  #define CNSS_DUMP_SEG_VER		0x1
60  #define FILE_SYSTEM_READY		1
61  #define FW_READY_TIMEOUT		20000
62  #define FW_ASSERT_TIMEOUT		5000
63  #define CNSS_EVENT_PENDING		2989
64  #define POWER_RESET_MIN_DELAY_MS	100
65  #define MAX_NAME_LEN			12
66  
67  #define CNSS_QUIRKS_DEFAULT		0
68  #ifdef CONFIG_CNSS_EMULATION
69  #define CNSS_MHI_TIMEOUT_DEFAULT	90000
70  #define CNSS_MHI_M2_TIMEOUT_DEFAULT	2000
71  #define CNSS_QMI_TIMEOUT_DEFAULT	90000
72  #else
73  #define CNSS_MHI_TIMEOUT_DEFAULT	0
74  #define CNSS_MHI_M2_TIMEOUT_DEFAULT	25
75  #define CNSS_QMI_TIMEOUT_DEFAULT	10000
76  #endif
77  #define CNSS_BDF_TYPE_DEFAULT		CNSS_BDF_ELF
78  #define CNSS_TIME_SYNC_PERIOD_DEFAULT	900000
79  #define CNSS_MIN_TIME_SYNC_PERIOD	2000
80  #define CNSS_DMS_QMI_CONNECTION_WAIT_MS 50
81  #define CNSS_DMS_QMI_CONNECTION_WAIT_RETRY 200
82  #define CNSS_DAEMON_CONNECT_TIMEOUT_MS  30000
83  #define CNSS_CAL_DB_FILE_NAME "wlfw_cal_db.bin"
84  #define CNSS_CAL_START_PROBE_WAIT_RETRY_MAX 100
85  #define CNSS_CAL_START_PROBE_WAIT_MS	500
86  #define CNSS_TIME_SYNC_PERIOD_INVALID	0xFFFFFFFF
87  
88  enum cnss_cal_db_op {
89  	CNSS_CAL_DB_UPLOAD,
90  	CNSS_CAL_DB_DOWNLOAD,
91  	CNSS_CAL_DB_INVALID_OP,
92  };
93  
94  enum cnss_recovery_type {
95  	CNSS_WLAN_RECOVERY = 0x1,
96  	CNSS_PCSS_RECOVERY = 0x2,
97  };
98  
99  #ifdef CONFIG_CNSS_SUPPORT_DUAL_DEV
100  #define CNSS_MAX_DEV_NUM		2
101  static struct cnss_plat_data *plat_env[CNSS_MAX_DEV_NUM];
102  static atomic_t plat_env_count;
103  #else
104  static struct cnss_plat_data *plat_env;
105  #endif
106  
107  static bool cnss_allow_driver_loading;
108  
109  static struct cnss_fw_files FW_FILES_QCA6174_FW_3_0 = {
110  	"qwlan30.bin", "bdwlan30.bin", "otp30.bin", "utf30.bin",
111  	"utfbd30.bin", "epping30.bin", "evicted30.bin"
112  };
113  
114  static struct cnss_fw_files FW_FILES_DEFAULT = {
115  	"qwlan.bin", "bdwlan.bin", "otp.bin", "utf.bin",
116  	"utfbd.bin", "epping.bin", "evicted.bin"
117  };
118  
119  struct cnss_driver_event {
120  	struct list_head list;
121  	enum cnss_driver_event_type type;
122  	bool sync;
123  	struct completion complete;
124  	int ret;
125  	void *data;
126  };
127  
cnss_check_driver_loading_allowed(void)128  bool cnss_check_driver_loading_allowed(void)
129  {
130  	return cnss_allow_driver_loading;
131  }
132  
133  #ifdef CONFIG_CNSS_SUPPORT_DUAL_DEV
cnss_init_plat_env_count(void)134  static void cnss_init_plat_env_count(void)
135  {
136  	atomic_set(&plat_env_count, 0);
137  }
138  
cnss_inc_plat_env_count(void)139  static void cnss_inc_plat_env_count(void)
140  {
141  	atomic_inc(&plat_env_count);
142  }
143  
cnss_dec_plat_env_count(void)144  static void cnss_dec_plat_env_count(void)
145  {
146  	atomic_dec(&plat_env_count);
147  }
148  
cnss_get_plat_env_count(void)149  static int cnss_get_plat_env_count(void)
150  {
151  	return atomic_read(&plat_env_count);
152  }
153  
cnss_get_max_plat_env_count(void)154  int cnss_get_max_plat_env_count(void)
155  {
156  	return CNSS_MAX_DEV_NUM;
157  }
158  
cnss_set_plat_priv(struct platform_device * plat_dev,struct cnss_plat_data * plat_priv)159  static void cnss_set_plat_priv(struct platform_device *plat_dev,
160  			       struct cnss_plat_data *plat_priv)
161  {
162  	int env_count = cnss_get_plat_env_count();
163  
164  	cnss_pr_dbg("Set plat_priv at %d", env_count);
165  	if (plat_priv) {
166  		plat_priv->plat_idx = env_count;
167  		plat_env[plat_priv->plat_idx] = plat_priv;
168  		cnss_inc_plat_env_count();
169  	}
170  }
171  
cnss_get_plat_priv(struct platform_device * plat_dev)172  struct cnss_plat_data *cnss_get_plat_priv(struct platform_device
173  						 *plat_dev)
174  {
175  	int i;
176  
177  	if (!plat_dev)
178  		return NULL;
179  
180  	for (i = 0; i < CNSS_MAX_DEV_NUM; i++) {
181  		if (plat_env[i] && plat_env[i]->plat_dev == plat_dev)
182  			return plat_env[i];
183  	}
184  	return NULL;
185  }
186  
cnss_get_first_plat_priv(struct platform_device * plat_dev)187  struct cnss_plat_data *cnss_get_first_plat_priv(struct platform_device
188  						 *plat_dev)
189  {
190  	int i;
191  
192  	if (!plat_dev) {
193  		for (i = 0; i < CNSS_MAX_DEV_NUM; i++) {
194  			if (plat_env[i])
195  				return plat_env[i];
196  		}
197  	}
198  	return NULL;
199  }
200  
cnss_clear_plat_priv(struct cnss_plat_data * plat_priv)201  static void cnss_clear_plat_priv(struct cnss_plat_data *plat_priv)
202  {
203  	cnss_pr_dbg("Clear plat_priv at %d", plat_priv->plat_idx);
204  	plat_env[plat_priv->plat_idx] = NULL;
205  	cnss_dec_plat_env_count();
206  }
207  
cnss_set_device_name(struct cnss_plat_data * plat_priv)208  static int cnss_set_device_name(struct cnss_plat_data *plat_priv)
209  {
210  	snprintf(plat_priv->device_name, sizeof(plat_priv->device_name),
211  		 "wlan_%d", plat_priv->plat_idx);
212  
213  	return 0;
214  }
215  
cnss_plat_env_available(void)216  static int cnss_plat_env_available(void)
217  {
218  	int ret = 0;
219  	int env_count = cnss_get_plat_env_count();
220  
221  	if (env_count >= CNSS_MAX_DEV_NUM) {
222  		cnss_pr_err("ERROR: No space to store plat_priv\n");
223  		ret = -ENOMEM;
224  	}
225  	return ret;
226  }
227  
cnss_get_plat_env(int index)228  struct cnss_plat_data *cnss_get_plat_env(int index)
229  {
230  	return plat_env[index];
231  }
232  
cnss_get_plat_priv_by_rc_num(int rc_num)233  struct cnss_plat_data *cnss_get_plat_priv_by_rc_num(int rc_num)
234  {
235  	int i;
236  
237  	for (i = 0; i < CNSS_MAX_DEV_NUM; i++) {
238  		if (plat_env[i] && plat_env[i]->rc_num == rc_num)
239  			return plat_env[i];
240  	}
241  	return NULL;
242  }
243  
244  static inline int
cnss_get_qrtr_node_id(struct cnss_plat_data * plat_priv)245  cnss_get_qrtr_node_id(struct cnss_plat_data *plat_priv)
246  {
247  	return of_property_read_u32(plat_priv->dev_node,
248  		"qcom,qrtr_node_id", &plat_priv->qrtr_node_id);
249  }
250  
cnss_get_qrtr_info(struct cnss_plat_data * plat_priv)251  void cnss_get_qrtr_info(struct cnss_plat_data *plat_priv)
252  {
253  	int ret = 0;
254  
255  	ret = cnss_get_qrtr_node_id(plat_priv);
256  	if (ret) {
257  		cnss_pr_warn("Failed to find qrtr_node_id err=%d\n", ret);
258  		plat_priv->qrtr_node_id = 0;
259  		plat_priv->wlfw_service_instance_id = 0;
260  	} else {
261  		plat_priv->wlfw_service_instance_id = plat_priv->qrtr_node_id +
262  						      QRTR_NODE_FW_ID_BASE;
263  		cnss_pr_dbg("service_instance_id=0x%x\n",
264  			    plat_priv->wlfw_service_instance_id);
265  	}
266  }
267  
268  static inline int
cnss_get_pld_bus_ops_name(struct cnss_plat_data * plat_priv)269  cnss_get_pld_bus_ops_name(struct cnss_plat_data *plat_priv)
270  {
271  	return of_property_read_string(plat_priv->plat_dev->dev.of_node,
272  				       "qcom,pld_bus_ops_name",
273  				       &plat_priv->pld_bus_ops_name);
274  }
275  
276  #else
cnss_init_plat_env_count(void)277  static void cnss_init_plat_env_count(void)
278  {
279  }
280  
cnss_set_plat_priv(struct platform_device * plat_dev,struct cnss_plat_data * plat_priv)281  static void cnss_set_plat_priv(struct platform_device *plat_dev,
282  			       struct cnss_plat_data *plat_priv)
283  {
284  	plat_env = plat_priv;
285  }
286  
cnss_get_plat_priv(struct platform_device * plat_dev)287  struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev)
288  {
289  	return plat_env;
290  }
291  
cnss_clear_plat_priv(struct cnss_plat_data * plat_priv)292  static void cnss_clear_plat_priv(struct cnss_plat_data *plat_priv)
293  {
294  	plat_env = NULL;
295  }
296  
cnss_set_device_name(struct cnss_plat_data * plat_priv)297  static int cnss_set_device_name(struct cnss_plat_data *plat_priv)
298  {
299  	snprintf(plat_priv->device_name, sizeof(plat_priv->device_name),
300  		 "wlan");
301  	return 0;
302  }
303  
cnss_plat_env_available(void)304  static int cnss_plat_env_available(void)
305  {
306  	return 0;
307  }
308  
cnss_get_plat_priv_by_rc_num(int rc_num)309  struct cnss_plat_data *cnss_get_plat_priv_by_rc_num(int rc_num)
310  {
311  	return cnss_bus_dev_to_plat_priv(NULL);
312  }
313  
cnss_get_qrtr_info(struct cnss_plat_data * plat_priv)314  void cnss_get_qrtr_info(struct cnss_plat_data *plat_priv)
315  {
316  }
317  
318  static int
cnss_get_pld_bus_ops_name(struct cnss_plat_data * plat_priv)319  cnss_get_pld_bus_ops_name(struct cnss_plat_data *plat_priv)
320  {
321  	return 0;
322  }
323  #endif
324  
cnss_get_sleep_clk_supported(struct cnss_plat_data * plat_priv)325  void cnss_get_sleep_clk_supported(struct cnss_plat_data *plat_priv)
326  {
327  	plat_priv->sleep_clk = of_property_read_bool(plat_priv->dev_node,
328  						     "qcom,sleep-clk-support");
329  	cnss_pr_dbg("qcom,sleep-clk-support is %d\n",
330  		    plat_priv->sleep_clk);
331  }
332  
cnss_get_bwscal_info(struct cnss_plat_data * plat_priv)333  void cnss_get_bwscal_info(struct cnss_plat_data *plat_priv)
334  {
335  	plat_priv->no_bwscale = of_property_read_bool(plat_priv->dev_node,
336  						      "qcom,no-bwscale");
337  }
338  
339  static inline int
cnss_get_rc_num(struct cnss_plat_data * plat_priv)340  cnss_get_rc_num(struct cnss_plat_data *plat_priv)
341  {
342  	return of_property_read_u32(plat_priv->plat_dev->dev.of_node,
343  		"qcom,wlan-rc-num", &plat_priv->rc_num);
344  }
345  
cnss_is_dual_wlan_enabled(void)346  bool cnss_is_dual_wlan_enabled(void)
347  {
348  	return IS_ENABLED(CONFIG_CNSS_SUPPORT_DUAL_DEV);
349  }
350  
351  /**
352   * cnss_get_mem_seg_count - Get segment count of memory
353   * @type: memory type
354   * @seg: segment count
355   *
356   * Return: 0 on success, negative value on failure
357   */
cnss_get_mem_seg_count(enum cnss_remote_mem_type type,u32 * seg)358  int cnss_get_mem_seg_count(enum cnss_remote_mem_type type, u32 *seg)
359  {
360  	struct cnss_plat_data *plat_priv;
361  
362  	plat_priv = cnss_get_plat_priv(NULL);
363  	if (!plat_priv)
364  		return -ENODEV;
365  
366  	switch (type) {
367  	case CNSS_REMOTE_MEM_TYPE_FW:
368  		*seg = plat_priv->fw_mem_seg_len;
369  		break;
370  	case CNSS_REMOTE_MEM_TYPE_QDSS:
371  		*seg = plat_priv->qdss_mem_seg_len;
372  		break;
373  	default:
374  		return -EINVAL;
375  	}
376  
377  	return 0;
378  }
379  EXPORT_SYMBOL(cnss_get_mem_seg_count);
380  
381  /**
382   * cnss_get_wifi_kobject -return wifi kobject
383   * Return: Null, to maintain driver comnpatibilty
384   */
cnss_get_wifi_kobj(struct device * dev)385  struct kobject *cnss_get_wifi_kobj(struct device *dev)
386  {
387  	struct cnss_plat_data *plat_priv;
388  
389  	plat_priv = cnss_get_plat_priv(NULL);
390  	if (!plat_priv)
391  		return NULL;
392  
393  	return plat_priv->wifi_kobj;
394  }
395  EXPORT_SYMBOL(cnss_get_wifi_kobj);
396  
397  /**
398   * cnss_get_mem_segment_info - Get memory info of different type
399   * @type: memory type
400   * @segment: array to save the segment info
401   * @seg: segment count
402   *
403   * Return: 0 on success, negative value on failure
404   */
cnss_get_mem_segment_info(enum cnss_remote_mem_type type,struct cnss_mem_segment segment[],u32 segment_count)405  int cnss_get_mem_segment_info(enum cnss_remote_mem_type type,
406  			      struct cnss_mem_segment segment[],
407  			      u32 segment_count)
408  {
409  	struct cnss_plat_data *plat_priv;
410  	u32 i;
411  
412  	plat_priv = cnss_get_plat_priv(NULL);
413  	if (!plat_priv)
414  		return -ENODEV;
415  
416  	switch (type) {
417  	case CNSS_REMOTE_MEM_TYPE_FW:
418  		if (segment_count > plat_priv->fw_mem_seg_len)
419  			segment_count = plat_priv->fw_mem_seg_len;
420  		for (i = 0; i < segment_count; i++) {
421  			segment[i].size = plat_priv->fw_mem[i].size;
422  			segment[i].va = plat_priv->fw_mem[i].va;
423  			segment[i].pa = plat_priv->fw_mem[i].pa;
424  		}
425  		break;
426  	case CNSS_REMOTE_MEM_TYPE_QDSS:
427  		if (segment_count > plat_priv->qdss_mem_seg_len)
428  			segment_count = plat_priv->qdss_mem_seg_len;
429  		for (i = 0; i < segment_count; i++) {
430  			segment[i].size = plat_priv->qdss_mem[i].size;
431  			segment[i].va = plat_priv->qdss_mem[i].va;
432  			segment[i].pa = plat_priv->qdss_mem[i].pa;
433  		}
434  		break;
435  	default:
436  		return -EINVAL;
437  	}
438  
439  	return 0;
440  }
441  EXPORT_SYMBOL(cnss_get_mem_segment_info);
442  
cnss_get_audio_iommu_domain(struct cnss_plat_data * plat_priv)443  static int cnss_get_audio_iommu_domain(struct cnss_plat_data *plat_priv)
444  {
445  	struct device_node *audio_ion_node;
446  	struct platform_device *audio_ion_pdev;
447  
448  	audio_ion_node = of_find_compatible_node(NULL, NULL,
449  						 "qcom,msm-audio-ion");
450  	if (!audio_ion_node) {
451  		cnss_pr_err("Unable to get Audio ion node");
452  		return -EINVAL;
453  	}
454  
455  	audio_ion_pdev = of_find_device_by_node(audio_ion_node);
456  	of_node_put(audio_ion_node);
457  	if (!audio_ion_pdev) {
458  		cnss_pr_err("Unable to get Audio ion platform device");
459  		return -EINVAL;
460  	}
461  
462  	plat_priv->audio_iommu_domain =
463  				iommu_get_domain_for_dev(&audio_ion_pdev->dev);
464  	put_device(&audio_ion_pdev->dev);
465  	if (!plat_priv->audio_iommu_domain) {
466  		cnss_pr_err("Unable to get Audio ion iommu domain");
467  		return -EINVAL;
468  	}
469  
470  	return 0;
471  }
472  
cnss_get_audio_shared_iommu_group_cap(struct device * dev)473  bool cnss_get_audio_shared_iommu_group_cap(struct device *dev)
474  {
475  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
476  	struct device_node *audio_ion_node;
477  	struct device_node *cnss_iommu_group_node;
478  	struct device_node *audio_iommu_group_node;
479  
480  	if (!plat_priv)
481  		return false;
482  
483  	audio_ion_node = of_find_compatible_node(NULL, NULL,
484  						 "qcom,msm-audio-ion");
485  	if (!audio_ion_node) {
486  		cnss_pr_err("Unable to get Audio ion node");
487  		return false;
488  	}
489  
490  	audio_iommu_group_node = of_parse_phandle(audio_ion_node,
491  						  "qcom,iommu-group", 0);
492  	of_node_put(audio_ion_node);
493  	if (!audio_iommu_group_node) {
494  		cnss_pr_err("Unable to get audio iommu group phandle");
495  		return false;
496  	}
497  	of_node_put(audio_iommu_group_node);
498  
499  	cnss_iommu_group_node = of_parse_phandle(dev->of_node,
500  						 "qcom,iommu-group", 0);
501  	if (!cnss_iommu_group_node) {
502  		cnss_pr_err("Unable to get cnss iommu group phandle");
503  		return false;
504  	}
505  	of_node_put(cnss_iommu_group_node);
506  
507  	if (cnss_iommu_group_node == audio_iommu_group_node) {
508  		plat_priv->is_audio_shared_iommu_group = true;
509  		cnss_pr_info("CNSS and Audio share IOMMU group");
510  	} else {
511  		cnss_pr_info("CNSS and Audio do not share IOMMU group");
512  	}
513  
514  	return plat_priv->is_audio_shared_iommu_group;
515  }
516  EXPORT_SYMBOL(cnss_get_audio_shared_iommu_group_cap);
517  
cnss_set_feature_list(struct cnss_plat_data * plat_priv,enum cnss_feature_v01 feature)518  int cnss_set_feature_list(struct cnss_plat_data *plat_priv,
519  			  enum cnss_feature_v01 feature)
520  {
521  	if (unlikely(!plat_priv || feature >= CNSS_MAX_FEATURE_V01))
522  		return -EINVAL;
523  
524  	plat_priv->feature_list |= 1 << feature;
525  	return 0;
526  }
527  
cnss_clear_feature_list(struct cnss_plat_data * plat_priv,enum cnss_feature_v01 feature)528  int cnss_clear_feature_list(struct cnss_plat_data *plat_priv,
529  			    enum cnss_feature_v01 feature)
530  {
531  	if (unlikely(!plat_priv || feature >= CNSS_MAX_FEATURE_V01))
532  		return -EINVAL;
533  
534  	plat_priv->feature_list &= ~(1 << feature);
535  	return 0;
536  }
537  
cnss_get_feature_list(struct cnss_plat_data * plat_priv,u64 * feature_list)538  int cnss_get_feature_list(struct cnss_plat_data *plat_priv,
539  			  u64 *feature_list)
540  {
541  	if (unlikely(!plat_priv))
542  		return -EINVAL;
543  
544  	*feature_list = plat_priv->feature_list;
545  	return 0;
546  }
547  
cnss_get_platform_name(struct cnss_plat_data * plat_priv,char * buf,const size_t buf_len)548  size_t cnss_get_platform_name(struct cnss_plat_data *plat_priv,
549  			      char *buf, const size_t buf_len)
550  {
551  	if (unlikely(!plat_priv || !buf || !buf_len))
552  		return 0;
553  
554  	if (of_property_read_bool(plat_priv->plat_dev->dev.of_node,
555  				  "platform-name-required")) {
556  		struct device_node *root;
557  
558  		root = of_find_node_by_path("/");
559  		if (root) {
560  			const char *model;
561  			size_t model_len;
562  
563  			model = of_get_property(root, "model", NULL);
564  			if (model) {
565  				model_len = strlcpy(buf, model, buf_len);
566  				cnss_pr_dbg("Platform name: %s (%zu)\n",
567  					    buf, model_len);
568  
569  				return model_len;
570  			}
571  		}
572  	}
573  
574  	return 0;
575  }
576  
cnss_pm_stay_awake(struct cnss_plat_data * plat_priv)577  void cnss_pm_stay_awake(struct cnss_plat_data *plat_priv)
578  {
579  	if (atomic_inc_return(&plat_priv->pm_count) != 1)
580  		return;
581  
582  	cnss_pr_dbg("PM stay awake, state: 0x%lx, count: %d\n",
583  		    plat_priv->driver_state,
584  		    atomic_read(&plat_priv->pm_count));
585  	pm_stay_awake(&plat_priv->plat_dev->dev);
586  }
587  
cnss_pm_relax(struct cnss_plat_data * plat_priv)588  void cnss_pm_relax(struct cnss_plat_data *plat_priv)
589  {
590  	int r = atomic_dec_return(&plat_priv->pm_count);
591  
592  	WARN_ON(r < 0);
593  
594  	if (r != 0)
595  		return;
596  
597  	cnss_pr_dbg("PM relax, state: 0x%lx, count: %d\n",
598  		    plat_priv->driver_state,
599  		    atomic_read(&plat_priv->pm_count));
600  	pm_relax(&plat_priv->plat_dev->dev);
601  }
602  
cnss_get_fw_files_for_target(struct device * dev,struct cnss_fw_files * pfw_files,u32 target_type,u32 target_version)603  int cnss_get_fw_files_for_target(struct device *dev,
604  				 struct cnss_fw_files *pfw_files,
605  				 u32 target_type, u32 target_version)
606  {
607  	if (!pfw_files)
608  		return -ENODEV;
609  
610  	switch (target_version) {
611  	case QCA6174_REV3_VERSION:
612  	case QCA6174_REV3_2_VERSION:
613  		memcpy(pfw_files, &FW_FILES_QCA6174_FW_3_0, sizeof(*pfw_files));
614  		break;
615  	default:
616  		memcpy(pfw_files, &FW_FILES_DEFAULT, sizeof(*pfw_files));
617  		cnss_pr_err("Unknown target version, type: 0x%X, version: 0x%X",
618  			    target_type, target_version);
619  		break;
620  	}
621  
622  	return 0;
623  }
624  EXPORT_SYMBOL(cnss_get_fw_files_for_target);
625  
cnss_get_platform_cap(struct device * dev,struct cnss_platform_cap * cap)626  int cnss_get_platform_cap(struct device *dev, struct cnss_platform_cap *cap)
627  {
628  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
629  
630  	if (!plat_priv)
631  		return -ENODEV;
632  
633  	if (!cap)
634  		return -EINVAL;
635  
636  	*cap = plat_priv->cap;
637  	cnss_pr_dbg("Platform cap_flag is 0x%x\n", cap->cap_flag);
638  
639  	return 0;
640  }
641  EXPORT_SYMBOL(cnss_get_platform_cap);
642  
643  /**
644   * cnss_get_fw_cap - Check whether FW supports specific capability or not
645   * @dev: Device
646   * @fw_cap: FW Capability which needs to be checked
647   *
648   * Return: TRUE if supported, FALSE on failure or if not supported
649   */
cnss_get_fw_cap(struct device * dev,enum cnss_fw_caps fw_cap)650  bool cnss_get_fw_cap(struct device *dev, enum cnss_fw_caps fw_cap)
651  {
652  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
653  	bool is_supported = false;
654  
655  	if (!plat_priv)
656  		return is_supported;
657  
658  	if (!plat_priv->fw_caps)
659  		return is_supported;
660  
661  	switch (fw_cap) {
662  	case CNSS_FW_CAP_DIRECT_LINK_SUPPORT:
663  		is_supported = !!(plat_priv->fw_caps &
664  				  QMI_WLFW_DIRECT_LINK_SUPPORT_V01);
665  		break;
666  	case CNSS_FW_CAP_CALDB_SEG_DDR_SUPPORT:
667  		is_supported = !!(plat_priv->fw_caps &
668  				  QMI_WLFW_CALDB_SEG_DDR_SUPPORT_V01);
669  		break;
670  	default:
671  		cnss_pr_err("Invalid FW Capability: 0x%x\n", fw_cap);
672  	}
673  
674  	cnss_pr_dbg("FW Capability 0x%x is %s\n", fw_cap,
675  		    is_supported ? "supported" : "not supported");
676  	return is_supported;
677  }
678  EXPORT_SYMBOL(cnss_get_fw_cap);
679  
680  /**
681   * cnss_audio_is_direct_link_supported - Check whether Audio can be used for direct link support
682   * @dev: Device
683   *
684   * Return: TRUE if supported, FALSE on failure or if not supported
685   */
cnss_audio_is_direct_link_supported(struct device * dev)686  bool cnss_audio_is_direct_link_supported(struct device *dev)
687  {
688  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
689  	bool is_supported = false;
690  
691  	if (!plat_priv) {
692  		cnss_pr_err("plat_priv not available to check audio direct link cap\n");
693  		return is_supported;
694  	}
695  
696  	if (cnss_get_audio_iommu_domain(plat_priv) == 0)
697  		is_supported = true;
698  
699  	return is_supported;
700  }
701  EXPORT_SYMBOL(cnss_audio_is_direct_link_supported);
702  
703  
cnss_request_pm_qos(struct device * dev,u32 qos_val)704  void cnss_request_pm_qos(struct device *dev, u32 qos_val)
705  {
706  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
707  
708  	if (!plat_priv)
709  		return;
710  
711  	cpu_latency_qos_add_request(&plat_priv->qos_request, qos_val);
712  }
713  EXPORT_SYMBOL(cnss_request_pm_qos);
714  
cnss_remove_pm_qos(struct device * dev)715  void cnss_remove_pm_qos(struct device *dev)
716  {
717  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
718  
719  	if (!plat_priv)
720  		return;
721  
722  	cpu_latency_qos_remove_request(&plat_priv->qos_request);
723  }
724  EXPORT_SYMBOL(cnss_remove_pm_qos);
725  
cnss_wlan_enable(struct device * dev,struct cnss_wlan_enable_cfg * config,enum cnss_driver_mode mode,const char * host_version)726  int cnss_wlan_enable(struct device *dev,
727  		     struct cnss_wlan_enable_cfg *config,
728  		     enum cnss_driver_mode mode,
729  		     const char *host_version)
730  {
731  	int ret = 0;
732  	struct cnss_plat_data *plat_priv;
733  
734  	if (!dev) {
735  		cnss_pr_err("Invalid dev pointer\n");
736  		return -EINVAL;
737  	}
738  
739  	plat_priv = cnss_bus_dev_to_plat_priv(dev);
740  	if (!plat_priv)
741  		return -ENODEV;
742  
743  	if (plat_priv->device_id == QCA6174_DEVICE_ID)
744  		return 0;
745  
746  	if (test_bit(QMI_BYPASS, &plat_priv->ctrl_params.quirks))
747  		return 0;
748  
749  	if (!config || !host_version) {
750  		cnss_pr_err("Invalid config or host_version pointer\n");
751  		return -EINVAL;
752  	}
753  
754  	cnss_pr_dbg("Mode: %d, config: %pK, host_version: %s\n",
755  		    mode, config, host_version);
756  
757  	if (mode == CNSS_WALTEST || mode == CNSS_CCPM)
758  		goto skip_cfg;
759  
760  	if (plat_priv->device_id == QCN7605_DEVICE_ID)
761  		config->send_msi_ce = true;
762  
763  	ret = cnss_wlfw_wlan_cfg_send_sync(plat_priv, config, host_version);
764  	if (ret)
765  		goto out;
766  
767  skip_cfg:
768  	ret = cnss_wlfw_wlan_mode_send_sync(plat_priv, mode);
769  out:
770  	return ret;
771  }
772  EXPORT_SYMBOL(cnss_wlan_enable);
773  
cnss_wlan_disable(struct device * dev,enum cnss_driver_mode mode)774  int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode)
775  {
776  	int ret = 0;
777  	struct cnss_plat_data *plat_priv;
778  
779  	if (!dev) {
780  		cnss_pr_err("Invalid dev pointer\n");
781  		return -EINVAL;
782  	}
783  
784  	plat_priv = cnss_bus_dev_to_plat_priv(dev);
785  	if (!plat_priv)
786  		return -ENODEV;
787  
788  	if (plat_priv->device_id == QCA6174_DEVICE_ID)
789  		return 0;
790  
791  	if (test_bit(QMI_BYPASS, &plat_priv->ctrl_params.quirks))
792  		return 0;
793  
794  	ret = cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_OFF);
795  	cnss_bus_free_qdss_mem(plat_priv);
796  
797  	return ret;
798  }
799  EXPORT_SYMBOL(cnss_wlan_disable);
800  
801  #if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0))
cnss_iommu_map(struct iommu_domain * domain,unsigned long iova,phys_addr_t paddr,size_t size,int prot)802  int cnss_iommu_map(struct iommu_domain *domain,
803  		   unsigned long iova, phys_addr_t paddr, size_t size, int prot)
804  {
805  	return iommu_map(domain, iova, paddr, size, prot);
806  }
807  #else
cnss_iommu_map(struct iommu_domain * domain,unsigned long iova,phys_addr_t paddr,size_t size,int prot)808  int cnss_iommu_map(struct iommu_domain *domain,
809  		   unsigned long iova, phys_addr_t paddr, size_t size, int prot)
810  {
811  	return iommu_map(domain, iova, paddr, size, prot, GFP_KERNEL);
812  }
813  #endif
814  
cnss_audio_smmu_map(struct device * dev,phys_addr_t paddr,dma_addr_t iova,size_t size)815  int cnss_audio_smmu_map(struct device *dev, phys_addr_t paddr,
816  			dma_addr_t iova, size_t size)
817  {
818  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
819  	uint32_t page_offset;
820  
821  	if (!plat_priv)
822  		return -ENODEV;
823  
824  	if (!plat_priv->audio_iommu_domain)
825  		return -EINVAL;
826  
827  	if (plat_priv->is_audio_shared_iommu_group)
828  		return 0;
829  
830  	page_offset = iova & (PAGE_SIZE - 1);
831  	if (page_offset + size > PAGE_SIZE)
832  		size += PAGE_SIZE;
833  
834  	iova -= page_offset;
835  	paddr -= page_offset;
836  
837  	return cnss_iommu_map(plat_priv->audio_iommu_domain, iova, paddr,
838  			      roundup(size, PAGE_SIZE), IOMMU_READ |
839  			      IOMMU_WRITE | IOMMU_CACHE);
840  }
841  EXPORT_SYMBOL(cnss_audio_smmu_map);
842  
cnss_audio_smmu_unmap(struct device * dev,dma_addr_t iova,size_t size)843  void cnss_audio_smmu_unmap(struct device *dev, dma_addr_t iova, size_t size)
844  {
845  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
846  	uint32_t page_offset;
847  
848  	if (!plat_priv || !plat_priv->audio_iommu_domain ||
849  	    plat_priv->is_audio_shared_iommu_group)
850  		return;
851  
852  	page_offset = iova & (PAGE_SIZE - 1);
853  	if (page_offset + size > PAGE_SIZE)
854  		size += PAGE_SIZE;
855  
856  	iova -= page_offset;
857  
858  	iommu_unmap(plat_priv->audio_iommu_domain, iova,
859  		    roundup(size, PAGE_SIZE));
860  }
861  EXPORT_SYMBOL(cnss_audio_smmu_unmap);
862  
cnss_get_fw_lpass_shared_mem(struct device * dev,dma_addr_t * iova,size_t * size)863  int cnss_get_fw_lpass_shared_mem(struct device *dev, dma_addr_t *iova,
864  				 size_t *size)
865  {
866  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
867  	uint8_t i;
868  
869  	if (!plat_priv)
870  		return -EINVAL;
871  
872  	for (i = 0; i < plat_priv->fw_mem_seg_len; i++) {
873  		if (plat_priv->fw_mem[i].type ==
874  		    QMI_WLFW_MEM_LPASS_SHARED_V01) {
875  			*iova = plat_priv->fw_mem[i].pa;
876  			*size = plat_priv->fw_mem[i].size;
877  			return 0;
878  		}
879  	}
880  
881  	return -EINVAL;
882  }
883  EXPORT_SYMBOL(cnss_get_fw_lpass_shared_mem);
884  
cnss_athdiag_read(struct device * dev,u32 offset,u32 mem_type,u32 data_len,u8 * output)885  int cnss_athdiag_read(struct device *dev, u32 offset, u32 mem_type,
886  		      u32 data_len, u8 *output)
887  {
888  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
889  	int ret = 0;
890  
891  	if (!plat_priv) {
892  		cnss_pr_err("plat_priv is NULL!\n");
893  		return -EINVAL;
894  	}
895  
896  	if (plat_priv->device_id == QCA6174_DEVICE_ID)
897  		return 0;
898  
899  	if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
900  		cnss_pr_err("Invalid state for athdiag read: 0x%lx\n",
901  			    plat_priv->driver_state);
902  		ret = -EINVAL;
903  		goto out;
904  	}
905  
906  	ret = cnss_wlfw_athdiag_read_send_sync(plat_priv, offset, mem_type,
907  					       data_len, output);
908  
909  out:
910  	return ret;
911  }
912  EXPORT_SYMBOL(cnss_athdiag_read);
913  
cnss_athdiag_write(struct device * dev,u32 offset,u32 mem_type,u32 data_len,u8 * input)914  int cnss_athdiag_write(struct device *dev, u32 offset, u32 mem_type,
915  		       u32 data_len, u8 *input)
916  {
917  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
918  	int ret = 0;
919  
920  	if (!plat_priv) {
921  		cnss_pr_err("plat_priv is NULL!\n");
922  		return -EINVAL;
923  	}
924  
925  	if (plat_priv->device_id == QCA6174_DEVICE_ID)
926  		return 0;
927  
928  	if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
929  		cnss_pr_err("Invalid state for athdiag write: 0x%lx\n",
930  			    plat_priv->driver_state);
931  		ret = -EINVAL;
932  		goto out;
933  	}
934  
935  	ret = cnss_wlfw_athdiag_write_send_sync(plat_priv, offset, mem_type,
936  						data_len, input);
937  
938  out:
939  	return ret;
940  }
941  EXPORT_SYMBOL(cnss_athdiag_write);
942  
cnss_set_fw_log_mode(struct device * dev,u8 fw_log_mode)943  int cnss_set_fw_log_mode(struct device *dev, u8 fw_log_mode)
944  {
945  	struct cnss_plat_data *plat_priv;
946  
947  	if (!dev) {
948  		cnss_pr_err("Invalid dev pointer\n");
949  		return -EINVAL;
950  	}
951  
952  	plat_priv = cnss_bus_dev_to_plat_priv(dev);
953  	if (!plat_priv)
954  		return -ENODEV;
955  
956  	if (plat_priv->device_id == QCA6174_DEVICE_ID)
957  		return 0;
958  
959  	return cnss_wlfw_ini_send_sync(plat_priv, fw_log_mode);
960  }
961  EXPORT_SYMBOL(cnss_set_fw_log_mode);
962  
cnss_set_pcie_gen_speed(struct device * dev,u8 pcie_gen_speed)963  int cnss_set_pcie_gen_speed(struct device *dev, u8 pcie_gen_speed)
964  {
965  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
966  
967  	if (!plat_priv)
968  		return -EINVAL;
969  
970  	if (!plat_priv->fw_pcie_gen_switch) {
971  		cnss_pr_err("Firmware does not support PCIe gen switch\n");
972  		return -EOPNOTSUPP;
973  	}
974  
975  	if (pcie_gen_speed < QMI_PCIE_GEN_SPEED_1_V01 ||
976  	    pcie_gen_speed > QMI_PCIE_GEN_SPEED_3_V01)
977  		return -EINVAL;
978  
979  	cnss_pr_dbg("WLAN provided PCIE gen speed: %d\n", pcie_gen_speed);
980  	plat_priv->pcie_gen_speed = pcie_gen_speed;
981  	return 0;
982  }
983  EXPORT_SYMBOL(cnss_set_pcie_gen_speed);
984  
cnss_is_aux_support_enabled(struct cnss_plat_data * plat_priv)985  static bool cnss_is_aux_support_enabled(struct cnss_plat_data *plat_priv)
986  {
987  	switch (plat_priv->device_id) {
988  	case PEACH_DEVICE_ID:
989  		if (!plat_priv->fw_aux_uc_support) {
990  			cnss_pr_dbg("FW does not support aux uc capability\n");
991  			return false;
992  		}
993  		break;
994  	default:
995  		cnss_pr_dbg("Host does not support aux uc capability\n");
996  		return false;
997  	}
998  
999  	return true;
1000  }
1001  
cnss_fw_mem_ready_hdlr(struct cnss_plat_data * plat_priv)1002  static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
1003  {
1004  	int ret = 0;
1005  
1006  	if (!plat_priv)
1007  		return -ENODEV;
1008  
1009  	set_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
1010  
1011  	ret = cnss_wlfw_tgt_cap_send_sync(plat_priv);
1012  	if (ret)
1013  		goto out;
1014  
1015  	cnss_bus_load_tme_patch(plat_priv);
1016  
1017  	cnss_wlfw_tme_patch_dnld_send_sync(plat_priv,
1018  					   WLFW_TME_LITE_PATCH_FILE_V01);
1019  
1020  	if (plat_priv->hds_enabled)
1021  		cnss_wlfw_bdf_dnld_send_sync(plat_priv, CNSS_BDF_HDS);
1022  
1023  	cnss_wlfw_bdf_dnld_send_sync(plat_priv, CNSS_BDF_REGDB);
1024  
1025  	if (plat_priv->device_id == QCN7605_DEVICE_ID)
1026  		plat_priv->ctrl_params.bdf_type = CNSS_BDF_BIN;
1027  
1028  	ret = cnss_wlfw_bdf_dnld_send_sync(plat_priv,
1029  					   plat_priv->ctrl_params.bdf_type);
1030  	if (ret)
1031  		goto out;
1032  
1033  	if (plat_priv->device_id == QCN7605_DEVICE_ID)
1034  		return 0;
1035  
1036  	ret = cnss_bus_load_m3(plat_priv);
1037  	if (ret)
1038  		goto out;
1039  
1040  	ret = cnss_wlfw_m3_dnld_send_sync(plat_priv);
1041  	if (ret)
1042  		goto out;
1043  
1044  	if (cnss_is_aux_support_enabled(plat_priv)) {
1045  		ret = cnss_bus_load_aux(plat_priv);
1046  		if (ret)
1047  			goto out;
1048  
1049  		ret = cnss_wlfw_aux_dnld_send_sync(plat_priv);
1050  		if (ret)
1051  			goto out;
1052  	}
1053  
1054  	cnss_wlfw_qdss_dnld_send_sync(plat_priv);
1055  
1056  	return 0;
1057  out:
1058  	return ret;
1059  }
1060  
cnss_request_antenna_sharing(struct cnss_plat_data * plat_priv)1061  static int cnss_request_antenna_sharing(struct cnss_plat_data *plat_priv)
1062  {
1063  	int ret = 0;
1064  
1065  	if (!plat_priv->antenna) {
1066  		ret = cnss_wlfw_antenna_switch_send_sync(plat_priv);
1067  		if (ret)
1068  			goto out;
1069  	}
1070  
1071  	if (test_bit(CNSS_COEX_CONNECTED, &plat_priv->driver_state)) {
1072  		ret = coex_antenna_switch_to_wlan_send_sync_msg(plat_priv);
1073  		if (ret)
1074  			goto out;
1075  	}
1076  
1077  	ret = cnss_wlfw_antenna_grant_send_sync(plat_priv);
1078  	if (ret)
1079  		goto out;
1080  
1081  	return 0;
1082  
1083  out:
1084  	return ret;
1085  }
1086  
cnss_release_antenna_sharing(struct cnss_plat_data * plat_priv)1087  static void cnss_release_antenna_sharing(struct cnss_plat_data *plat_priv)
1088  {
1089  	if (test_bit(CNSS_COEX_CONNECTED, &plat_priv->driver_state))
1090  		coex_antenna_switch_to_mdm_send_sync_msg(plat_priv);
1091  }
1092  
cnss_setup_dms_mac(struct cnss_plat_data * plat_priv)1093  static int cnss_setup_dms_mac(struct cnss_plat_data *plat_priv)
1094  {
1095  	u32 i;
1096  	int ret = 0;
1097  	struct cnss_plat_ipc_daemon_config *cfg;
1098  
1099  	ret = cnss_qmi_get_dms_mac(plat_priv);
1100  	if (ret == 0 && plat_priv->dms.mac_valid)
1101  		goto qmi_send;
1102  
1103  	/* DTSI property use-nv-mac is used to force DMS MAC address for WLAN.
1104  	 * Thus assert on failure to get MAC from DMS even after retries
1105  	 */
1106  	if (plat_priv->use_nv_mac) {
1107  		/* Check if Daemon says platform support DMS MAC provisioning */
1108  		cfg = cnss_plat_ipc_qmi_daemon_config();
1109  		if (cfg) {
1110  			if (!cfg->dms_mac_addr_supported) {
1111  				cnss_pr_err("DMS MAC address not supported\n");
1112  				CNSS_ASSERT(0);
1113  				return -EINVAL;
1114  			}
1115  		}
1116  		for (i = 0; i < CNSS_DMS_QMI_CONNECTION_WAIT_RETRY; i++) {
1117  			if (plat_priv->dms.mac_valid)
1118  				break;
1119  
1120  			ret = cnss_qmi_get_dms_mac(plat_priv);
1121  			if (ret == 0)
1122  				break;
1123  			msleep(CNSS_DMS_QMI_CONNECTION_WAIT_MS);
1124  		}
1125  		if (!plat_priv->dms.mac_valid) {
1126  			cnss_pr_err("Unable to get MAC from DMS after retries\n");
1127  			CNSS_ASSERT(0);
1128  			return -EINVAL;
1129  		}
1130  	}
1131  qmi_send:
1132  	if (plat_priv->dms.mac_valid)
1133  		ret =
1134  		cnss_wlfw_wlan_mac_req_send_sync(plat_priv, plat_priv->dms.mac,
1135  						 ARRAY_SIZE(plat_priv->dms.mac));
1136  
1137  	return ret;
1138  }
1139  
cnss_cal_db_mem_update(struct cnss_plat_data * plat_priv,enum cnss_cal_db_op op,u32 * size)1140  static int cnss_cal_db_mem_update(struct cnss_plat_data *plat_priv,
1141  				  enum cnss_cal_db_op op, u32 *size)
1142  {
1143  	int ret = 0;
1144  	u32 timeout = cnss_get_timeout(plat_priv,
1145  				       CNSS_TIMEOUT_DAEMON_CONNECTION);
1146  	enum cnss_plat_ipc_qmi_client_id_v01 client_id =
1147  					CNSS_PLAT_IPC_DAEMON_QMI_CLIENT_V01;
1148  
1149  	if (op >= CNSS_CAL_DB_INVALID_OP)
1150  		return -EINVAL;
1151  
1152  	if (!plat_priv->cbc_file_download) {
1153  		cnss_pr_info("CAL DB file not required as per BDF\n");
1154  		return 0;
1155  	}
1156  	if (*size == 0) {
1157  		cnss_pr_err("Invalid cal file size\n");
1158  		return -EINVAL;
1159  	}
1160  	if (!test_bit(CNSS_DAEMON_CONNECTED, &plat_priv->driver_state)) {
1161  		cnss_pr_info("Waiting for CNSS Daemon connection\n");
1162  		ret = wait_for_completion_timeout(&plat_priv->daemon_connected,
1163  						  msecs_to_jiffies(timeout));
1164  		if (!ret) {
1165  			cnss_pr_err("Daemon not yet connected\n");
1166  			CNSS_ASSERT(0);
1167  			return ret;
1168  		}
1169  	}
1170  	if (!plat_priv->cal_mem->va) {
1171  		cnss_pr_err("CAL DB Memory not setup for FW\n");
1172  		return -EINVAL;
1173  	}
1174  
1175  	/* Copy CAL DB file contents to/from CAL_TYPE_DDR mem allocated to FW */
1176  	if (op == CNSS_CAL_DB_DOWNLOAD) {
1177  		cnss_pr_dbg("Initiating Calibration file download to mem\n");
1178  		ret = cnss_plat_ipc_qmi_file_download(client_id,
1179  						      CNSS_CAL_DB_FILE_NAME,
1180  						      plat_priv->cal_mem->va,
1181  						      size);
1182  	} else {
1183  		cnss_pr_dbg("Initiating Calibration mem upload to file\n");
1184  		ret = cnss_plat_ipc_qmi_file_upload(client_id,
1185  						    CNSS_CAL_DB_FILE_NAME,
1186  						    plat_priv->cal_mem->va,
1187  						    *size);
1188  	}
1189  
1190  	if (ret)
1191  		cnss_pr_err("Cal DB file %s %s failure\n",
1192  			    CNSS_CAL_DB_FILE_NAME,
1193  			    op == CNSS_CAL_DB_DOWNLOAD ? "download" : "upload");
1194  	else
1195  		cnss_pr_dbg("Cal DB file %s %s size %d done\n",
1196  			    CNSS_CAL_DB_FILE_NAME,
1197  			    op == CNSS_CAL_DB_DOWNLOAD ? "download" : "upload",
1198  			    *size);
1199  
1200  	return ret;
1201  }
1202  
cnss_cal_mem_upload_to_file(struct cnss_plat_data * plat_priv)1203  static int cnss_cal_mem_upload_to_file(struct cnss_plat_data *plat_priv)
1204  {
1205  	if (plat_priv->cal_file_size > plat_priv->cal_mem->size) {
1206  		cnss_pr_err("Cal file size is larger than Cal DB Mem size\n");
1207  		return -EINVAL;
1208  	}
1209  	return cnss_cal_db_mem_update(plat_priv, CNSS_CAL_DB_UPLOAD,
1210  				      &plat_priv->cal_file_size);
1211  }
1212  
cnss_cal_file_download_to_mem(struct cnss_plat_data * plat_priv,u32 * cal_file_size)1213  static int cnss_cal_file_download_to_mem(struct cnss_plat_data *plat_priv,
1214  					 u32 *cal_file_size)
1215  {
1216  	/* To download pass the total size of cal DB mem allocated.
1217  	 * After cal file is download to mem, its size is updated in
1218  	 * return pointer
1219  	 */
1220  	*cal_file_size = plat_priv->cal_mem->size;
1221  	return cnss_cal_db_mem_update(plat_priv, CNSS_CAL_DB_DOWNLOAD,
1222  				      cal_file_size);
1223  }
1224  
cnss_fw_ready_hdlr(struct cnss_plat_data * plat_priv)1225  static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
1226  {
1227  	int ret = 0;
1228  	u32 cal_file_size = 0;
1229  
1230  	if (!plat_priv)
1231  		return -ENODEV;
1232  
1233  	if (test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state)) {
1234  		cnss_pr_err("Reboot is in progress, ignore FW ready\n");
1235  		return -EINVAL;
1236  	}
1237  
1238  	cnss_pr_dbg("Processing FW Init Done..\n");
1239  	del_timer(&plat_priv->fw_boot_timer);
1240  	set_bit(CNSS_FW_READY, &plat_priv->driver_state);
1241  	clear_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
1242  
1243  	cnss_wlfw_send_pcie_gen_speed_sync(plat_priv);
1244  	cnss_send_subsys_restart_level_msg(plat_priv);
1245  
1246  	if (test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state)) {
1247  		clear_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state);
1248  		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
1249  	}
1250  
1251  	if (test_bit(ENABLE_WALTEST, &plat_priv->ctrl_params.quirks)) {
1252  		ret = cnss_wlfw_wlan_mode_send_sync(plat_priv,
1253  						    CNSS_WALTEST);
1254  	} else if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state)) {
1255  		cnss_request_antenna_sharing(plat_priv);
1256  		cnss_cal_file_download_to_mem(plat_priv, &cal_file_size);
1257  		cnss_wlfw_cal_report_req_send_sync(plat_priv, cal_file_size);
1258  		plat_priv->cal_time = jiffies;
1259  		ret = cnss_wlfw_wlan_mode_send_sync(plat_priv,
1260  						    CNSS_CALIBRATION);
1261  	} else {
1262  		ret = cnss_setup_dms_mac(plat_priv);
1263  		ret = cnss_bus_call_driver_probe(plat_priv);
1264  	}
1265  
1266  	if (ret && test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state))
1267  		goto out;
1268  	else if (ret)
1269  		goto shutdown;
1270  
1271  	cnss_vreg_unvote_type(plat_priv, CNSS_VREG_PRIM);
1272  
1273  	return 0;
1274  
1275  shutdown:
1276  	cnss_bus_dev_shutdown(plat_priv);
1277  
1278  	clear_bit(CNSS_FW_READY, &plat_priv->driver_state);
1279  	clear_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
1280  
1281  out:
1282  	return ret;
1283  }
1284  
cnss_driver_event_to_str(enum cnss_driver_event_type type)1285  static char *cnss_driver_event_to_str(enum cnss_driver_event_type type)
1286  {
1287  	switch (type) {
1288  	case CNSS_DRIVER_EVENT_SERVER_ARRIVE:
1289  		return "SERVER_ARRIVE";
1290  	case CNSS_DRIVER_EVENT_SERVER_EXIT:
1291  		return "SERVER_EXIT";
1292  	case CNSS_DRIVER_EVENT_REQUEST_MEM:
1293  		return "REQUEST_MEM";
1294  	case CNSS_DRIVER_EVENT_FW_MEM_READY:
1295  		return "FW_MEM_READY";
1296  	case CNSS_DRIVER_EVENT_FW_READY:
1297  		return "FW_READY";
1298  	case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START:
1299  		return "COLD_BOOT_CAL_START";
1300  	case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE:
1301  		return "COLD_BOOT_CAL_DONE";
1302  	case CNSS_DRIVER_EVENT_REGISTER_DRIVER:
1303  		return "REGISTER_DRIVER";
1304  	case CNSS_DRIVER_EVENT_UNREGISTER_DRIVER:
1305  		return "UNREGISTER_DRIVER";
1306  	case CNSS_DRIVER_EVENT_RECOVERY:
1307  		return "RECOVERY";
1308  	case CNSS_DRIVER_EVENT_FORCE_FW_ASSERT:
1309  		return "FORCE_FW_ASSERT";
1310  	case CNSS_DRIVER_EVENT_POWER_UP:
1311  		return "POWER_UP";
1312  	case CNSS_DRIVER_EVENT_POWER_DOWN:
1313  		return "POWER_DOWN";
1314  	case CNSS_DRIVER_EVENT_IDLE_RESTART:
1315  		return "IDLE_RESTART";
1316  	case CNSS_DRIVER_EVENT_IDLE_SHUTDOWN:
1317  		return "IDLE_SHUTDOWN";
1318  	case CNSS_DRIVER_EVENT_IMS_WFC_CALL_IND:
1319  		return "IMS_WFC_CALL_IND";
1320  	case CNSS_DRIVER_EVENT_WLFW_TWT_CFG_IND:
1321  		return "WLFW_TWC_CFG_IND";
1322  	case CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM:
1323  		return "QDSS_TRACE_REQ_MEM";
1324  	case CNSS_DRIVER_EVENT_FW_MEM_FILE_SAVE:
1325  		return "FW_MEM_FILE_SAVE";
1326  	case CNSS_DRIVER_EVENT_QDSS_TRACE_FREE:
1327  		return "QDSS_TRACE_FREE";
1328  	case CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_DATA:
1329  		return "QDSS_TRACE_REQ_DATA";
1330  	case CNSS_DRIVER_EVENT_MAX:
1331  		return "EVENT_MAX";
1332  	}
1333  
1334  	return "UNKNOWN";
1335  };
1336  
cnss_driver_event_post(struct cnss_plat_data * plat_priv,enum cnss_driver_event_type type,u32 flags,void * data)1337  int cnss_driver_event_post(struct cnss_plat_data *plat_priv,
1338  			   enum cnss_driver_event_type type,
1339  			   u32 flags, void *data)
1340  {
1341  	struct cnss_driver_event *event;
1342  	unsigned long irq_flags;
1343  	int gfp = GFP_KERNEL;
1344  	int ret = 0;
1345  
1346  	if (!plat_priv)
1347  		return -ENODEV;
1348  
1349  	cnss_pr_dbg("Posting event: %s(%d)%s, state: 0x%lx flags: 0x%0x\n",
1350  		    cnss_driver_event_to_str(type), type,
1351  		    flags ? "-sync" : "", plat_priv->driver_state, flags);
1352  
1353  	if (type >= CNSS_DRIVER_EVENT_MAX) {
1354  		cnss_pr_err("Invalid Event type: %d, can't post", type);
1355  		return -EINVAL;
1356  	}
1357  
1358  	if (in_interrupt() || irqs_disabled())
1359  		gfp = GFP_ATOMIC;
1360  
1361  	event = kzalloc(sizeof(*event), gfp);
1362  	if (!event)
1363  		return -ENOMEM;
1364  
1365  	cnss_pm_stay_awake(plat_priv);
1366  
1367  	event->type = type;
1368  	event->data = data;
1369  	init_completion(&event->complete);
1370  	event->ret = CNSS_EVENT_PENDING;
1371  	event->sync = !!(flags & CNSS_EVENT_SYNC);
1372  
1373  	spin_lock_irqsave(&plat_priv->event_lock, irq_flags);
1374  	list_add_tail(&event->list, &plat_priv->event_list);
1375  	spin_unlock_irqrestore(&plat_priv->event_lock, irq_flags);
1376  
1377  	queue_work(plat_priv->event_wq, &plat_priv->event_work);
1378  
1379  	if (!(flags & CNSS_EVENT_SYNC))
1380  		goto out;
1381  
1382  	if (flags & CNSS_EVENT_UNKILLABLE)
1383  		wait_for_completion(&event->complete);
1384  	else if (flags & CNSS_EVENT_UNINTERRUPTIBLE)
1385  		ret = wait_for_completion_killable(&event->complete);
1386  	else
1387  		ret = wait_for_completion_interruptible(&event->complete);
1388  
1389  	cnss_pr_dbg("Completed event: %s(%d), state: 0x%lx, ret: %d/%d\n",
1390  		    cnss_driver_event_to_str(type), type,
1391  		    plat_priv->driver_state, ret, event->ret);
1392  	spin_lock_irqsave(&plat_priv->event_lock, irq_flags);
1393  	if (ret == -ERESTARTSYS && event->ret == CNSS_EVENT_PENDING) {
1394  		event->sync = false;
1395  		spin_unlock_irqrestore(&plat_priv->event_lock, irq_flags);
1396  		ret = -EINTR;
1397  		goto out;
1398  	}
1399  	spin_unlock_irqrestore(&plat_priv->event_lock, irq_flags);
1400  
1401  	ret = event->ret;
1402  	kfree(event);
1403  
1404  out:
1405  	cnss_pm_relax(plat_priv);
1406  	return ret;
1407  }
1408  
1409  /**
1410   * cnss_get_timeout - Get timeout for corresponding type.
1411   * @plat_priv: Pointer to platform driver context.
1412   * @cnss_timeout_type: Timeout type.
1413   *
1414   * Return: Timeout in milliseconds.
1415   */
cnss_get_timeout(struct cnss_plat_data * plat_priv,enum cnss_timeout_type timeout_type)1416  unsigned int cnss_get_timeout(struct cnss_plat_data *plat_priv,
1417  			      enum cnss_timeout_type timeout_type)
1418  {
1419  	unsigned int qmi_timeout = cnss_get_qmi_timeout(plat_priv);
1420  
1421  	switch (timeout_type) {
1422  	case CNSS_TIMEOUT_QMI:
1423  		return qmi_timeout;
1424  	case CNSS_TIMEOUT_POWER_UP:
1425  		return (qmi_timeout << 2);
1426  	case CNSS_TIMEOUT_IDLE_RESTART:
1427  		/* In idle restart power up sequence, we have fw_boot_timer to
1428  		 * handle FW initialization failure.
1429  		 * It uses WLAN_MISSION_MODE_TIMEOUT, so setup 3x that time to
1430  		 * account for FW dump collection and FW re-initialization on
1431  		 * retry.
1432  		 */
1433  		return (qmi_timeout + WLAN_MISSION_MODE_TIMEOUT * 3);
1434  	case CNSS_TIMEOUT_CALIBRATION:
1435  		/* Similar to mission mode, in CBC if FW init fails
1436  		 * fw recovery is tried. Thus return 2x the CBC timeout.
1437  		 */
1438  		return (qmi_timeout + WLAN_COLD_BOOT_CAL_TIMEOUT * 2);
1439  	case CNSS_TIMEOUT_WLAN_WATCHDOG:
1440  		return ((qmi_timeout << 1) + WLAN_WD_TIMEOUT_MS);
1441  	case CNSS_TIMEOUT_RDDM:
1442  		return CNSS_RDDM_TIMEOUT_MS;
1443  	case CNSS_TIMEOUT_RECOVERY:
1444  		return RECOVERY_TIMEOUT;
1445  	case CNSS_TIMEOUT_DAEMON_CONNECTION:
1446  		return qmi_timeout + CNSS_DAEMON_CONNECT_TIMEOUT_MS;
1447  	default:
1448  		return qmi_timeout;
1449  	}
1450  }
1451  
cnss_get_boot_timeout(struct device * dev)1452  unsigned int cnss_get_boot_timeout(struct device *dev)
1453  {
1454  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
1455  
1456  	if (!plat_priv) {
1457  		cnss_pr_err("plat_priv is NULL\n");
1458  		return 0;
1459  	}
1460  
1461  	return cnss_get_timeout(plat_priv, CNSS_TIMEOUT_QMI);
1462  }
1463  EXPORT_SYMBOL(cnss_get_boot_timeout);
1464  
cnss_power_up(struct device * dev)1465  int cnss_power_up(struct device *dev)
1466  {
1467  	int ret = 0;
1468  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
1469  	unsigned int timeout;
1470  
1471  	if (!plat_priv) {
1472  		cnss_pr_err("plat_priv is NULL\n");
1473  		return -ENODEV;
1474  	}
1475  
1476  	cnss_pr_dbg("Powering up device\n");
1477  
1478  	ret = cnss_driver_event_post(plat_priv,
1479  				     CNSS_DRIVER_EVENT_POWER_UP,
1480  				     CNSS_EVENT_SYNC, NULL);
1481  	if (ret)
1482  		goto out;
1483  
1484  	if (plat_priv->device_id == QCA6174_DEVICE_ID)
1485  		goto out;
1486  
1487  	timeout = cnss_get_timeout(plat_priv, CNSS_TIMEOUT_POWER_UP);
1488  
1489  	reinit_completion(&plat_priv->power_up_complete);
1490  	ret = wait_for_completion_timeout(&plat_priv->power_up_complete,
1491  					  msecs_to_jiffies(timeout));
1492  	if (!ret) {
1493  		cnss_pr_err("Timeout (%ums) waiting for power up to complete\n",
1494  			    timeout);
1495  		ret = -EAGAIN;
1496  		goto out;
1497  	}
1498  
1499  	return 0;
1500  
1501  out:
1502  	return ret;
1503  }
1504  EXPORT_SYMBOL(cnss_power_up);
1505  
cnss_power_down(struct device * dev)1506  int cnss_power_down(struct device *dev)
1507  {
1508  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
1509  
1510  	if (!plat_priv) {
1511  		cnss_pr_err("plat_priv is NULL\n");
1512  		return -ENODEV;
1513  	}
1514  
1515  	cnss_pr_dbg("Powering down device\n");
1516  
1517  	return cnss_driver_event_post(plat_priv,
1518  				      CNSS_DRIVER_EVENT_POWER_DOWN,
1519  				      CNSS_EVENT_SYNC, NULL);
1520  }
1521  EXPORT_SYMBOL(cnss_power_down);
1522  
cnss_idle_restart(struct device * dev)1523  int cnss_idle_restart(struct device *dev)
1524  {
1525  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
1526  	unsigned int timeout;
1527  	int ret = 0;
1528  
1529  	if (!plat_priv) {
1530  		cnss_pr_err("plat_priv is NULL\n");
1531  		return -ENODEV;
1532  	}
1533  
1534  	if (!mutex_trylock(&plat_priv->driver_ops_lock)) {
1535  		cnss_pr_dbg("Another driver operation is in progress, ignore idle restart\n");
1536  		return -EBUSY;
1537  	}
1538  
1539  	cnss_pr_dbg("Doing idle restart\n");
1540  
1541  	reinit_completion(&plat_priv->power_up_complete);
1542  
1543  	if (test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state)) {
1544  		cnss_pr_dbg("Reboot or shutdown is in progress, ignore idle restart\n");
1545  		ret = -EINVAL;
1546  		goto out;
1547  	}
1548  
1549  	ret = cnss_driver_event_post(plat_priv,
1550  				     CNSS_DRIVER_EVENT_IDLE_RESTART,
1551  				     CNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL);
1552  	if (ret == -EINTR && plat_priv->device_id != QCA6174_DEVICE_ID)
1553  		cnss_pr_err("Idle restart has been interrupted but device power up is still in progress");
1554  	else if (ret)
1555  		goto out;
1556  
1557  	if (plat_priv->device_id == QCA6174_DEVICE_ID) {
1558  		ret = cnss_bus_call_driver_probe(plat_priv);
1559  		goto out;
1560  	}
1561  
1562  	timeout = cnss_get_timeout(plat_priv, CNSS_TIMEOUT_IDLE_RESTART);
1563  	ret = wait_for_completion_timeout(&plat_priv->power_up_complete,
1564  					  msecs_to_jiffies(timeout));
1565  	if (plat_priv->power_up_error) {
1566  		ret = plat_priv->power_up_error;
1567  		clear_bit(CNSS_DRIVER_IDLE_RESTART, &plat_priv->driver_state);
1568  		cnss_pr_dbg("Power up error:%d, exiting\n",
1569  			    plat_priv->power_up_error);
1570  		goto out;
1571  	}
1572  
1573  	if (!ret) {
1574  		/* This exception occurs after attempting retry of FW recovery.
1575  		 * Thus we can safely power off the device.
1576  		 */
1577  		cnss_fatal_err("Timeout (%ums) waiting for idle restart to complete\n",
1578  			       timeout);
1579  		ret = -ETIMEDOUT;
1580  		cnss_power_down(dev);
1581  		CNSS_ASSERT(0);
1582  		goto out;
1583  	}
1584  
1585  	if (test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state)) {
1586  		cnss_pr_dbg("Reboot or shutdown is in progress, ignore idle restart\n");
1587  		del_timer(&plat_priv->fw_boot_timer);
1588  		ret = -EINVAL;
1589  		goto out;
1590  	}
1591  
1592  	/* In non-DRV mode, remove MHI satellite configuration. Switching to
1593  	 * non-DRV is supported only once after device reboots and before wifi
1594  	 * is turned on. We do not allow switching back to DRV.
1595  	 * To bring device back into DRV, user needs to reboot device.
1596  	 */
1597  	if (test_bit(DISABLE_DRV, &plat_priv->ctrl_params.quirks)) {
1598  		cnss_pr_dbg("DRV is disabled\n");
1599  		cnss_bus_disable_mhi_satellite_cfg(plat_priv);
1600  	}
1601  
1602  	mutex_unlock(&plat_priv->driver_ops_lock);
1603  	return 0;
1604  
1605  out:
1606  	mutex_unlock(&plat_priv->driver_ops_lock);
1607  	return ret;
1608  }
1609  EXPORT_SYMBOL(cnss_idle_restart);
1610  
cnss_idle_shutdown(struct device * dev)1611  int cnss_idle_shutdown(struct device *dev)
1612  {
1613  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
1614  
1615  	if (!plat_priv) {
1616  		cnss_pr_err("plat_priv is NULL\n");
1617  		return -ENODEV;
1618  	}
1619  
1620  	if (test_bit(CNSS_IN_SUSPEND_RESUME, &plat_priv->driver_state)) {
1621  		cnss_pr_dbg("System suspend or resume in progress, ignore idle shutdown\n");
1622  		return -EAGAIN;
1623  	}
1624  
1625  	cnss_pr_dbg("Doing idle shutdown\n");
1626  
1627  	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) ||
1628  	    test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state)) {
1629  		cnss_pr_dbg("Recovery in progress. Ignore IDLE Shutdown\n");
1630  		return -EBUSY;
1631  	}
1632  
1633  	return cnss_driver_event_post(plat_priv,
1634  				      CNSS_DRIVER_EVENT_IDLE_SHUTDOWN,
1635  				      CNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL);
1636  }
1637  EXPORT_SYMBOL(cnss_idle_shutdown);
1638  
cnss_get_resources(struct cnss_plat_data * plat_priv)1639  static int cnss_get_resources(struct cnss_plat_data *plat_priv)
1640  {
1641  	int ret = 0;
1642  
1643  	ret = cnss_get_vreg_type(plat_priv, CNSS_VREG_PRIM);
1644  	if (ret < 0) {
1645  		cnss_pr_err("Failed to get vreg, err = %d\n", ret);
1646  		goto out;
1647  	}
1648  
1649  	ret = cnss_get_clk(plat_priv);
1650  	if (ret) {
1651  		cnss_pr_err("Failed to get clocks, err = %d\n", ret);
1652  		goto put_vreg;
1653  	}
1654  
1655  	ret = cnss_get_pinctrl(plat_priv);
1656  	if (ret) {
1657  		cnss_pr_err("Failed to get pinctrl, err = %d\n", ret);
1658  		goto put_clk;
1659  	}
1660  
1661  	return 0;
1662  
1663  put_clk:
1664  	cnss_put_clk(plat_priv);
1665  put_vreg:
1666  	cnss_put_vreg_type(plat_priv, CNSS_VREG_PRIM);
1667  out:
1668  	return ret;
1669  }
1670  
cnss_put_resources(struct cnss_plat_data * plat_priv)1671  static void cnss_put_resources(struct cnss_plat_data *plat_priv)
1672  {
1673  	cnss_put_clk(plat_priv);
1674  	cnss_put_vreg_type(plat_priv, CNSS_VREG_PRIM);
1675  }
1676  
1677  #if IS_ENABLED(CONFIG_ESOC) && IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
cnss_modem_notifier_nb(struct notifier_block * nb,unsigned long code,void * ss_handle)1678  static int cnss_modem_notifier_nb(struct notifier_block *nb,
1679  				  unsigned long code,
1680  				  void *ss_handle)
1681  {
1682  	struct cnss_plat_data *plat_priv =
1683  		container_of(nb, struct cnss_plat_data, modem_nb);
1684  	struct cnss_esoc_info *esoc_info;
1685  
1686  	cnss_pr_dbg("Modem notifier: event %lu\n", code);
1687  
1688  	if (!plat_priv)
1689  		return NOTIFY_DONE;
1690  
1691  	esoc_info = &plat_priv->esoc_info;
1692  
1693  	if (code == SUBSYS_AFTER_POWERUP)
1694  		esoc_info->modem_current_status = 1;
1695  	else if (code == SUBSYS_BEFORE_SHUTDOWN)
1696  		esoc_info->modem_current_status = 0;
1697  	else
1698  		return NOTIFY_DONE;
1699  
1700  	if (!cnss_bus_call_driver_modem_status(plat_priv,
1701  					       esoc_info->modem_current_status))
1702  		return NOTIFY_DONE;
1703  
1704  	return NOTIFY_OK;
1705  }
1706  
cnss_register_esoc(struct cnss_plat_data * plat_priv)1707  static int cnss_register_esoc(struct cnss_plat_data *plat_priv)
1708  {
1709  	int ret = 0;
1710  	struct device *dev;
1711  	struct cnss_esoc_info *esoc_info;
1712  	struct esoc_desc *esoc_desc;
1713  	const char *client_desc;
1714  
1715  	dev = &plat_priv->plat_dev->dev;
1716  	esoc_info = &plat_priv->esoc_info;
1717  
1718  	esoc_info->notify_modem_status =
1719  		of_property_read_bool(dev->of_node,
1720  				      "qcom,notify-modem-status");
1721  
1722  	if (!esoc_info->notify_modem_status)
1723  		goto out;
1724  
1725  	ret = of_property_read_string_index(dev->of_node, "esoc-names", 0,
1726  					    &client_desc);
1727  	if (ret) {
1728  		cnss_pr_dbg("esoc-names is not defined in DT, skip!\n");
1729  	} else {
1730  		esoc_desc = devm_register_esoc_client(dev, client_desc);
1731  		if (IS_ERR_OR_NULL(esoc_desc)) {
1732  			ret = PTR_RET(esoc_desc);
1733  			cnss_pr_err("Failed to register esoc_desc, err = %d\n",
1734  				    ret);
1735  			goto out;
1736  		}
1737  		esoc_info->esoc_desc = esoc_desc;
1738  	}
1739  
1740  	plat_priv->modem_nb.notifier_call = cnss_modem_notifier_nb;
1741  	esoc_info->modem_current_status = 0;
1742  	esoc_info->modem_notify_handler =
1743  		subsys_notif_register_notifier(esoc_info->esoc_desc ?
1744  					       esoc_info->esoc_desc->name :
1745  					       "modem", &plat_priv->modem_nb);
1746  	if (IS_ERR(esoc_info->modem_notify_handler)) {
1747  		ret = PTR_ERR(esoc_info->modem_notify_handler);
1748  		cnss_pr_err("Failed to register esoc notifier, err = %d\n",
1749  			    ret);
1750  		goto unreg_esoc;
1751  	}
1752  
1753  	return 0;
1754  unreg_esoc:
1755  	if (esoc_info->esoc_desc)
1756  		devm_unregister_esoc_client(dev, esoc_info->esoc_desc);
1757  out:
1758  	return ret;
1759  }
1760  
cnss_unregister_esoc(struct cnss_plat_data * plat_priv)1761  static void cnss_unregister_esoc(struct cnss_plat_data *plat_priv)
1762  {
1763  	struct device *dev;
1764  	struct cnss_esoc_info *esoc_info;
1765  
1766  	dev = &plat_priv->plat_dev->dev;
1767  	esoc_info = &plat_priv->esoc_info;
1768  
1769  	if (esoc_info->notify_modem_status)
1770  		subsys_notif_unregister_notifier
1771  		(esoc_info->modem_notify_handler,
1772  		 &plat_priv->modem_nb);
1773  	if (esoc_info->esoc_desc)
1774  		devm_unregister_esoc_client(dev, esoc_info->esoc_desc);
1775  }
1776  #else
cnss_register_esoc(struct cnss_plat_data * plat_priv)1777  static inline int cnss_register_esoc(struct cnss_plat_data *plat_priv)
1778  {
1779  	return 0;
1780  }
1781  
cnss_unregister_esoc(struct cnss_plat_data * plat_priv)1782  static inline void cnss_unregister_esoc(struct cnss_plat_data *plat_priv) {}
1783  #endif
1784  
cnss_enable_dev_sol_irq(struct cnss_plat_data * plat_priv)1785  int cnss_enable_dev_sol_irq(struct cnss_plat_data *plat_priv)
1786  {
1787  	struct cnss_sol_gpio *sol_gpio = &plat_priv->sol_gpio;
1788  	int ret = 0;
1789  
1790  	if (sol_gpio->dev_sol_gpio < 0 || sol_gpio->dev_sol_irq <= 0)
1791  		return 0;
1792  
1793  	ret = enable_irq_wake(sol_gpio->dev_sol_irq);
1794  	if (ret)
1795  		cnss_pr_err("Failed to enable device SOL as wake IRQ, err = %d\n",
1796  			    ret);
1797  
1798  	return ret;
1799  }
1800  
cnss_disable_dev_sol_irq(struct cnss_plat_data * plat_priv)1801  int cnss_disable_dev_sol_irq(struct cnss_plat_data *plat_priv)
1802  {
1803  	struct cnss_sol_gpio *sol_gpio = &plat_priv->sol_gpio;
1804  	int ret = 0;
1805  
1806  	if (sol_gpio->dev_sol_gpio < 0 || sol_gpio->dev_sol_irq <= 0)
1807  		return 0;
1808  
1809  	ret = disable_irq_wake(sol_gpio->dev_sol_irq);
1810  	if (ret)
1811  		cnss_pr_err("Failed to disable device SOL as wake IRQ, err = %d\n",
1812  			    ret);
1813  
1814  	return ret;
1815  }
1816  
cnss_get_dev_sol_value(struct cnss_plat_data * plat_priv)1817  int cnss_get_dev_sol_value(struct cnss_plat_data *plat_priv)
1818  {
1819  	struct cnss_sol_gpio *sol_gpio = &plat_priv->sol_gpio;
1820  
1821  	if (sol_gpio->dev_sol_gpio < 0)
1822  		return -EINVAL;
1823  
1824  	return gpio_get_value(sol_gpio->dev_sol_gpio);
1825  }
1826  
cnss_dev_sol_handler(int irq,void * data)1827  static irqreturn_t cnss_dev_sol_handler(int irq, void *data)
1828  {
1829  	struct cnss_plat_data *plat_priv = data;
1830  	struct cnss_sol_gpio *sol_gpio = &plat_priv->sol_gpio;
1831  
1832  	if (test_bit(CNSS_POWER_OFF, &plat_priv->driver_state)) {
1833  		cnss_pr_dbg("Ignore Dev SOL during device power off");
1834  		return IRQ_HANDLED;
1835  	}
1836  
1837  	sol_gpio->dev_sol_counter++;
1838  	cnss_pr_dbg("WLAN device SOL IRQ (%u) is asserted #%u, dev_sol_val: %d\n",
1839  		    irq, sol_gpio->dev_sol_counter,
1840  		    cnss_get_dev_sol_value(plat_priv));
1841  
1842  	/* Make sure abort current suspend */
1843  	cnss_pm_stay_awake(plat_priv);
1844  	cnss_pm_relax(plat_priv);
1845  	pm_system_wakeup();
1846  
1847  	cnss_bus_handle_dev_sol_irq(plat_priv);
1848  
1849  	return IRQ_HANDLED;
1850  }
1851  
cnss_init_dev_sol_gpio(struct cnss_plat_data * plat_priv)1852  static int cnss_init_dev_sol_gpio(struct cnss_plat_data *plat_priv)
1853  {
1854  	struct device *dev = &plat_priv->plat_dev->dev;
1855  	struct cnss_sol_gpio *sol_gpio = &plat_priv->sol_gpio;
1856  	int ret = 0;
1857  
1858  	sol_gpio->dev_sol_gpio = of_get_named_gpio(dev->of_node,
1859  						   "wlan-dev-sol-gpio", 0);
1860  	if (sol_gpio->dev_sol_gpio < 0)
1861  		goto out;
1862  
1863  	cnss_pr_dbg("Get device SOL GPIO (%d) from device node\n",
1864  		    sol_gpio->dev_sol_gpio);
1865  
1866  	ret = gpio_request(sol_gpio->dev_sol_gpio, "wlan_dev_sol_gpio");
1867  	if (ret) {
1868  		cnss_pr_err("Failed to request device SOL GPIO, err = %d\n",
1869  			    ret);
1870  		goto out;
1871  	}
1872  
1873  	gpio_direction_input(sol_gpio->dev_sol_gpio);
1874  	sol_gpio->dev_sol_irq = gpio_to_irq(sol_gpio->dev_sol_gpio);
1875  
1876  	ret = request_irq(sol_gpio->dev_sol_irq, cnss_dev_sol_handler,
1877  			  IRQF_TRIGGER_FALLING, "wlan_dev_sol_irq", plat_priv);
1878  	if (ret) {
1879  		cnss_pr_err("Failed to request device SOL IRQ, err = %d\n", ret);
1880  		goto free_gpio;
1881  	}
1882  
1883  	return 0;
1884  
1885  free_gpio:
1886  	gpio_free(sol_gpio->dev_sol_gpio);
1887  out:
1888  	return ret;
1889  }
1890  
cnss_deinit_dev_sol_gpio(struct cnss_plat_data * plat_priv)1891  static void cnss_deinit_dev_sol_gpio(struct cnss_plat_data *plat_priv)
1892  {
1893  	struct cnss_sol_gpio *sol_gpio = &plat_priv->sol_gpio;
1894  
1895  	if (sol_gpio->dev_sol_gpio < 0)
1896  		return;
1897  
1898  	free_irq(sol_gpio->dev_sol_irq, plat_priv);
1899  	gpio_free(sol_gpio->dev_sol_gpio);
1900  }
1901  
cnss_set_host_sol_value(struct cnss_plat_data * plat_priv,int value)1902  int cnss_set_host_sol_value(struct cnss_plat_data *plat_priv, int value)
1903  {
1904  	struct cnss_sol_gpio *sol_gpio = &plat_priv->sol_gpio;
1905  
1906  	if (sol_gpio->host_sol_gpio < 0)
1907  		return -EINVAL;
1908  
1909  	if (value)
1910  		cnss_pr_dbg("Assert host SOL GPIO\n");
1911  	gpio_set_value(sol_gpio->host_sol_gpio, value);
1912  
1913  	return 0;
1914  }
1915  
cnss_get_host_sol_value(struct cnss_plat_data * plat_priv)1916  int cnss_get_host_sol_value(struct cnss_plat_data *plat_priv)
1917  {
1918  	struct cnss_sol_gpio *sol_gpio = &plat_priv->sol_gpio;
1919  
1920  	if (sol_gpio->host_sol_gpio < 0)
1921  		return -EINVAL;
1922  
1923  	return gpio_get_value(sol_gpio->host_sol_gpio);
1924  }
1925  
cnss_init_host_sol_gpio(struct cnss_plat_data * plat_priv)1926  static int cnss_init_host_sol_gpio(struct cnss_plat_data *plat_priv)
1927  {
1928  	struct device *dev = &plat_priv->plat_dev->dev;
1929  	struct cnss_sol_gpio *sol_gpio = &plat_priv->sol_gpio;
1930  	int ret = 0;
1931  
1932  	sol_gpio->host_sol_gpio = of_get_named_gpio(dev->of_node,
1933  						    "wlan-host-sol-gpio", 0);
1934  	if (sol_gpio->host_sol_gpio < 0)
1935  		goto out;
1936  
1937  	cnss_pr_dbg("Get host SOL GPIO (%d) from device node\n",
1938  		    sol_gpio->host_sol_gpio);
1939  
1940  	ret = gpio_request(sol_gpio->host_sol_gpio, "wlan_host_sol_gpio");
1941  	if (ret) {
1942  		cnss_pr_err("Failed to request host SOL GPIO, err = %d\n",
1943  			    ret);
1944  		goto out;
1945  	}
1946  
1947  	gpio_direction_output(sol_gpio->host_sol_gpio, 0);
1948  
1949  	return 0;
1950  
1951  out:
1952  	return ret;
1953  }
1954  
cnss_deinit_host_sol_gpio(struct cnss_plat_data * plat_priv)1955  static void cnss_deinit_host_sol_gpio(struct cnss_plat_data *plat_priv)
1956  {
1957  	struct cnss_sol_gpio *sol_gpio = &plat_priv->sol_gpio;
1958  
1959  	if (sol_gpio->host_sol_gpio < 0)
1960  		return;
1961  
1962  	gpio_free(sol_gpio->host_sol_gpio);
1963  }
1964  
cnss_init_sol_gpio(struct cnss_plat_data * plat_priv)1965  static int cnss_init_sol_gpio(struct cnss_plat_data *plat_priv)
1966  {
1967  	int ret;
1968  
1969  	ret = cnss_init_dev_sol_gpio(plat_priv);
1970  	if (ret)
1971  		goto out;
1972  
1973  	ret = cnss_init_host_sol_gpio(plat_priv);
1974  	if (ret)
1975  		goto deinit_dev_sol;
1976  
1977  	return 0;
1978  
1979  deinit_dev_sol:
1980  	cnss_deinit_dev_sol_gpio(plat_priv);
1981  out:
1982  	return ret;
1983  }
1984  
cnss_deinit_sol_gpio(struct cnss_plat_data * plat_priv)1985  static void cnss_deinit_sol_gpio(struct cnss_plat_data *plat_priv)
1986  {
1987  	cnss_deinit_host_sol_gpio(plat_priv);
1988  	cnss_deinit_dev_sol_gpio(plat_priv);
1989  }
1990  
1991  #if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
cnss_subsys_powerup(const struct subsys_desc * subsys_desc)1992  static int cnss_subsys_powerup(const struct subsys_desc *subsys_desc)
1993  {
1994  	struct cnss_plat_data *plat_priv;
1995  	int ret = 0;
1996  
1997  	if (!subsys_desc->dev) {
1998  		cnss_pr_err("dev from subsys_desc is NULL\n");
1999  		return -ENODEV;
2000  	}
2001  
2002  	plat_priv = dev_get_drvdata(subsys_desc->dev);
2003  	if (!plat_priv) {
2004  		cnss_pr_err("plat_priv is NULL\n");
2005  		return -ENODEV;
2006  	}
2007  
2008  	if (!plat_priv->driver_state) {
2009  		cnss_pr_dbg("subsys powerup is ignored\n");
2010  		return 0;
2011  	}
2012  
2013  	ret = cnss_bus_dev_powerup(plat_priv);
2014  	if (ret)
2015  		__pm_relax(plat_priv->recovery_ws);
2016  	return ret;
2017  }
2018  
cnss_subsys_shutdown(const struct subsys_desc * subsys_desc,bool force_stop)2019  static int cnss_subsys_shutdown(const struct subsys_desc *subsys_desc,
2020  				bool force_stop)
2021  {
2022  	struct cnss_plat_data *plat_priv;
2023  
2024  	if (!subsys_desc->dev) {
2025  		cnss_pr_err("dev from subsys_desc is NULL\n");
2026  		return -ENODEV;
2027  	}
2028  
2029  	plat_priv = dev_get_drvdata(subsys_desc->dev);
2030  	if (!plat_priv) {
2031  		cnss_pr_err("plat_priv is NULL\n");
2032  		return -ENODEV;
2033  	}
2034  
2035  	if (!plat_priv->driver_state) {
2036  		cnss_pr_dbg("subsys shutdown is ignored\n");
2037  		return 0;
2038  	}
2039  
2040  	return cnss_bus_dev_shutdown(plat_priv);
2041  }
2042  
cnss_device_crashed(struct device * dev)2043  void cnss_device_crashed(struct device *dev)
2044  {
2045  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
2046  	struct cnss_subsys_info *subsys_info;
2047  
2048  	if (!plat_priv)
2049  		return;
2050  
2051  	subsys_info = &plat_priv->subsys_info;
2052  	if (subsys_info->subsys_device) {
2053  		set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
2054  		subsys_set_crash_status(subsys_info->subsys_device, true);
2055  		subsystem_restart_dev(subsys_info->subsys_device);
2056  	}
2057  }
2058  EXPORT_SYMBOL(cnss_device_crashed);
2059  
cnss_subsys_crash_shutdown(const struct subsys_desc * subsys_desc)2060  static void cnss_subsys_crash_shutdown(const struct subsys_desc *subsys_desc)
2061  {
2062  	struct cnss_plat_data *plat_priv = dev_get_drvdata(subsys_desc->dev);
2063  
2064  	if (!plat_priv) {
2065  		cnss_pr_err("plat_priv is NULL\n");
2066  		return;
2067  	}
2068  
2069  	cnss_bus_dev_crash_shutdown(plat_priv);
2070  }
2071  
cnss_subsys_ramdump(int enable,const struct subsys_desc * subsys_desc)2072  static int cnss_subsys_ramdump(int enable,
2073  			       const struct subsys_desc *subsys_desc)
2074  {
2075  	struct cnss_plat_data *plat_priv = dev_get_drvdata(subsys_desc->dev);
2076  
2077  	if (!plat_priv) {
2078  		cnss_pr_err("plat_priv is NULL\n");
2079  		return -ENODEV;
2080  	}
2081  
2082  	if (!enable)
2083  		return 0;
2084  
2085  	return cnss_bus_dev_ramdump(plat_priv);
2086  }
2087  
cnss_recovery_work_handler(struct work_struct * work)2088  static void cnss_recovery_work_handler(struct work_struct *work)
2089  {
2090  }
2091  #else
cnss_recovery_handler(struct cnss_plat_data * plat_priv)2092  void cnss_recovery_handler(struct cnss_plat_data *plat_priv)
2093  {
2094  	int ret;
2095  
2096  	set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
2097  
2098  	if (!plat_priv->recovery_enabled)
2099  		panic("subsys-restart: Resetting the SoC wlan crashed\n");
2100  
2101  	cnss_bus_dev_shutdown(plat_priv);
2102  	cnss_bus_dev_ramdump(plat_priv);
2103  
2104  	/* If recovery is triggered before Host driver registration,
2105  	 * avoid device power up because eventually device will be
2106  	 * power up as part of driver registration.
2107  	 */
2108  	if (!test_bit(CNSS_DRIVER_REGISTER, &plat_priv->driver_state) ||
2109  	    !test_bit(CNSS_DRIVER_REGISTERED, &plat_priv->driver_state)) {
2110  		cnss_pr_dbg("Host driver not registered yet, ignore Device Power Up, 0x%lx\n",
2111  			    plat_priv->driver_state);
2112  		return;
2113  	}
2114  
2115  	msleep(POWER_RESET_MIN_DELAY_MS);
2116  
2117  	ret = cnss_bus_dev_powerup(plat_priv);
2118  	if (ret) {
2119  		__pm_relax(plat_priv->recovery_ws);
2120  		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
2121  	}
2122  
2123  	return;
2124  }
2125  
cnss_recovery_work_handler(struct work_struct * work)2126  static void cnss_recovery_work_handler(struct work_struct *work)
2127  {
2128  	struct cnss_plat_data *plat_priv =
2129  		container_of(work, struct cnss_plat_data, recovery_work);
2130  
2131  	cnss_recovery_handler(plat_priv);
2132  }
2133  
cnss_device_crashed(struct device * dev)2134  void cnss_device_crashed(struct device *dev)
2135  {
2136  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
2137  
2138  	if (!plat_priv)
2139  		return;
2140  
2141  	set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
2142  	schedule_work(&plat_priv->recovery_work);
2143  }
2144  EXPORT_SYMBOL(cnss_device_crashed);
2145  #endif /* CONFIG_MSM_SUBSYSTEM_RESTART */
2146  
cnss_get_virt_ramdump_mem(struct device * dev,unsigned long * size)2147  void *cnss_get_virt_ramdump_mem(struct device *dev, unsigned long *size)
2148  {
2149  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
2150  	struct cnss_ramdump_info *ramdump_info;
2151  
2152  	if (!plat_priv)
2153  		return NULL;
2154  
2155  	ramdump_info = &plat_priv->ramdump_info;
2156  	*size = ramdump_info->ramdump_size;
2157  
2158  	return ramdump_info->ramdump_va;
2159  }
2160  EXPORT_SYMBOL(cnss_get_virt_ramdump_mem);
2161  
cnss_recovery_reason_to_str(enum cnss_recovery_reason reason)2162  static const char *cnss_recovery_reason_to_str(enum cnss_recovery_reason reason)
2163  {
2164  	switch (reason) {
2165  	case CNSS_REASON_DEFAULT:
2166  		return "DEFAULT";
2167  	case CNSS_REASON_LINK_DOWN:
2168  		return "LINK_DOWN";
2169  	case CNSS_REASON_RDDM:
2170  		return "RDDM";
2171  	case CNSS_REASON_TIMEOUT:
2172  		return "TIMEOUT";
2173  	}
2174  
2175  	return "UNKNOWN";
2176  };
2177  
cnss_do_recovery(struct cnss_plat_data * plat_priv,enum cnss_recovery_reason reason)2178  static int cnss_do_recovery(struct cnss_plat_data *plat_priv,
2179  			    enum cnss_recovery_reason reason)
2180  {
2181  	int ret;
2182  
2183  	plat_priv->recovery_count++;
2184  
2185  	if (plat_priv->device_id == QCA6174_DEVICE_ID)
2186  		goto self_recovery;
2187  
2188  	if (test_bit(SKIP_RECOVERY, &plat_priv->ctrl_params.quirks)) {
2189  		cnss_pr_dbg("Skip device recovery\n");
2190  		return 0;
2191  	}
2192  
2193  	/* FW recovery sequence has multiple steps and firmware load requires
2194  	 * linux PM in awake state. Thus hold the cnss wake source until
2195  	 * WLAN MISSION enabled. CNSS_TIMEOUT_RECOVERY option should cover all
2196  	 * time taken in this process.
2197  	 */
2198  	pm_wakeup_ws_event(plat_priv->recovery_ws,
2199  			   cnss_get_timeout(plat_priv, CNSS_TIMEOUT_RECOVERY),
2200  			   true);
2201  
2202  	switch (reason) {
2203  	case CNSS_REASON_LINK_DOWN:
2204  		if (!cnss_bus_check_link_status(plat_priv)) {
2205  			cnss_pr_dbg("Skip link down recovery as link is already up\n");
2206  			return 0;
2207  		}
2208  		if (test_bit(LINK_DOWN_SELF_RECOVERY,
2209  			     &plat_priv->ctrl_params.quirks))
2210  			goto self_recovery;
2211  		if (!cnss_bus_recover_link_down(plat_priv)) {
2212  			/* clear recovery bit here to avoid skipping
2213  			 * the recovery work for RDDM later
2214  			 */
2215  			clear_bit(CNSS_DRIVER_RECOVERY,
2216  				  &plat_priv->driver_state);
2217  			return 0;
2218  		}
2219  		break;
2220  	case CNSS_REASON_RDDM:
2221  		cnss_bus_collect_dump_info(plat_priv, false);
2222  		break;
2223  	case CNSS_REASON_DEFAULT:
2224  	case CNSS_REASON_TIMEOUT:
2225  		break;
2226  	default:
2227  		cnss_pr_err("Unsupported recovery reason: %s(%d)\n",
2228  			    cnss_recovery_reason_to_str(reason), reason);
2229  		break;
2230  	}
2231  	cnss_bus_device_crashed(plat_priv);
2232  
2233  	return 0;
2234  
2235  self_recovery:
2236  	cnss_pr_dbg("Going for self recovery\n");
2237  	cnss_bus_dev_shutdown(plat_priv);
2238  
2239  	if (test_bit(LINK_DOWN_SELF_RECOVERY, &plat_priv->ctrl_params.quirks))
2240  		clear_bit(LINK_DOWN_SELF_RECOVERY,
2241  			  &plat_priv->ctrl_params.quirks);
2242  
2243  	/* If link down self recovery is triggered before Host driver
2244  	 * registration, avoid device power up because eventually device
2245  	 * will be power up as part of driver registration.
2246  	 */
2247  
2248  	if (!test_bit(CNSS_DRIVER_REGISTER, &plat_priv->driver_state) ||
2249  	    !test_bit(CNSS_DRIVER_REGISTERED, &plat_priv->driver_state)) {
2250  		cnss_pr_dbg("Host driver not registered yet, ignore Device Power Up, 0x%lx\n",
2251  			    plat_priv->driver_state);
2252  		return 0;
2253  	}
2254  
2255  	ret = cnss_bus_dev_powerup(plat_priv);
2256  	if (ret)
2257  		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
2258  
2259  	return 0;
2260  }
2261  
cnss_driver_recovery_hdlr(struct cnss_plat_data * plat_priv,void * data)2262  static int cnss_driver_recovery_hdlr(struct cnss_plat_data *plat_priv,
2263  				     void *data)
2264  {
2265  	struct cnss_recovery_data *recovery_data = data;
2266  	int ret = 0;
2267  
2268  	cnss_pr_dbg("Driver recovery is triggered with reason: %s(%d)\n",
2269  		    cnss_recovery_reason_to_str(recovery_data->reason),
2270  		    recovery_data->reason);
2271  
2272  	if (!plat_priv->driver_state) {
2273  		cnss_pr_err("Improper driver state, ignore recovery\n");
2274  		ret = -EINVAL;
2275  		goto out;
2276  	}
2277  
2278  	if (test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state)) {
2279  		cnss_pr_err("Reboot is in progress, ignore recovery\n");
2280  		ret = -EINVAL;
2281  		goto out;
2282  	}
2283  
2284  	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
2285  		cnss_pr_err("Recovery is already in progress\n");
2286  		CNSS_ASSERT(0);
2287  		ret = -EINVAL;
2288  		goto out;
2289  	}
2290  
2291  	if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state) ||
2292  	    test_bit(CNSS_DRIVER_IDLE_SHUTDOWN, &plat_priv->driver_state)) {
2293  		cnss_pr_err("Driver unload or idle shutdown is in progress, ignore recovery\n");
2294  		ret = -EINVAL;
2295  		goto out;
2296  	}
2297  
2298  	switch (plat_priv->device_id) {
2299  	case QCA6174_DEVICE_ID:
2300  		if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
2301  		    test_bit(CNSS_DRIVER_IDLE_RESTART,
2302  			     &plat_priv->driver_state)) {
2303  			cnss_pr_err("Driver load or idle restart is in progress, ignore recovery\n");
2304  			ret = -EINVAL;
2305  			goto out;
2306  		}
2307  		break;
2308  	default:
2309  		if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
2310  			set_bit(CNSS_FW_BOOT_RECOVERY,
2311  				&plat_priv->driver_state);
2312  		}
2313  		break;
2314  	}
2315  
2316  	set_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
2317  	ret = cnss_do_recovery(plat_priv, recovery_data->reason);
2318  
2319  out:
2320  	kfree(data);
2321  	return ret;
2322  }
2323  
cnss_self_recovery(struct device * dev,enum cnss_recovery_reason reason)2324  int cnss_self_recovery(struct device *dev,
2325  		       enum cnss_recovery_reason reason)
2326  {
2327  	cnss_schedule_recovery(dev, reason);
2328  	return 0;
2329  }
2330  EXPORT_SYMBOL(cnss_self_recovery);
2331  
cnss_schedule_recovery(struct device * dev,enum cnss_recovery_reason reason)2332  void cnss_schedule_recovery(struct device *dev,
2333  			    enum cnss_recovery_reason reason)
2334  {
2335  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
2336  	struct cnss_recovery_data *data;
2337  	int gfp = GFP_KERNEL;
2338  
2339  	if (!test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state))
2340  		cnss_bus_update_status(plat_priv, CNSS_FW_DOWN);
2341  
2342  	if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state) ||
2343  	    test_bit(CNSS_DRIVER_IDLE_SHUTDOWN, &plat_priv->driver_state)) {
2344  		cnss_pr_dbg("Driver unload or idle shutdown is in progress, ignore schedule recovery\n");
2345  		return;
2346  	}
2347  
2348  	if (in_interrupt() || irqs_disabled())
2349  		gfp = GFP_ATOMIC;
2350  
2351  	data = kzalloc(sizeof(*data), gfp);
2352  	if (!data)
2353  		return;
2354  
2355  	data->reason = reason;
2356  	cnss_driver_event_post(plat_priv,
2357  			       CNSS_DRIVER_EVENT_RECOVERY,
2358  			       0, data);
2359  }
2360  EXPORT_SYMBOL(cnss_schedule_recovery);
2361  
cnss_force_fw_assert(struct device * dev)2362  int cnss_force_fw_assert(struct device *dev)
2363  {
2364  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
2365  
2366  	if (!plat_priv) {
2367  		cnss_pr_err("plat_priv is NULL\n");
2368  		return -ENODEV;
2369  	}
2370  
2371  	if (plat_priv->device_id == QCA6174_DEVICE_ID) {
2372  		cnss_pr_info("Forced FW assert is not supported\n");
2373  		return -EOPNOTSUPP;
2374  	}
2375  
2376  	if (cnss_bus_is_device_down(plat_priv)) {
2377  		cnss_pr_info("Device is already in bad state, ignore force assert\n");
2378  		return 0;
2379  	}
2380  
2381  	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
2382  		cnss_pr_info("Recovery is already in progress, ignore forced FW assert\n");
2383  		return 0;
2384  	}
2385  
2386  	if (in_interrupt() || irqs_disabled())
2387  		cnss_driver_event_post(plat_priv,
2388  				       CNSS_DRIVER_EVENT_FORCE_FW_ASSERT,
2389  				       0, NULL);
2390  	else
2391  		cnss_bus_force_fw_assert_hdlr(plat_priv);
2392  
2393  	return 0;
2394  }
2395  EXPORT_SYMBOL(cnss_force_fw_assert);
2396  
cnss_force_collect_rddm(struct device * dev)2397  int cnss_force_collect_rddm(struct device *dev)
2398  {
2399  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
2400  	unsigned int timeout;
2401  	int ret = 0;
2402  
2403  	if (!plat_priv) {
2404  		cnss_pr_err("plat_priv is NULL\n");
2405  		return -ENODEV;
2406  	}
2407  
2408  	if (plat_priv->device_id == QCA6174_DEVICE_ID) {
2409  		cnss_pr_info("Force collect rddm is not supported\n");
2410  		return -EOPNOTSUPP;
2411  	}
2412  
2413  	if (cnss_bus_is_device_down(plat_priv)) {
2414  		cnss_pr_info("Device is already in bad state, wait to collect rddm\n");
2415  		goto wait_rddm;
2416  	}
2417  
2418  	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
2419  		cnss_pr_info("Recovery is already in progress, wait to collect rddm\n");
2420  		goto wait_rddm;
2421  	}
2422  
2423  	if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
2424  	    test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state) ||
2425  	    test_bit(CNSS_DRIVER_IDLE_RESTART, &plat_priv->driver_state) ||
2426  	    test_bit(CNSS_DRIVER_IDLE_SHUTDOWN, &plat_priv->driver_state)) {
2427  		cnss_pr_info("Loading/Unloading/idle restart/shutdown is in progress, ignore forced collect rddm\n");
2428  		return 0;
2429  	}
2430  
2431  	ret = cnss_bus_force_fw_assert_hdlr(plat_priv);
2432  	if (ret)
2433  		return ret;
2434  
2435  wait_rddm:
2436  	reinit_completion(&plat_priv->rddm_complete);
2437  	timeout = cnss_get_timeout(plat_priv, CNSS_TIMEOUT_RDDM);
2438  	ret = wait_for_completion_timeout(&plat_priv->rddm_complete,
2439  					  msecs_to_jiffies(timeout));
2440  	if (!ret) {
2441  		cnss_pr_err("Timeout (%ums) waiting for RDDM to complete\n",
2442  			    timeout);
2443  		ret = -ETIMEDOUT;
2444  	} else if (ret > 0) {
2445  		ret = 0;
2446  	}
2447  
2448  	return ret;
2449  }
2450  EXPORT_SYMBOL(cnss_force_collect_rddm);
2451  
cnss_qmi_send_get(struct device * dev)2452  int cnss_qmi_send_get(struct device *dev)
2453  {
2454  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
2455  
2456  	if (!test_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state))
2457  		return 0;
2458  
2459  	return cnss_bus_qmi_send_get(plat_priv);
2460  }
2461  EXPORT_SYMBOL(cnss_qmi_send_get);
2462  
cnss_qmi_send_put(struct device * dev)2463  int cnss_qmi_send_put(struct device *dev)
2464  {
2465  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
2466  
2467  	if (!test_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state))
2468  		return 0;
2469  
2470  	return cnss_bus_qmi_send_put(plat_priv);
2471  }
2472  EXPORT_SYMBOL(cnss_qmi_send_put);
2473  
cnss_qmi_send(struct device * dev,int type,void * cmd,int cmd_len,void * cb_ctx,int (* cb)(void * ctx,void * event,int event_len))2474  int cnss_qmi_send(struct device *dev, int type, void *cmd,
2475  		  int cmd_len, void *cb_ctx,
2476  		  int (*cb)(void *ctx, void *event, int event_len))
2477  {
2478  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
2479  	int ret;
2480  
2481  	if (!plat_priv)
2482  		return -ENODEV;
2483  
2484  	if (!test_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state))
2485  		return -EINVAL;
2486  
2487  	plat_priv->get_info_cb = cb;
2488  	plat_priv->get_info_cb_ctx = cb_ctx;
2489  
2490  	ret = cnss_wlfw_get_info_send_sync(plat_priv, type, cmd, cmd_len);
2491  	if (ret) {
2492  		plat_priv->get_info_cb = NULL;
2493  		plat_priv->get_info_cb_ctx = NULL;
2494  	}
2495  
2496  	return ret;
2497  }
2498  EXPORT_SYMBOL(cnss_qmi_send);
2499  
cnss_register_driver_async_data_cb(struct device * dev,void * cb_ctx,int (* cb)(void * ctx,uint16_t type,void * event,int event_len))2500  int cnss_register_driver_async_data_cb(struct device *dev, void *cb_ctx,
2501  				       int (*cb)(void *ctx, uint16_t type,
2502  						 void *event, int event_len))
2503  {
2504  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
2505  
2506  	if (!plat_priv)
2507  		return -ENODEV;
2508  
2509  	if (!test_bit(CNSS_QMI_WLFW_CONNECTED, &plat_priv->driver_state))
2510  		return -EINVAL;
2511  
2512  	plat_priv->get_driver_async_data_cb = cb;
2513  	plat_priv->get_driver_async_data_ctx = cb_ctx;
2514  
2515  	return 0;
2516  }
2517  EXPORT_SYMBOL(cnss_register_driver_async_data_cb);
2518  
cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data * plat_priv)2519  static int cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data *plat_priv)
2520  {
2521  	int ret = 0;
2522  	u32 retry = 0, timeout;
2523  
2524  	if (test_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state)) {
2525  		cnss_pr_dbg("Calibration complete. Ignore calibration req\n");
2526  		goto out;
2527  	} else if (test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state)) {
2528  		cnss_pr_dbg("Calibration in progress. Ignore new calibration req\n");
2529  		goto out;
2530  	} else if (test_bit(CNSS_WLAN_HW_DISABLED, &plat_priv->driver_state)) {
2531  		cnss_pr_dbg("Calibration deferred as WLAN device disabled\n");
2532  		goto out;
2533  	}
2534  
2535  	if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
2536  	    test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state) ||
2537  	    test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
2538  		cnss_pr_err("WLAN in mission mode before cold boot calibration\n");
2539  		CNSS_ASSERT(0);
2540  		return -EINVAL;
2541  	}
2542  
2543  	while (retry++ < CNSS_CAL_START_PROBE_WAIT_RETRY_MAX) {
2544  		if (test_bit(CNSS_PCI_PROBE_DONE, &plat_priv->driver_state))
2545  			break;
2546  		msleep(CNSS_CAL_START_PROBE_WAIT_MS);
2547  
2548  		if (retry == CNSS_CAL_START_PROBE_WAIT_RETRY_MAX) {
2549  			cnss_pr_err("Calibration start failed as PCI probe not complete\n");
2550  			CNSS_ASSERT(0);
2551  			ret = -EINVAL;
2552  			goto mark_cal_fail;
2553  		}
2554  	}
2555  
2556  	switch (plat_priv->device_id) {
2557  	case QCA6290_DEVICE_ID:
2558  	case QCA6390_DEVICE_ID:
2559  	case QCA6490_DEVICE_ID:
2560  	case KIWI_DEVICE_ID:
2561  	case MANGO_DEVICE_ID:
2562  	case PEACH_DEVICE_ID:
2563  		break;
2564  	default:
2565  		cnss_pr_err("Not supported for device ID 0x%lx\n",
2566  			    plat_priv->device_id);
2567  		ret = -EINVAL;
2568  		goto mark_cal_fail;
2569  	}
2570  
2571  	set_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state);
2572  	if (test_bit(CNSS_DRIVER_REGISTER, &plat_priv->driver_state)) {
2573  		timeout = cnss_get_timeout(plat_priv,
2574  					   CNSS_TIMEOUT_CALIBRATION);
2575  		cnss_pr_dbg("Restarting calibration %ds timeout\n",
2576  			    timeout / 1000);
2577  		if (cancel_delayed_work_sync(&plat_priv->wlan_reg_driver_work))
2578  			schedule_delayed_work(&plat_priv->wlan_reg_driver_work,
2579  					      msecs_to_jiffies(timeout));
2580  	}
2581  	reinit_completion(&plat_priv->cal_complete);
2582  	ret = cnss_bus_dev_powerup(plat_priv);
2583  mark_cal_fail:
2584  	if (ret) {
2585  		complete(&plat_priv->cal_complete);
2586  		clear_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state);
2587  		/* Set CBC done in driver state to mark attempt and note error
2588  		 * since calibration cannot be retried at boot.
2589  		 */
2590  		plat_priv->cal_done = CNSS_CAL_FAILURE;
2591  		set_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state);
2592  
2593  		if (plat_priv->device_id == QCA6174_DEVICE_ID ||
2594  		    plat_priv->device_id == QCN7605_DEVICE_ID) {
2595  			if (!test_bit(CNSS_DRIVER_REGISTER, &plat_priv->driver_state))
2596  				goto out;
2597  
2598  			cnss_pr_info("Schedule WLAN driver load\n");
2599  
2600  			if (cancel_delayed_work_sync(&plat_priv->wlan_reg_driver_work))
2601  				schedule_delayed_work(&plat_priv->wlan_reg_driver_work,
2602  						      0);
2603  		}
2604  	}
2605  
2606  out:
2607  	return ret;
2608  }
2609  
cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data * plat_priv,void * data)2610  static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv,
2611  					void *data)
2612  {
2613  	struct cnss_cal_info *cal_info = data;
2614  
2615  	if (!test_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state) ||
2616  	    test_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state))
2617  		goto out;
2618  
2619  	switch (cal_info->cal_status) {
2620  	case CNSS_CAL_DONE:
2621  		cnss_pr_dbg("Calibration completed successfully\n");
2622  		plat_priv->cal_done = true;
2623  		break;
2624  	case CNSS_CAL_TIMEOUT:
2625  	case CNSS_CAL_FAILURE:
2626  		cnss_pr_dbg("Calibration failed. Status: %d, force shutdown\n",
2627  			    cal_info->cal_status);
2628  		break;
2629  	default:
2630  		cnss_pr_err("Unknown calibration status: %u\n",
2631  			    cal_info->cal_status);
2632  		break;
2633  	}
2634  
2635  	cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_OFF);
2636  	cnss_bus_free_qdss_mem(plat_priv);
2637  	cnss_release_antenna_sharing(plat_priv);
2638  
2639  	if (plat_priv->device_id == QCN7605_DEVICE_ID)
2640  		goto skip_shutdown;
2641  
2642  	cnss_bus_dev_shutdown(plat_priv);
2643  	msleep(POWER_RESET_MIN_DELAY_MS);
2644  
2645  skip_shutdown:
2646  	complete(&plat_priv->cal_complete);
2647  	clear_bit(CNSS_IN_COLD_BOOT_CAL, &plat_priv->driver_state);
2648  	set_bit(CNSS_COLD_BOOT_CAL_DONE, &plat_priv->driver_state);
2649  
2650  	if (cal_info->cal_status == CNSS_CAL_DONE) {
2651  		cnss_cal_mem_upload_to_file(plat_priv);
2652  		if (!test_bit(CNSS_DRIVER_REGISTER, &plat_priv->driver_state))
2653  			goto out;
2654  
2655  		cnss_pr_dbg("Schedule WLAN driver load\n");
2656  		if (cancel_delayed_work_sync(&plat_priv->wlan_reg_driver_work))
2657  			schedule_delayed_work(&plat_priv->wlan_reg_driver_work,
2658  					      0);
2659  	}
2660  out:
2661  	kfree(data);
2662  	return 0;
2663  }
2664  
cnss_power_up_hdlr(struct cnss_plat_data * plat_priv)2665  static int cnss_power_up_hdlr(struct cnss_plat_data *plat_priv)
2666  {
2667  	int ret;
2668  
2669  	ret = cnss_bus_dev_powerup(plat_priv);
2670  	if (ret)
2671  		clear_bit(CNSS_DRIVER_IDLE_RESTART, &plat_priv->driver_state);
2672  
2673  	return ret;
2674  }
2675  
cnss_power_down_hdlr(struct cnss_plat_data * plat_priv)2676  static int cnss_power_down_hdlr(struct cnss_plat_data *plat_priv)
2677  {
2678  	cnss_bus_dev_shutdown(plat_priv);
2679  
2680  	return 0;
2681  }
2682  
cnss_qdss_trace_req_mem_hdlr(struct cnss_plat_data * plat_priv)2683  static int cnss_qdss_trace_req_mem_hdlr(struct cnss_plat_data *plat_priv)
2684  {
2685  	int ret = 0;
2686  
2687  	ret = cnss_bus_alloc_qdss_mem(plat_priv);
2688  	if (ret < 0)
2689  		return ret;
2690  
2691  	return cnss_wlfw_qdss_trace_mem_info_send_sync(plat_priv);
2692  }
2693  
cnss_get_fw_mem_pa_to_va(struct cnss_fw_mem * fw_mem,u32 mem_seg_len,u64 pa,u32 size)2694  static void *cnss_get_fw_mem_pa_to_va(struct cnss_fw_mem *fw_mem,
2695  				      u32 mem_seg_len, u64 pa, u32 size)
2696  {
2697  	int i = 0;
2698  	u64 offset = 0;
2699  	void *va = NULL;
2700  	u64 local_pa;
2701  	u32 local_size;
2702  
2703  	for (i = 0; i < mem_seg_len; i++) {
2704  		if (i == QMI_WLFW_MEM_LPASS_SHARED_V01)
2705  			continue;
2706  
2707  		local_pa = (u64)fw_mem[i].pa;
2708  		local_size = (u32)fw_mem[i].size;
2709  		if (pa == local_pa && size <= local_size) {
2710  			va = fw_mem[i].va;
2711  			break;
2712  		}
2713  		if (pa > local_pa &&
2714  		    pa < local_pa + local_size &&
2715  		    pa + size <= local_pa + local_size) {
2716  			offset = pa - local_pa;
2717  			va = fw_mem[i].va + offset;
2718  			break;
2719  		}
2720  	}
2721  	return va;
2722  }
2723  
cnss_fw_mem_file_save_hdlr(struct cnss_plat_data * plat_priv,void * data)2724  static int cnss_fw_mem_file_save_hdlr(struct cnss_plat_data *plat_priv,
2725  				      void *data)
2726  {
2727  	struct cnss_qmi_event_fw_mem_file_save_data *event_data = data;
2728  	struct cnss_fw_mem *fw_mem_seg;
2729  	int ret = 0L;
2730  	void *va = NULL;
2731  	u32 i, fw_mem_seg_len;
2732  
2733  	switch (event_data->mem_type) {
2734  	case QMI_WLFW_MEM_TYPE_DDR_V01:
2735  		if (!plat_priv->fw_mem_seg_len)
2736  			goto invalid_mem_save;
2737  
2738  		fw_mem_seg = plat_priv->fw_mem;
2739  		fw_mem_seg_len = plat_priv->fw_mem_seg_len;
2740  		break;
2741  	case QMI_WLFW_MEM_QDSS_V01:
2742  		if (!plat_priv->qdss_mem_seg_len)
2743  			goto invalid_mem_save;
2744  
2745  		fw_mem_seg = plat_priv->qdss_mem;
2746  		fw_mem_seg_len = plat_priv->qdss_mem_seg_len;
2747  		break;
2748  	default:
2749  		goto invalid_mem_save;
2750  	}
2751  
2752  	for (i = 0; i < event_data->mem_seg_len; i++) {
2753  		va = cnss_get_fw_mem_pa_to_va(fw_mem_seg, fw_mem_seg_len,
2754  					      event_data->mem_seg[i].addr,
2755  					      event_data->mem_seg[i].size);
2756  		if (!va) {
2757  			cnss_pr_err("Fail to find matching va of pa %pa for mem type: %d\n",
2758  				    &event_data->mem_seg[i].addr,
2759  				    event_data->mem_type);
2760  			ret = -EINVAL;
2761  			break;
2762  		}
2763  		ret = cnss_genl_send_msg(va, CNSS_GENL_MSG_TYPE_QDSS,
2764  					 event_data->file_name,
2765  					 event_data->mem_seg[i].size);
2766  		if (ret < 0) {
2767  			cnss_pr_err("Fail to save fw mem data: %d\n",
2768  				    ret);
2769  			break;
2770  		}
2771  	}
2772  	kfree(data);
2773  	return ret;
2774  
2775  invalid_mem_save:
2776  	cnss_pr_err("FW Mem type %d not allocated. Invalid save request\n",
2777  		    event_data->mem_type);
2778  	kfree(data);
2779  	return -EINVAL;
2780  }
2781  
cnss_qdss_trace_free_hdlr(struct cnss_plat_data * plat_priv)2782  static int cnss_qdss_trace_free_hdlr(struct cnss_plat_data *plat_priv)
2783  {
2784  	cnss_bus_free_qdss_mem(plat_priv);
2785  
2786  	return 0;
2787  }
2788  
cnss_qdss_trace_req_data_hdlr(struct cnss_plat_data * plat_priv,void * data)2789  static int cnss_qdss_trace_req_data_hdlr(struct cnss_plat_data *plat_priv,
2790  					 void *data)
2791  {
2792  	int ret = 0;
2793  	struct cnss_qmi_event_fw_mem_file_save_data *event_data = data;
2794  
2795  	if (!plat_priv)
2796  		return -ENODEV;
2797  
2798  	ret = cnss_wlfw_qdss_data_send_sync(plat_priv, event_data->file_name,
2799  					    event_data->total_size);
2800  
2801  	kfree(data);
2802  	return ret;
2803  }
2804  
cnss_driver_event_work(struct work_struct * work)2805  static void cnss_driver_event_work(struct work_struct *work)
2806  {
2807  	struct cnss_plat_data *plat_priv =
2808  		container_of(work, struct cnss_plat_data, event_work);
2809  	struct cnss_driver_event *event;
2810  	unsigned long flags;
2811  	int ret = 0;
2812  
2813  	if (!plat_priv) {
2814  		cnss_pr_err("plat_priv is NULL!\n");
2815  		return;
2816  	}
2817  
2818  	cnss_pm_stay_awake(plat_priv);
2819  
2820  	spin_lock_irqsave(&plat_priv->event_lock, flags);
2821  
2822  	while (!list_empty(&plat_priv->event_list)) {
2823  		event = list_first_entry(&plat_priv->event_list,
2824  					 struct cnss_driver_event, list);
2825  		list_del(&event->list);
2826  		spin_unlock_irqrestore(&plat_priv->event_lock, flags);
2827  
2828  		cnss_pr_dbg("Processing driver event: %s%s(%d), state: 0x%lx\n",
2829  			    cnss_driver_event_to_str(event->type),
2830  			    event->sync ? "-sync" : "", event->type,
2831  			    plat_priv->driver_state);
2832  
2833  		switch (event->type) {
2834  		case CNSS_DRIVER_EVENT_SERVER_ARRIVE:
2835  			ret = cnss_wlfw_server_arrive(plat_priv, event->data);
2836  			break;
2837  		case CNSS_DRIVER_EVENT_SERVER_EXIT:
2838  			ret = cnss_wlfw_server_exit(plat_priv);
2839  			break;
2840  		case CNSS_DRIVER_EVENT_REQUEST_MEM:
2841  			ret = cnss_bus_alloc_fw_mem(plat_priv);
2842  			if (ret)
2843  				break;
2844  			ret = cnss_wlfw_respond_mem_send_sync(plat_priv);
2845  			break;
2846  		case CNSS_DRIVER_EVENT_FW_MEM_READY:
2847  			ret = cnss_fw_mem_ready_hdlr(plat_priv);
2848  			break;
2849  		case CNSS_DRIVER_EVENT_FW_READY:
2850  			ret = cnss_fw_ready_hdlr(plat_priv);
2851  			break;
2852  		case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START:
2853  			ret = cnss_cold_boot_cal_start_hdlr(plat_priv);
2854  			break;
2855  		case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE:
2856  			ret = cnss_cold_boot_cal_done_hdlr(plat_priv,
2857  							   event->data);
2858  			break;
2859  		case CNSS_DRIVER_EVENT_REGISTER_DRIVER:
2860  			ret = cnss_bus_register_driver_hdlr(plat_priv,
2861  							    event->data);
2862  			break;
2863  		case CNSS_DRIVER_EVENT_UNREGISTER_DRIVER:
2864  			ret = cnss_bus_unregister_driver_hdlr(plat_priv);
2865  			break;
2866  		case CNSS_DRIVER_EVENT_RECOVERY:
2867  			ret = cnss_driver_recovery_hdlr(plat_priv,
2868  							event->data);
2869  			break;
2870  		case CNSS_DRIVER_EVENT_FORCE_FW_ASSERT:
2871  			ret = cnss_bus_force_fw_assert_hdlr(plat_priv);
2872  			break;
2873  		case CNSS_DRIVER_EVENT_IDLE_RESTART:
2874  			set_bit(CNSS_DRIVER_IDLE_RESTART,
2875  				&plat_priv->driver_state);
2876  			fallthrough;
2877  		case CNSS_DRIVER_EVENT_POWER_UP:
2878  			ret = cnss_power_up_hdlr(plat_priv);
2879  			break;
2880  		case CNSS_DRIVER_EVENT_IDLE_SHUTDOWN:
2881  			set_bit(CNSS_DRIVER_IDLE_SHUTDOWN,
2882  				&plat_priv->driver_state);
2883  			fallthrough;
2884  		case CNSS_DRIVER_EVENT_POWER_DOWN:
2885  			ret = cnss_power_down_hdlr(plat_priv);
2886  			break;
2887  		case CNSS_DRIVER_EVENT_IMS_WFC_CALL_IND:
2888  			ret = cnss_process_wfc_call_ind_event(plat_priv,
2889  							      event->data);
2890  			break;
2891  		case CNSS_DRIVER_EVENT_WLFW_TWT_CFG_IND:
2892  			ret = cnss_process_twt_cfg_ind_event(plat_priv,
2893  							     event->data);
2894  			break;
2895  		case CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_MEM:
2896  			ret = cnss_qdss_trace_req_mem_hdlr(plat_priv);
2897  			break;
2898  		case CNSS_DRIVER_EVENT_FW_MEM_FILE_SAVE:
2899  			ret = cnss_fw_mem_file_save_hdlr(plat_priv,
2900  							 event->data);
2901  			break;
2902  		case CNSS_DRIVER_EVENT_QDSS_TRACE_FREE:
2903  			ret = cnss_qdss_trace_free_hdlr(plat_priv);
2904  			break;
2905  		case CNSS_DRIVER_EVENT_QDSS_TRACE_REQ_DATA:
2906  			ret = cnss_qdss_trace_req_data_hdlr(plat_priv,
2907  							    event->data);
2908  			break;
2909  		default:
2910  			cnss_pr_err("Invalid driver event type: %d",
2911  				    event->type);
2912  			kfree(event);
2913  			spin_lock_irqsave(&plat_priv->event_lock, flags);
2914  			continue;
2915  		}
2916  
2917  		spin_lock_irqsave(&plat_priv->event_lock, flags);
2918  		if (event->sync) {
2919  			event->ret = ret;
2920  			complete(&event->complete);
2921  			continue;
2922  		}
2923  		spin_unlock_irqrestore(&plat_priv->event_lock, flags);
2924  
2925  		kfree(event);
2926  
2927  		spin_lock_irqsave(&plat_priv->event_lock, flags);
2928  	}
2929  	spin_unlock_irqrestore(&plat_priv->event_lock, flags);
2930  
2931  	cnss_pm_relax(plat_priv);
2932  }
2933  
2934  #if IS_ENABLED(CONFIG_MSM_SUBSYSTEM_RESTART)
cnss_register_subsys(struct cnss_plat_data * plat_priv)2935  int cnss_register_subsys(struct cnss_plat_data *plat_priv)
2936  {
2937  	int ret = 0;
2938  	struct cnss_subsys_info *subsys_info;
2939  
2940  	subsys_info = &plat_priv->subsys_info;
2941  
2942  	subsys_info->subsys_desc.name = plat_priv->device_name;
2943  	subsys_info->subsys_desc.owner = THIS_MODULE;
2944  	subsys_info->subsys_desc.powerup = cnss_subsys_powerup;
2945  	subsys_info->subsys_desc.shutdown = cnss_subsys_shutdown;
2946  	subsys_info->subsys_desc.ramdump = cnss_subsys_ramdump;
2947  	subsys_info->subsys_desc.crash_shutdown = cnss_subsys_crash_shutdown;
2948  	subsys_info->subsys_desc.dev = &plat_priv->plat_dev->dev;
2949  
2950  	subsys_info->subsys_device = subsys_register(&subsys_info->subsys_desc);
2951  	if (IS_ERR(subsys_info->subsys_device)) {
2952  		ret = PTR_ERR(subsys_info->subsys_device);
2953  		cnss_pr_err("Failed to register subsys, err = %d\n", ret);
2954  		goto out;
2955  	}
2956  
2957  	subsys_info->subsys_handle =
2958  		subsystem_get(subsys_info->subsys_desc.name);
2959  	if (!subsys_info->subsys_handle) {
2960  		cnss_pr_err("Failed to get subsys_handle!\n");
2961  		ret = -EINVAL;
2962  		goto unregister_subsys;
2963  	} else if (IS_ERR(subsys_info->subsys_handle)) {
2964  		ret = PTR_ERR(subsys_info->subsys_handle);
2965  		cnss_pr_err("Failed to do subsystem_get, err = %d\n", ret);
2966  		goto unregister_subsys;
2967  	}
2968  
2969  	return 0;
2970  
2971  unregister_subsys:
2972  	subsys_unregister(subsys_info->subsys_device);
2973  out:
2974  	return ret;
2975  }
2976  
cnss_unregister_subsys(struct cnss_plat_data * plat_priv)2977  void cnss_unregister_subsys(struct cnss_plat_data *plat_priv)
2978  {
2979  	struct cnss_subsys_info *subsys_info;
2980  
2981  	subsys_info = &plat_priv->subsys_info;
2982  	subsystem_put(subsys_info->subsys_handle);
2983  	subsys_unregister(subsys_info->subsys_device);
2984  }
2985  
cnss_create_ramdump_device(struct cnss_plat_data * plat_priv)2986  static void *cnss_create_ramdump_device(struct cnss_plat_data *plat_priv)
2987  {
2988  	struct cnss_subsys_info *subsys_info = &plat_priv->subsys_info;
2989  
2990  	return create_ramdump_device(subsys_info->subsys_desc.name,
2991  				     subsys_info->subsys_desc.dev);
2992  }
2993  
cnss_destroy_ramdump_device(struct cnss_plat_data * plat_priv,void * ramdump_dev)2994  static void cnss_destroy_ramdump_device(struct cnss_plat_data *plat_priv,
2995  					void *ramdump_dev)
2996  {
2997  	destroy_ramdump_device(ramdump_dev);
2998  }
2999  
cnss_do_ramdump(struct cnss_plat_data * plat_priv)3000  int cnss_do_ramdump(struct cnss_plat_data *plat_priv)
3001  {
3002  	struct cnss_ramdump_info *ramdump_info = &plat_priv->ramdump_info;
3003  	struct ramdump_segment segment;
3004  
3005  	memset(&segment, 0, sizeof(segment));
3006  	segment.v_address = (void __iomem *)ramdump_info->ramdump_va;
3007  	segment.size = ramdump_info->ramdump_size;
3008  
3009  	return qcom_ramdump(ramdump_info->ramdump_dev, &segment, 1);
3010  }
3011  
cnss_do_elf_ramdump(struct cnss_plat_data * plat_priv)3012  int cnss_do_elf_ramdump(struct cnss_plat_data *plat_priv)
3013  {
3014  	struct cnss_ramdump_info_v2 *info_v2 = &plat_priv->ramdump_info_v2;
3015  	struct cnss_dump_data *dump_data = &info_v2->dump_data;
3016  	struct cnss_dump_seg *dump_seg = info_v2->dump_data_vaddr;
3017  	struct ramdump_segment *ramdump_segs, *s;
3018  	struct cnss_dump_meta_info meta_info = {0};
3019  	int i, ret = 0;
3020  
3021  	ramdump_segs = kcalloc(dump_data->nentries + 1,
3022  			       sizeof(*ramdump_segs),
3023  			       GFP_KERNEL);
3024  	if (!ramdump_segs)
3025  		return -ENOMEM;
3026  
3027  	s = ramdump_segs + 1;
3028  	for (i = 0; i < dump_data->nentries; i++) {
3029  		if (dump_seg->type >= CNSS_FW_DUMP_TYPE_MAX) {
3030  			cnss_pr_err("Unsupported dump type: %d",
3031  				    dump_seg->type);
3032  			continue;
3033  		}
3034  
3035  		if (meta_info.entry[dump_seg->type].entry_start == 0) {
3036  			meta_info.entry[dump_seg->type].type = dump_seg->type;
3037  			meta_info.entry[dump_seg->type].entry_start = i + 1;
3038  		}
3039  		meta_info.entry[dump_seg->type].entry_num++;
3040  
3041  		s->address = dump_seg->address;
3042  		s->v_address = (void __iomem *)dump_seg->v_address;
3043  		s->size = dump_seg->size;
3044  		s++;
3045  		dump_seg++;
3046  	}
3047  
3048  	meta_info.magic = CNSS_RAMDUMP_MAGIC;
3049  	meta_info.version = CNSS_RAMDUMP_VERSION;
3050  	meta_info.chipset = plat_priv->device_id;
3051  	meta_info.total_entries = CNSS_FW_DUMP_TYPE_MAX;
3052  
3053  	ramdump_segs->v_address = (void __iomem *)(&meta_info);
3054  	ramdump_segs->size = sizeof(meta_info);
3055  
3056  	ret = qcom_elf_ramdump(info_v2->ramdump_dev, ramdump_segs,
3057  			       dump_data->nentries + 1);
3058  	kfree(ramdump_segs);
3059  
3060  	return ret;
3061  }
3062  #else
cnss_panic_handler(struct notifier_block * nb,unsigned long action,void * data)3063  static int cnss_panic_handler(struct notifier_block *nb, unsigned long action,
3064  			      void *data)
3065  {
3066  	struct cnss_plat_data *plat_priv =
3067  		container_of(nb, struct cnss_plat_data, panic_nb);
3068  
3069  	cnss_bus_dev_crash_shutdown(plat_priv);
3070  
3071  	return NOTIFY_DONE;
3072  }
3073  
cnss_register_subsys(struct cnss_plat_data * plat_priv)3074  int cnss_register_subsys(struct cnss_plat_data *plat_priv)
3075  {
3076  	int ret;
3077  
3078  	if (!plat_priv)
3079  		return -ENODEV;
3080  
3081  	plat_priv->panic_nb.notifier_call = cnss_panic_handler;
3082  	ret = atomic_notifier_chain_register(&panic_notifier_list,
3083  					     &plat_priv->panic_nb);
3084  	if (ret) {
3085  		cnss_pr_err("Failed to register panic handler\n");
3086  		return -EINVAL;
3087  	}
3088  
3089  	return 0;
3090  }
3091  
cnss_unregister_subsys(struct cnss_plat_data * plat_priv)3092  void cnss_unregister_subsys(struct cnss_plat_data *plat_priv)
3093  {
3094  	int ret;
3095  
3096  	ret = atomic_notifier_chain_unregister(&panic_notifier_list,
3097  					       &plat_priv->panic_nb);
3098  	if (ret)
3099  		cnss_pr_err("Failed to unregister panic handler\n");
3100  }
3101  
3102  #if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2)
cnss_create_ramdump_device(struct cnss_plat_data * plat_priv)3103  static void *cnss_create_ramdump_device(struct cnss_plat_data *plat_priv)
3104  {
3105  	return &plat_priv->plat_dev->dev;
3106  }
3107  
cnss_destroy_ramdump_device(struct cnss_plat_data * plat_priv,void * ramdump_dev)3108  static void cnss_destroy_ramdump_device(struct cnss_plat_data *plat_priv,
3109  					void *ramdump_dev)
3110  {
3111  }
3112  #endif
3113  
3114  #if IS_ENABLED(CONFIG_QCOM_RAMDUMP)
cnss_do_ramdump(struct cnss_plat_data * plat_priv)3115  int cnss_do_ramdump(struct cnss_plat_data *plat_priv)
3116  {
3117  	struct cnss_ramdump_info *ramdump_info = &plat_priv->ramdump_info;
3118  	struct qcom_dump_segment segment;
3119  	struct list_head head;
3120  
3121  	if (!dump_enabled()) {
3122  		cnss_pr_info("Dump collection is not enabled\n");
3123  		return 0;
3124  	}
3125  	INIT_LIST_HEAD(&head);
3126  	memset(&segment, 0, sizeof(segment));
3127  	segment.va = ramdump_info->ramdump_va;
3128  	segment.size = ramdump_info->ramdump_size;
3129  	list_add(&segment.node, &head);
3130  
3131  	return qcom_dump(&head, ramdump_info->ramdump_dev);
3132  }
3133  #else
cnss_do_ramdump(struct cnss_plat_data * plat_priv)3134  int cnss_do_ramdump(struct cnss_plat_data *plat_priv)
3135  {
3136  	return 0;
3137  }
3138  
3139  /* Using completion event inside dynamically allocated ramdump_desc
3140   * may result a race between freeing the event after setting it to
3141   * complete inside dev coredump free callback and the thread that is
3142   * waiting for completion.
3143   */
3144  DECLARE_COMPLETION(dump_done);
3145  #define TIMEOUT_SAVE_DUMP_MS 30000
3146  
3147  #define SIZEOF_ELF_STRUCT(__xhdr)					\
3148  static inline size_t sizeof_elf_##__xhdr(unsigned char class)		\
3149  {									\
3150  	if (class == ELFCLASS32)					\
3151  		return sizeof(struct elf32_##__xhdr);			\
3152  	else								\
3153  		return sizeof(struct elf64_##__xhdr);			\
3154  }
3155  
3156  SIZEOF_ELF_STRUCT(phdr)
3157  SIZEOF_ELF_STRUCT(hdr)
3158  
3159  #define set_xhdr_property(__xhdr, arg, class, member, value)		\
3160  do {									\
3161  	if (class == ELFCLASS32)					\
3162  		((struct elf32_##__xhdr *)arg)->member = value;		\
3163  	else								\
3164  		((struct elf64_##__xhdr *)arg)->member = value;		\
3165  } while (0)
3166  
3167  #define set_ehdr_property(arg, class, member, value) \
3168  	set_xhdr_property(hdr, arg, class, member, value)
3169  #define set_phdr_property(arg, class, member, value) \
3170  	set_xhdr_property(phdr, arg, class, member, value)
3171  
3172  /* These replace qcom_ramdump driver APIs called from common API
3173   * cnss_do_elf_dump() by the ones defined here.
3174   */
3175  #define qcom_dump_segment cnss_qcom_dump_segment
3176  #define qcom_elf_dump cnss_qcom_elf_dump
3177  #define dump_enabled cnss_dump_enabled
3178  
3179  struct cnss_qcom_dump_segment {
3180  	struct list_head node;
3181  	dma_addr_t da;
3182  	void *va;
3183  	size_t size;
3184  };
3185  
3186  struct cnss_qcom_ramdump_desc {
3187  	void *data;
3188  	struct completion dump_done;
3189  };
3190  
cnss_qcom_devcd_readv(char * buffer,loff_t offset,size_t count,void * data,size_t datalen)3191  static ssize_t cnss_qcom_devcd_readv(char *buffer, loff_t offset, size_t count,
3192  				     void *data, size_t datalen)
3193  {
3194  	struct cnss_qcom_ramdump_desc *desc = data;
3195  
3196  	return memory_read_from_buffer(buffer, count, &offset, desc->data,
3197  				       datalen);
3198  }
3199  
cnss_qcom_devcd_freev(void * data)3200  static void cnss_qcom_devcd_freev(void *data)
3201  {
3202  	struct cnss_qcom_ramdump_desc *desc = data;
3203  
3204  	cnss_pr_dbg("Free dump data for dev coredump\n");
3205  
3206  	complete(&dump_done);
3207  	vfree(desc->data);
3208  	kfree(desc);
3209  }
3210  
cnss_qcom_devcd_dump(struct device * dev,void * data,size_t datalen,gfp_t gfp)3211  static int cnss_qcom_devcd_dump(struct device *dev, void *data, size_t datalen,
3212  				gfp_t gfp)
3213  {
3214  	struct cnss_qcom_ramdump_desc *desc;
3215  	unsigned int timeout = TIMEOUT_SAVE_DUMP_MS;
3216  	int ret;
3217  
3218  	desc = kmalloc(sizeof(*desc), GFP_KERNEL);
3219  	if (!desc)
3220  		return -ENOMEM;
3221  
3222  	desc->data = data;
3223  	reinit_completion(&dump_done);
3224  
3225  	dev_coredumpm(dev, NULL, desc, datalen, gfp,
3226  		      cnss_qcom_devcd_readv, cnss_qcom_devcd_freev);
3227  
3228  	ret = wait_for_completion_timeout(&dump_done,
3229  					  msecs_to_jiffies(timeout));
3230  	if (!ret)
3231  		cnss_pr_err("Timeout waiting (%dms) for saving dump to file system\n",
3232  			    timeout);
3233  
3234  	return ret ? 0 : -ETIMEDOUT;
3235  }
3236  
3237  /* Since the elf32 and elf64 identification is identical apart from
3238   * the class, use elf32 by default.
3239   */
init_elf_identification(struct elf32_hdr * ehdr,unsigned char class)3240  static void init_elf_identification(struct elf32_hdr *ehdr, unsigned char class)
3241  {
3242  	memcpy(ehdr->e_ident, ELFMAG, SELFMAG);
3243  	ehdr->e_ident[EI_CLASS] = class;
3244  	ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
3245  	ehdr->e_ident[EI_VERSION] = EV_CURRENT;
3246  	ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
3247  }
3248  
cnss_qcom_elf_dump(struct list_head * segs,struct device * dev,unsigned char class)3249  int cnss_qcom_elf_dump(struct list_head *segs, struct device *dev,
3250  		       unsigned char class)
3251  {
3252  	struct cnss_qcom_dump_segment *segment;
3253  	void *phdr, *ehdr;
3254  	size_t data_size, offset;
3255  	int phnum = 0;
3256  	void *data;
3257  	void __iomem *ptr;
3258  
3259  	if (!segs || list_empty(segs))
3260  		return -EINVAL;
3261  
3262  	data_size = sizeof_elf_hdr(class);
3263  	list_for_each_entry(segment, segs, node) {
3264  		data_size += sizeof_elf_phdr(class) + segment->size;
3265  		phnum++;
3266  	}
3267  
3268  	data = vmalloc(data_size);
3269  	if (!data)
3270  		return -ENOMEM;
3271  
3272  	cnss_pr_dbg("Creating ELF file with size %d\n", data_size);
3273  
3274  	ehdr = data;
3275  	memset(ehdr, 0, sizeof_elf_hdr(class));
3276  	init_elf_identification(ehdr, class);
3277  	set_ehdr_property(ehdr, class, e_type, ET_CORE);
3278  	set_ehdr_property(ehdr, class, e_machine, EM_NONE);
3279  	set_ehdr_property(ehdr, class, e_version, EV_CURRENT);
3280  	set_ehdr_property(ehdr, class, e_phoff, sizeof_elf_hdr(class));
3281  	set_ehdr_property(ehdr, class, e_ehsize, sizeof_elf_hdr(class));
3282  	set_ehdr_property(ehdr, class, e_phentsize, sizeof_elf_phdr(class));
3283  	set_ehdr_property(ehdr, class, e_phnum, phnum);
3284  
3285  	phdr = data + sizeof_elf_hdr(class);
3286  	offset = sizeof_elf_hdr(class) + sizeof_elf_phdr(class) * phnum;
3287  	list_for_each_entry(segment, segs, node) {
3288  		memset(phdr, 0, sizeof_elf_phdr(class));
3289  		set_phdr_property(phdr, class, p_type, PT_LOAD);
3290  		set_phdr_property(phdr, class, p_offset, offset);
3291  		set_phdr_property(phdr, class, p_vaddr, segment->da);
3292  		set_phdr_property(phdr, class, p_paddr, segment->da);
3293  		set_phdr_property(phdr, class, p_filesz, segment->size);
3294  		set_phdr_property(phdr, class, p_memsz, segment->size);
3295  		set_phdr_property(phdr, class, p_flags, PF_R | PF_W | PF_X);
3296  		set_phdr_property(phdr, class, p_align, 0);
3297  
3298  		if (segment->va) {
3299  			memcpy(data + offset, segment->va, segment->size);
3300  		} else {
3301  			ptr = devm_ioremap(dev, segment->da, segment->size);
3302  			if (!ptr) {
3303  				cnss_pr_err("Invalid coredump segment (%pad, %zu)\n",
3304  					    &segment->da, segment->size);
3305  				memset(data + offset, 0xff, segment->size);
3306  			} else {
3307  				memcpy_fromio(data + offset, ptr,
3308  					      segment->size);
3309  			}
3310  		}
3311  
3312  		offset += segment->size;
3313  		phdr += sizeof_elf_phdr(class);
3314  	}
3315  
3316  	return cnss_qcom_devcd_dump(dev, data, data_size, GFP_KERNEL);
3317  }
3318  
3319  /* Saving dump to file system is always needed in this case. */
cnss_dump_enabled(void)3320  static bool cnss_dump_enabled(void)
3321  {
3322  	return true;
3323  }
3324  #endif /* CONFIG_QCOM_RAMDUMP */
3325  
cnss_do_elf_ramdump(struct cnss_plat_data * plat_priv)3326  int cnss_do_elf_ramdump(struct cnss_plat_data *plat_priv)
3327  {
3328  	struct cnss_ramdump_info_v2 *info_v2 = &plat_priv->ramdump_info_v2;
3329  	struct cnss_dump_data *dump_data = &info_v2->dump_data;
3330  	struct cnss_dump_seg *dump_seg = info_v2->dump_data_vaddr;
3331  	struct qcom_dump_segment *seg;
3332  	struct cnss_dump_meta_info meta_info = {0};
3333  	struct list_head head;
3334  	int i, ret = 0;
3335  
3336  	if (!dump_enabled()) {
3337  		cnss_pr_info("Dump collection is not enabled\n");
3338  		return ret;
3339  	}
3340  
3341  	INIT_LIST_HEAD(&head);
3342  	for (i = 0; i < dump_data->nentries; i++) {
3343  		if (dump_seg->type >= CNSS_FW_DUMP_TYPE_MAX) {
3344  			cnss_pr_err("Unsupported dump type: %d",
3345  				    dump_seg->type);
3346  			continue;
3347  		}
3348  
3349  		seg = kcalloc(1, sizeof(*seg), GFP_KERNEL);
3350  		if (!seg) {
3351  			cnss_pr_err("%s: Failed to allocate mem for seg %d\n",
3352  				    __func__, i);
3353  			continue;
3354  		}
3355  
3356  		if (meta_info.entry[dump_seg->type].entry_start == 0) {
3357  			meta_info.entry[dump_seg->type].type = dump_seg->type;
3358  			meta_info.entry[dump_seg->type].entry_start = i + 1;
3359  		}
3360  		meta_info.entry[dump_seg->type].entry_num++;
3361  		seg->da = dump_seg->address;
3362  		seg->va = dump_seg->v_address;
3363  		seg->size = dump_seg->size;
3364  		list_add_tail(&seg->node, &head);
3365  		dump_seg++;
3366  	}
3367  
3368  	seg = kcalloc(1, sizeof(*seg), GFP_KERNEL);
3369  	if (!seg) {
3370  		cnss_pr_err("%s: Failed to allocate mem for elf ramdump seg\n",
3371  			    __func__);
3372  		goto skip_elf_dump;
3373  	}
3374  
3375  	meta_info.magic = CNSS_RAMDUMP_MAGIC;
3376  	meta_info.version = CNSS_RAMDUMP_VERSION;
3377  	meta_info.chipset = plat_priv->device_id;
3378  	meta_info.total_entries = CNSS_FW_DUMP_TYPE_MAX;
3379  	seg->va = &meta_info;
3380  	seg->size = sizeof(meta_info);
3381  	list_add(&seg->node, &head);
3382  
3383  	ret = qcom_elf_dump(&head, info_v2->ramdump_dev, ELF_CLASS);
3384  
3385  skip_elf_dump:
3386  	while (!list_empty(&head)) {
3387  		seg = list_first_entry(&head, struct qcom_dump_segment, node);
3388  		list_del(&seg->node);
3389  		kfree(seg);
3390  	}
3391  
3392  	return ret;
3393  }
3394  
3395  #ifdef CONFIG_CNSS2_SSR_DRIVER_DUMP
3396  /**
3397   * cnss_host_ramdump_dev_release() - callback function for device release
3398   * @dev: device to be released
3399   *
3400   * Return: None
3401   */
cnss_host_ramdump_dev_release(struct device * dev)3402  static void cnss_host_ramdump_dev_release(struct device *dev)
3403  {
3404  	cnss_pr_dbg("free host ramdump device\n");
3405  	kfree(dev);
3406  }
3407  
cnss_do_host_ramdump(struct cnss_plat_data * plat_priv,struct cnss_ssr_driver_dump_entry * ssr_entry,size_t num_entries_loaded)3408  int cnss_do_host_ramdump(struct cnss_plat_data *plat_priv,
3409  			 struct cnss_ssr_driver_dump_entry *ssr_entry,
3410  			 size_t num_entries_loaded)
3411  {
3412  	struct qcom_dump_segment *seg;
3413  	struct cnss_host_dump_meta_info meta_info = {0};
3414  	struct list_head head;
3415  	int dev_ret = 0;
3416  	struct device *new_device;
3417  	static const char * const wlan_str[] = {
3418  		[CNSS_HOST_WLAN_LOGS] = "wlan_logs",
3419  		[CNSS_HOST_HTC_CREDIT] = "htc_credit",
3420  		[CNSS_HOST_WMI_TX_CMP] = "wmi_tx_cmp",
3421  		[CNSS_HOST_WMI_COMMAND_LOG] = "wmi_command_log",
3422  		[CNSS_HOST_WMI_EVENT_LOG] = "wmi_event_log",
3423  		[CNSS_HOST_WMI_RX_EVENT] = "wmi_rx_event",
3424  		[CNSS_HOST_HAL_SOC] = "hal_soc",
3425  		[CNSS_HOST_GWLAN_LOGGING] = "gwlan_logging",
3426  		[CNSS_HOST_WMI_DEBUG_LOG_INFO] = "wmi_debug_log_info",
3427  		[CNSS_HOST_HTC_CREDIT_IDX] = "htc_credit_history_idx",
3428  		[CNSS_HOST_HTC_CREDIT_LEN] = "htc_credit_history_length",
3429  		[CNSS_HOST_WMI_TX_CMP_IDX] = "wmi_tx_cmp_idx",
3430  		[CNSS_HOST_WMI_COMMAND_LOG_IDX] = "wmi_command_log_idx",
3431  		[CNSS_HOST_WMI_EVENT_LOG_IDX] = "wmi_event_log_idx",
3432  		[CNSS_HOST_WMI_RX_EVENT_IDX] = "wmi_rx_event_idx",
3433  		[CNSS_HOST_HIF_CE_DESC_HISTORY_BUFF] = "hif_ce_desc_history_buff",
3434  		[CNSS_HOST_HANG_EVENT_DATA] = "hang_event_data",
3435  		[CNSS_HOST_CE_DESC_HIST] = "hif_ce_desc_hist",
3436  		[CNSS_HOST_CE_COUNT_MAX] = "hif_ce_count_max",
3437  		[CNSS_HOST_CE_HISTORY_MAX] = "hif_ce_history_max",
3438  		[CNSS_HOST_ONLY_FOR_CRIT_CE] = "hif_ce_only_for_crit",
3439  		[CNSS_HOST_HIF_EVENT_HISTORY] = "hif_event_history",
3440  		[CNSS_HOST_HIF_EVENT_HIST_MAX] = "hif_event_hist_max",
3441  		[CNSS_HOST_DP_WBM_DESC_REL] = "wbm_desc_rel_ring",
3442  		[CNSS_HOST_DP_WBM_DESC_REL_HANDLE] = "wbm_desc_rel_ring_handle",
3443  		[CNSS_HOST_DP_TCL_CMD] = "tcl_cmd_ring",
3444  		[CNSS_HOST_DP_TCL_CMD_HANDLE] = "tcl_cmd_ring_handle",
3445  		[CNSS_HOST_DP_TCL_STATUS] = "tcl_status_ring",
3446  		[CNSS_HOST_DP_TCL_STATUS_HANDLE] = "tcl_status_ring_handle",
3447  		[CNSS_HOST_DP_REO_REINJ] = "reo_reinject_ring",
3448  		[CNSS_HOST_DP_REO_REINJ_HANDLE] = "reo_reinject_ring_handle",
3449  		[CNSS_HOST_DP_RX_REL] = "rx_rel_ring",
3450  		[CNSS_HOST_DP_RX_REL_HANDLE] = "rx_rel_ring_handle",
3451  		[CNSS_HOST_DP_REO_EXP] = "reo_exception_ring",
3452  		[CNSS_HOST_DP_REO_EXP_HANDLE] = "reo_exception_ring_handle",
3453  		[CNSS_HOST_DP_REO_CMD] = "reo_cmd_ring",
3454  		[CNSS_HOST_DP_REO_CMD_HANDLE] = "reo_cmd_ring_handle",
3455  		[CNSS_HOST_DP_REO_STATUS] = "reo_status_ring",
3456  		[CNSS_HOST_DP_REO_STATUS_HANDLE] = "reo_status_ring_handle",
3457  		[CNSS_HOST_DP_TCL_DATA_0] = "tcl_data_ring_0",
3458  		[CNSS_HOST_DP_TCL_DATA_0_HANDLE] = "tcl_data_ring_0_handle",
3459  		[CNSS_HOST_DP_TX_COMP_0] = "tx_comp_ring_0",
3460  		[CNSS_HOST_DP_TX_COMP_0_HANDLE] = "tx_comp_ring_0_handle",
3461  		[CNSS_HOST_DP_TCL_DATA_1] = "tcl_data_ring_1",
3462  		[CNSS_HOST_DP_TCL_DATA_1_HANDLE] = "tcl_data_ring_1_handle",
3463  		[CNSS_HOST_DP_TX_COMP_1] = "tx_comp_ring_1",
3464  		[CNSS_HOST_DP_TX_COMP_1_HANDLE] = "tx_comp_ring_1_handle",
3465  		[CNSS_HOST_DP_TCL_DATA_2] = "tcl_data_ring_2",
3466  		[CNSS_HOST_DP_TCL_DATA_2_HANDLE] = "tcl_data_ring_2_handle",
3467  		[CNSS_HOST_DP_TX_COMP_2] = "tx_comp_ring_2",
3468  		[CNSS_HOST_DP_TX_COMP_2_HANDLE] = "tx_comp_ring_2_handle",
3469  		[CNSS_HOST_DP_REO_DST_0] = "reo_dest_ring_0",
3470  		[CNSS_HOST_DP_REO_DST_0_HANDLE] = "reo_dest_ring_0_handle",
3471  		[CNSS_HOST_DP_REO_DST_1] = "reo_dest_ring_1",
3472  		[CNSS_HOST_DP_REO_DST_1_HANDLE] = "reo_dest_ring_1_handle",
3473  		[CNSS_HOST_DP_REO_DST_2] = "reo_dest_ring_2",
3474  		[CNSS_HOST_DP_REO_DST_2_HANDLE] = "reo_dest_ring_2_handle",
3475  		[CNSS_HOST_DP_REO_DST_3] = "reo_dest_ring_3",
3476  		[CNSS_HOST_DP_REO_DST_3_HANDLE] = "reo_dest_ring_3_handle",
3477  		[CNSS_HOST_DP_REO_DST_4] = "reo_dest_ring_4",
3478  		[CNSS_HOST_DP_REO_DST_4_HANDLE] = "reo_dest_ring_4_handle",
3479  		[CNSS_HOST_DP_REO_DST_5] = "reo_dest_ring_5",
3480  		[CNSS_HOST_DP_REO_DST_5_HANDLE] = "reo_dest_ring_5_handle",
3481  		[CNSS_HOST_DP_REO_DST_6] = "reo_dest_ring_6",
3482  		[CNSS_HOST_DP_REO_DST_6_HANDLE] = "reo_dest_ring_6_handle",
3483  		[CNSS_HOST_DP_REO_DST_7] = "reo_dest_ring_7",
3484  		[CNSS_HOST_DP_REO_DST_7_HANDLE] = "reo_dest_ring_7_handle",
3485  		[CNSS_HOST_DP_PDEV_0] = "dp_pdev_0",
3486  		[CNSS_HOST_DP_WLAN_CFG_CTX] = "wlan_cfg_ctx",
3487  		[CNSS_HOST_DP_SOC] = "dp_soc",
3488  		[CNSS_HOST_HAL_RX_FST] = "hal_rx_fst",
3489  		[CNSS_HOST_DP_FISA] = "dp_fisa",
3490  		[CNSS_HOST_DP_FISA_HW_FSE_TABLE] = "dp_fisa_hw_fse_table",
3491  		[CNSS_HOST_DP_FISA_SW_FSE_TABLE] = "dp_fisa_sw_fse_table",
3492  		[CNSS_HOST_HIF] = "hif",
3493  		[CNSS_HOST_QDF_NBUF_HIST] = "qdf_nbuf_history",
3494  		[CNSS_HOST_TCL_WBM_MAP] = "tcl_wbm_map_array",
3495  		[CNSS_HOST_RX_MAC_BUF_RING_0] = "rx_mac_buf_ring_0",
3496  		[CNSS_HOST_RX_MAC_BUF_RING_0_HANDLE] = "rx_mac_buf_ring_0_handle",
3497  		[CNSS_HOST_RX_MAC_BUF_RING_1] = "rx_mac_buf_ring_1",
3498  		[CNSS_HOST_RX_MAC_BUF_RING_1_HANDLE] = "rx_mac_buf_ring_1_handle",
3499  		[CNSS_HOST_RX_REFILL_0] = "rx_refill_buf_ring_0",
3500  		[CNSS_HOST_RX_REFILL_0_HANDLE] = "rx_refill_buf_ring_0_handle",
3501  		[CNSS_HOST_CE_0] = "ce_0",
3502  		[CNSS_HOST_CE_0_SRC_RING] = "ce_0_src_ring",
3503  		[CNSS_HOST_CE_0_SRC_RING_CTX] = "ce_0_src_ring_ctx",
3504  		[CNSS_HOST_CE_1] = "ce_1",
3505  		[CNSS_HOST_CE_1_STATUS_RING] = "ce_1_status_ring",
3506  		[CNSS_HOST_CE_1_STATUS_RING_CTX] = "ce_1_status_ring_ctx",
3507  		[CNSS_HOST_CE_1_DEST_RING] = "ce_1_dest_ring",
3508  		[CNSS_HOST_CE_1_DEST_RING_CTX] = "ce_1_dest_ring_ctx",
3509  		[CNSS_HOST_CE_2] = "ce_2",
3510  		[CNSS_HOST_CE_2_STATUS_RING] = "ce_2_status_ring",
3511  		[CNSS_HOST_CE_2_STATUS_RING_CTX] = "ce_2_status_ring_ctx",
3512  		[CNSS_HOST_CE_2_DEST_RING] = "ce_2_dest_ring",
3513  		[CNSS_HOST_CE_2_DEST_RING_CTX] = "ce_2_dest_ring_ctx",
3514  		[CNSS_HOST_CE_3] = "ce_3",
3515  		[CNSS_HOST_CE_3_SRC_RING] = "ce_3_src_ring",
3516  		[CNSS_HOST_CE_3_SRC_RING_CTX] = "ce_3_src_ring_ctx",
3517  		[CNSS_HOST_CE_4] = "ce_4",
3518  		[CNSS_HOST_CE_4_SRC_RING] = "ce_4_src_ring",
3519  		[CNSS_HOST_CE_4_SRC_RING_CTX] = "ce_4_src_ring_ctx",
3520  		[CNSS_HOST_CE_5] = "ce_5",
3521  		[CNSS_HOST_CE_6] = "ce_6",
3522  		[CNSS_HOST_CE_7] = "ce_7",
3523  		[CNSS_HOST_CE_7_STATUS_RING] = "ce_7_status_ring",
3524  		[CNSS_HOST_CE_7_STATUS_RING_CTX] = "ce_7_status_ring_ctx",
3525  		[CNSS_HOST_CE_7_DEST_RING] = "ce_7_dest_ring",
3526  		[CNSS_HOST_CE_7_DEST_RING_CTX] = "ce_7_dest_ring_ctx",
3527  		[CNSS_HOST_CE_8] = "ce_8",
3528  		[CNSS_HOST_DP_TCL_DATA_3] = "tcl_data_ring_3",
3529  		[CNSS_HOST_DP_TCL_DATA_3_HANDLE] = "tcl_data_ring_3_handle",
3530  		[CNSS_HOST_DP_TX_COMP_3] = "tx_comp_ring_3",
3531  		[CNSS_HOST_DP_TX_COMP_3_HANDLE] = "tx_comp_ring_3_handle"
3532  	};
3533  	int i;
3534  	int ret = 0;
3535  	enum cnss_host_dump_type j;
3536  
3537  	if (!dump_enabled()) {
3538  		cnss_pr_info("Dump collection is not enabled\n");
3539  		return ret;
3540  	}
3541  
3542  	new_device = kcalloc(1, sizeof(*new_device), GFP_KERNEL);
3543  	if (!new_device) {
3544  		cnss_pr_err("Failed to alloc device mem\n");
3545  		return -ENOMEM;
3546  	}
3547  
3548  	new_device->release = cnss_host_ramdump_dev_release;
3549  	device_initialize(new_device);
3550  	dev_set_name(new_device, "wlan_driver");
3551  	dev_ret = device_add(new_device);
3552  	if (dev_ret) {
3553  		cnss_pr_err("Failed to add new device\n");
3554  		goto put_device;
3555  	}
3556  
3557  	INIT_LIST_HEAD(&head);
3558  	for (i = 0; i < num_entries_loaded; i++) {
3559  		/* If region name registered by driver is not present in
3560  		 * wlan_str. type for that entry will not be set, but entry will
3561  		 * be added. Which will result in entry type being 0. Currently
3562  		 * entry type 0 is for wlan_logs, which will result in parsing
3563  		 * issue for wlan_logs as parsing is done based upon type field.
3564  		 * So initialize type with -1(Invalid) to avoid such issues.
3565  		 */
3566  		meta_info.entry[i].type = -1;
3567  		seg = kcalloc(1, sizeof(*seg), GFP_KERNEL);
3568  		if (!seg) {
3569  			cnss_pr_err("Failed to alloc seg entry %d\n", i);
3570  			continue;
3571  		}
3572  
3573  		seg->va = ssr_entry[i].buffer_pointer;
3574  		seg->da = (dma_addr_t)ssr_entry[i].buffer_pointer;
3575  		seg->size = ssr_entry[i].buffer_size;
3576  
3577  		for (j = 0; j < CNSS_HOST_DUMP_TYPE_MAX; j++) {
3578  			if (strcmp(ssr_entry[i].region_name, wlan_str[j]) == 0) {
3579  				meta_info.entry[i].type = j;
3580  			}
3581  		}
3582  		meta_info.entry[i].entry_start = i + 1;
3583  		meta_info.entry[i].entry_num++;
3584  
3585  		list_add_tail(&seg->node, &head);
3586  	}
3587  
3588  	seg = kcalloc(1, sizeof(*seg), GFP_KERNEL);
3589  
3590  	if (!seg) {
3591  		cnss_pr_err("%s: Failed to allocate mem for host dump seg\n",
3592  			    __func__);
3593  		goto skip_host_dump;
3594  	}
3595  
3596  	meta_info.magic = CNSS_RAMDUMP_MAGIC;
3597  	meta_info.version = CNSS_RAMDUMP_VERSION;
3598  	meta_info.chipset = plat_priv->device_id;
3599  	meta_info.total_entries = num_entries_loaded;
3600  	seg->va = &meta_info;
3601  	seg->da = (dma_addr_t)&meta_info;
3602  	seg->size = sizeof(meta_info);
3603  	list_add(&seg->node, &head);
3604  
3605  	ret = qcom_elf_dump(&head, new_device, ELF_CLASS);
3606  
3607  skip_host_dump:
3608  	while (!list_empty(&head)) {
3609  		seg = list_first_entry(&head, struct qcom_dump_segment, node);
3610  		list_del(&seg->node);
3611  		kfree(seg);
3612  	}
3613  	device_del(new_device);
3614  put_device:
3615  	put_device(new_device);
3616  	cnss_pr_dbg("host ramdump result %d\n", ret);
3617  	return ret;
3618  }
3619  #endif
3620  #endif /* CONFIG_MSM_SUBSYSTEM_RESTART */
3621  
3622  #if IS_ENABLED(CONFIG_QCOM_MEMORY_DUMP_V2)
cnss_init_dump_entry(struct cnss_plat_data * plat_priv)3623  static int cnss_init_dump_entry(struct cnss_plat_data *plat_priv)
3624  {
3625  	struct cnss_ramdump_info *ramdump_info;
3626  	struct msm_dump_entry dump_entry;
3627  
3628  	ramdump_info = &plat_priv->ramdump_info;
3629  	ramdump_info->dump_data.addr = ramdump_info->ramdump_pa;
3630  	ramdump_info->dump_data.len = ramdump_info->ramdump_size;
3631  	ramdump_info->dump_data.version = CNSS_DUMP_FORMAT_VER;
3632  	ramdump_info->dump_data.magic = CNSS_DUMP_MAGIC_VER_V2;
3633  	strlcpy(ramdump_info->dump_data.name, CNSS_DUMP_NAME,
3634  		sizeof(ramdump_info->dump_data.name));
3635  	dump_entry.id = MSM_DUMP_DATA_CNSS_WLAN;
3636  	dump_entry.addr = virt_to_phys(&ramdump_info->dump_data);
3637  
3638  	return msm_dump_data_register_nominidump(MSM_DUMP_TABLE_APPS,
3639  						&dump_entry);
3640  }
3641  
cnss_register_ramdump_v1(struct cnss_plat_data * plat_priv)3642  static int cnss_register_ramdump_v1(struct cnss_plat_data *plat_priv)
3643  {
3644  	int ret = 0;
3645  	struct device *dev;
3646  	struct cnss_ramdump_info *ramdump_info;
3647  	u32 ramdump_size = 0;
3648  
3649  	dev = &plat_priv->plat_dev->dev;
3650  	ramdump_info = &plat_priv->ramdump_info;
3651  
3652  	if (plat_priv->dt_type != CNSS_DTT_MULTIEXCHG) {
3653  		/* dt type: legacy or converged */
3654  		ret = of_property_read_u32(dev->of_node,
3655  					   "qcom,wlan-ramdump-dynamic",
3656  					   &ramdump_size);
3657  	} else {
3658  		ret = of_property_read_u32(plat_priv->dev_node,
3659  					   "qcom,wlan-ramdump-dynamic",
3660  					   &ramdump_size);
3661  	}
3662  	if (ret == 0) {
3663  		ramdump_info->ramdump_va =
3664  			dma_alloc_coherent(dev, ramdump_size,
3665  					   &ramdump_info->ramdump_pa,
3666  					   GFP_KERNEL);
3667  
3668  		if (ramdump_info->ramdump_va)
3669  			ramdump_info->ramdump_size = ramdump_size;
3670  	}
3671  
3672  	cnss_pr_dbg("ramdump va: %pK, pa: %pa\n",
3673  		    ramdump_info->ramdump_va, &ramdump_info->ramdump_pa);
3674  
3675  	if (ramdump_info->ramdump_size == 0) {
3676  		cnss_pr_info("Ramdump will not be collected");
3677  		goto out;
3678  	}
3679  
3680  	ret = cnss_init_dump_entry(plat_priv);
3681  	if (ret) {
3682  		cnss_pr_err("Failed to setup dump table, err = %d\n", ret);
3683  		goto free_ramdump;
3684  	}
3685  
3686  	ramdump_info->ramdump_dev = cnss_create_ramdump_device(plat_priv);
3687  	if (!ramdump_info->ramdump_dev) {
3688  		cnss_pr_err("Failed to create ramdump device!");
3689  		ret = -ENOMEM;
3690  		goto free_ramdump;
3691  	}
3692  
3693  	return 0;
3694  free_ramdump:
3695  	dma_free_coherent(dev, ramdump_info->ramdump_size,
3696  			  ramdump_info->ramdump_va, ramdump_info->ramdump_pa);
3697  out:
3698  	return ret;
3699  }
3700  
cnss_unregister_ramdump_v1(struct cnss_plat_data * plat_priv)3701  static void cnss_unregister_ramdump_v1(struct cnss_plat_data *plat_priv)
3702  {
3703  	struct device *dev;
3704  	struct cnss_ramdump_info *ramdump_info;
3705  
3706  	dev = &plat_priv->plat_dev->dev;
3707  	ramdump_info = &plat_priv->ramdump_info;
3708  
3709  	if (ramdump_info->ramdump_dev)
3710  		cnss_destroy_ramdump_device(plat_priv,
3711  					    ramdump_info->ramdump_dev);
3712  
3713  	if (ramdump_info->ramdump_va)
3714  		dma_free_coherent(dev, ramdump_info->ramdump_size,
3715  				  ramdump_info->ramdump_va,
3716  				  ramdump_info->ramdump_pa);
3717  }
3718  
3719  /**
3720   * cnss_ignore_dump_data_reg_fail - Ignore Ramdump table register failure
3721   * @ret: Error returned by msm_dump_data_register_nominidump
3722   *
3723   * For Lahaina GKI boot, we dont have support for mem dump feature. So
3724   * ignore failure.
3725   *
3726   * Return: Same given error code if mem dump feature enabled, 0 otherwise
3727   */
cnss_ignore_dump_data_reg_fail(int ret)3728  static int cnss_ignore_dump_data_reg_fail(int ret)
3729  {
3730  	return ret;
3731  }
3732  
cnss_register_ramdump_v2(struct cnss_plat_data * plat_priv)3733  static int cnss_register_ramdump_v2(struct cnss_plat_data *plat_priv)
3734  {
3735  	int ret = 0;
3736  	struct cnss_ramdump_info_v2 *info_v2;
3737  	struct cnss_dump_data *dump_data;
3738  	struct msm_dump_entry dump_entry;
3739  	struct device *dev = &plat_priv->plat_dev->dev;
3740  	u32 ramdump_size = 0;
3741  
3742  	info_v2 = &plat_priv->ramdump_info_v2;
3743  	dump_data = &info_v2->dump_data;
3744  
3745  	if (plat_priv->dt_type != CNSS_DTT_MULTIEXCHG) {
3746  		/* dt type: legacy or converged */
3747  		ret = of_property_read_u32(dev->of_node,
3748  					   "qcom,wlan-ramdump-dynamic",
3749  					   &ramdump_size);
3750  	} else {
3751  		ret = of_property_read_u32(plat_priv->dev_node,
3752  					   "qcom,wlan-ramdump-dynamic",
3753  					   &ramdump_size);
3754  	}
3755  	if (ret == 0)
3756  		info_v2->ramdump_size = ramdump_size;
3757  
3758  	cnss_pr_dbg("Ramdump size 0x%lx\n", info_v2->ramdump_size);
3759  
3760  	info_v2->dump_data_vaddr = kzalloc(CNSS_DUMP_DESC_SIZE, GFP_KERNEL);
3761  	if (!info_v2->dump_data_vaddr)
3762  		return -ENOMEM;
3763  
3764  	dump_data->paddr = virt_to_phys(info_v2->dump_data_vaddr);
3765  	dump_data->version = CNSS_DUMP_FORMAT_VER_V2;
3766  	dump_data->magic = CNSS_DUMP_MAGIC_VER_V2;
3767  	dump_data->seg_version = CNSS_DUMP_SEG_VER;
3768  	strlcpy(dump_data->name, CNSS_DUMP_NAME,
3769  		sizeof(dump_data->name));
3770  	dump_entry.id = MSM_DUMP_DATA_CNSS_WLAN;
3771  	dump_entry.addr = virt_to_phys(dump_data);
3772  
3773  	ret = msm_dump_data_register_nominidump(MSM_DUMP_TABLE_APPS,
3774  						&dump_entry);
3775  	if (ret) {
3776  		ret = cnss_ignore_dump_data_reg_fail(ret);
3777  		cnss_pr_err("Failed to setup dump table, %s (%d)\n",
3778  			    ret ? "Error" : "Ignoring", ret);
3779  		goto free_ramdump;
3780  	}
3781  
3782  	info_v2->ramdump_dev = cnss_create_ramdump_device(plat_priv);
3783  	if (!info_v2->ramdump_dev) {
3784  		cnss_pr_err("Failed to create ramdump device!\n");
3785  		ret = -ENOMEM;
3786  		goto free_ramdump;
3787  	}
3788  
3789  	return 0;
3790  
3791  free_ramdump:
3792  	kfree(info_v2->dump_data_vaddr);
3793  	info_v2->dump_data_vaddr = NULL;
3794  	return ret;
3795  }
3796  
cnss_unregister_ramdump_v2(struct cnss_plat_data * plat_priv)3797  static void cnss_unregister_ramdump_v2(struct cnss_plat_data *plat_priv)
3798  {
3799  	struct cnss_ramdump_info_v2 *info_v2;
3800  
3801  	info_v2 = &plat_priv->ramdump_info_v2;
3802  
3803  	if (info_v2->ramdump_dev)
3804  		cnss_destroy_ramdump_device(plat_priv, info_v2->ramdump_dev);
3805  
3806  	kfree(info_v2->dump_data_vaddr);
3807  	info_v2->dump_data_vaddr = NULL;
3808  	info_v2->dump_data_valid = false;
3809  }
3810  
cnss_register_ramdump(struct cnss_plat_data * plat_priv)3811  int cnss_register_ramdump(struct cnss_plat_data *plat_priv)
3812  {
3813  	int ret = 0;
3814  
3815  	switch (plat_priv->device_id) {
3816  	case QCA6174_DEVICE_ID:
3817  		ret = cnss_register_ramdump_v1(plat_priv);
3818  		break;
3819  	case QCA6290_DEVICE_ID:
3820  	case QCA6390_DEVICE_ID:
3821  	case QCN7605_DEVICE_ID:
3822  	case QCA6490_DEVICE_ID:
3823  	case KIWI_DEVICE_ID:
3824  	case MANGO_DEVICE_ID:
3825  	case PEACH_DEVICE_ID:
3826  		ret = cnss_register_ramdump_v2(plat_priv);
3827  		break;
3828  	default:
3829  		cnss_pr_err("Unknown device ID: 0x%lx\n", plat_priv->device_id);
3830  		ret = -ENODEV;
3831  		break;
3832  	}
3833  	return ret;
3834  }
3835  
cnss_unregister_ramdump(struct cnss_plat_data * plat_priv)3836  void cnss_unregister_ramdump(struct cnss_plat_data *plat_priv)
3837  {
3838  	switch (plat_priv->device_id) {
3839  	case QCA6174_DEVICE_ID:
3840  		cnss_unregister_ramdump_v1(plat_priv);
3841  		break;
3842  	case QCA6290_DEVICE_ID:
3843  	case QCA6390_DEVICE_ID:
3844  	case QCN7605_DEVICE_ID:
3845  	case QCA6490_DEVICE_ID:
3846  	case KIWI_DEVICE_ID:
3847  	case MANGO_DEVICE_ID:
3848  	case PEACH_DEVICE_ID:
3849  		cnss_unregister_ramdump_v2(plat_priv);
3850  		break;
3851  	default:
3852  		cnss_pr_err("Unknown device ID: 0x%lx\n", plat_priv->device_id);
3853  		break;
3854  	}
3855  }
3856  #else
cnss_register_ramdump(struct cnss_plat_data * plat_priv)3857  int cnss_register_ramdump(struct cnss_plat_data *plat_priv)
3858  {
3859  	struct cnss_ramdump_info_v2 *info_v2 = &plat_priv->ramdump_info_v2;
3860  	struct cnss_dump_data *dump_data = dump_data = &info_v2->dump_data;
3861  	struct device *dev = &plat_priv->plat_dev->dev;
3862  	u32 ramdump_size = 0;
3863  
3864  	if (of_property_read_u32(dev->of_node, "qcom,wlan-ramdump-dynamic",
3865  				 &ramdump_size) == 0)
3866  		info_v2->ramdump_size = ramdump_size;
3867  
3868  	cnss_pr_dbg("Ramdump size 0x%lx\n", info_v2->ramdump_size);
3869  
3870  	info_v2->dump_data_vaddr = kzalloc(CNSS_DUMP_DESC_SIZE, GFP_KERNEL);
3871  	if (!info_v2->dump_data_vaddr)
3872  		return -ENOMEM;
3873  
3874  	dump_data->paddr = virt_to_phys(info_v2->dump_data_vaddr);
3875  	dump_data->version = CNSS_DUMP_FORMAT_VER_V2;
3876  	dump_data->magic = CNSS_DUMP_MAGIC_VER_V2;
3877  	dump_data->seg_version = CNSS_DUMP_SEG_VER;
3878  	strlcpy(dump_data->name, CNSS_DUMP_NAME,
3879  		sizeof(dump_data->name));
3880  
3881  	info_v2->ramdump_dev = dev;
3882  
3883  	return 0;
3884  }
3885  
cnss_unregister_ramdump(struct cnss_plat_data * plat_priv)3886  void cnss_unregister_ramdump(struct cnss_plat_data *plat_priv)
3887  {
3888  	struct cnss_ramdump_info_v2 *info_v2 = &plat_priv->ramdump_info_v2;
3889  
3890  	info_v2->ramdump_dev = NULL;
3891  	kfree(info_v2->dump_data_vaddr);
3892  	info_v2->dump_data_vaddr = NULL;
3893  	info_v2->dump_data_valid = false;
3894  }
3895  #endif /* CONFIG_QCOM_MEMORY_DUMP_V2 */
3896  
cnss_va_to_pa(struct device * dev,size_t size,void * va,dma_addr_t dma,phys_addr_t * pa,unsigned long attrs)3897  int cnss_va_to_pa(struct device *dev, size_t size, void *va, dma_addr_t dma,
3898  		  phys_addr_t *pa, unsigned long attrs)
3899  {
3900  	struct sg_table sgt;
3901  	int ret;
3902  
3903  	ret = dma_get_sgtable_attrs(dev, &sgt, va, dma, size, attrs);
3904  	if (ret) {
3905  		cnss_pr_err("Failed to get sgtable for va: 0x%pK, dma: %pa, size: 0x%zx, attrs: 0x%x\n",
3906  			    va, &dma, size, attrs);
3907  		return -EINVAL;
3908  	}
3909  
3910  	*pa = page_to_phys(sg_page(sgt.sgl));
3911  	sg_free_table(&sgt);
3912  
3913  	return 0;
3914  }
3915  
3916  #if IS_ENABLED(CONFIG_QCOM_MINIDUMP)
cnss_minidump_add_region(struct cnss_plat_data * plat_priv,enum cnss_fw_dump_type type,int seg_no,void * va,phys_addr_t pa,size_t size)3917  int cnss_minidump_add_region(struct cnss_plat_data *plat_priv,
3918  			     enum cnss_fw_dump_type type, int seg_no,
3919  			     void *va, phys_addr_t pa, size_t size)
3920  {
3921  	struct md_region md_entry;
3922  	int ret;
3923  
3924  	switch (type) {
3925  	case CNSS_FW_IMAGE:
3926  		snprintf(md_entry.name, sizeof(md_entry.name), "FBC_%X",
3927  			 seg_no);
3928  		break;
3929  	case CNSS_FW_RDDM:
3930  		snprintf(md_entry.name, sizeof(md_entry.name), "RDDM_%X",
3931  			 seg_no);
3932  		break;
3933  	case CNSS_FW_REMOTE_HEAP:
3934  		snprintf(md_entry.name, sizeof(md_entry.name), "RHEAP_%X",
3935  			 seg_no);
3936  		break;
3937  	default:
3938  		cnss_pr_err("Unknown dump type ID: %d\n", type);
3939  		return -EINVAL;
3940  	}
3941  
3942  	md_entry.phys_addr = pa;
3943  	md_entry.virt_addr = (uintptr_t)va;
3944  	md_entry.size = size;
3945  	md_entry.id = MSM_DUMP_DATA_CNSS_WLAN;
3946  
3947  	cnss_pr_dbg("Mini dump region: %s, va: %pK, pa: %pa, size: 0x%zx\n",
3948  		    md_entry.name, va, &pa, size);
3949  
3950  	ret = msm_minidump_add_region(&md_entry);
3951  	if (ret < 0)
3952  		cnss_pr_err("Failed to add mini dump region, err = %d\n", ret);
3953  
3954  	return ret;
3955  }
3956  
cnss_minidump_remove_region(struct cnss_plat_data * plat_priv,enum cnss_fw_dump_type type,int seg_no,void * va,phys_addr_t pa,size_t size)3957  int cnss_minidump_remove_region(struct cnss_plat_data *plat_priv,
3958  				enum cnss_fw_dump_type type, int seg_no,
3959  				void *va, phys_addr_t pa, size_t size)
3960  {
3961  	struct md_region md_entry;
3962  	int ret;
3963  
3964  	switch (type) {
3965  	case CNSS_FW_IMAGE:
3966  		snprintf(md_entry.name, sizeof(md_entry.name), "FBC_%X",
3967  			 seg_no);
3968  		break;
3969  	case CNSS_FW_RDDM:
3970  		snprintf(md_entry.name, sizeof(md_entry.name), "RDDM_%X",
3971  			 seg_no);
3972  		break;
3973  	case CNSS_FW_REMOTE_HEAP:
3974  		snprintf(md_entry.name, sizeof(md_entry.name), "RHEAP_%X",
3975  			 seg_no);
3976  		break;
3977  	default:
3978  		cnss_pr_err("Unknown dump type ID: %d\n", type);
3979  		return -EINVAL;
3980  	}
3981  
3982  	md_entry.phys_addr = pa;
3983  	md_entry.virt_addr = (uintptr_t)va;
3984  	md_entry.size = size;
3985  	md_entry.id = MSM_DUMP_DATA_CNSS_WLAN;
3986  
3987  	cnss_pr_vdbg("Remove mini dump region: %s, va: %pK, pa: %pa, size: 0x%zx\n",
3988  		     md_entry.name, va, &pa, size);
3989  
3990  	ret = msm_minidump_remove_region(&md_entry);
3991  	if (ret)
3992  		cnss_pr_err("Failed to remove mini dump region, err = %d\n",
3993  			    ret);
3994  
3995  	return ret;
3996  }
3997  #else
cnss_minidump_add_region(struct cnss_plat_data * plat_priv,enum cnss_fw_dump_type type,int seg_no,void * va,phys_addr_t pa,size_t size)3998  int cnss_minidump_add_region(struct cnss_plat_data *plat_priv,
3999  			     enum cnss_fw_dump_type type, int seg_no,
4000  			     void *va, phys_addr_t pa, size_t size)
4001  {
4002  	char name[MAX_NAME_LEN];
4003  
4004  	switch (type) {
4005  	case CNSS_FW_IMAGE:
4006  		snprintf(name, MAX_NAME_LEN, "FBC_%X", seg_no);
4007  		break;
4008  	case CNSS_FW_RDDM:
4009  		snprintf(name, MAX_NAME_LEN, "RDDM_%X", seg_no);
4010  		break;
4011  	case CNSS_FW_REMOTE_HEAP:
4012  		snprintf(name, MAX_NAME_LEN, "RHEAP_%X", seg_no);
4013  		break;
4014  	default:
4015  		cnss_pr_err("Unknown dump type ID: %d\n", type);
4016  		return -EINVAL;
4017  	}
4018  
4019  	cnss_pr_dbg("Dump region: %s, va: %pK, pa: %pa, size: 0x%zx\n",
4020  		    name, va, &pa, size);
4021  	return 0;
4022  }
4023  
cnss_minidump_remove_region(struct cnss_plat_data * plat_priv,enum cnss_fw_dump_type type,int seg_no,void * va,phys_addr_t pa,size_t size)4024  int cnss_minidump_remove_region(struct cnss_plat_data *plat_priv,
4025  				enum cnss_fw_dump_type type, int seg_no,
4026  				void *va, phys_addr_t pa, size_t size)
4027  {
4028  	return 0;
4029  }
4030  #endif /* CONFIG_QCOM_MINIDUMP */
4031  
cnss_request_firmware_direct(struct cnss_plat_data * plat_priv,const struct firmware ** fw_entry,const char * filename)4032  int cnss_request_firmware_direct(struct cnss_plat_data *plat_priv,
4033  				 const struct firmware **fw_entry,
4034  				 const char *filename)
4035  {
4036  	if (IS_ENABLED(CONFIG_CNSS_REQ_FW_DIRECT))
4037  		return request_firmware_direct(fw_entry, filename,
4038  					       &plat_priv->plat_dev->dev);
4039  	else
4040  		return firmware_request_nowarn(fw_entry, filename,
4041  					       &plat_priv->plat_dev->dev);
4042  }
4043  
4044  #if IS_ENABLED(CONFIG_INTERCONNECT)
4045  /**
4046   * cnss_register_bus_scale() - Setup interconnect voting data
4047   * @plat_priv: Platform data structure
4048   *
4049   * For different interconnect path configured in device tree setup voting data
4050   * for list of bandwidth requirements.
4051   *
4052   * Result: 0 for success. -EINVAL if not configured
4053   */
cnss_register_bus_scale(struct cnss_plat_data * plat_priv)4054  static int cnss_register_bus_scale(struct cnss_plat_data *plat_priv)
4055  {
4056  	int ret = -EINVAL;
4057  	u32 idx, i, j, cfg_arr_size, *cfg_arr = NULL;
4058  	struct cnss_bus_bw_info *bus_bw_info, *tmp;
4059  	struct device *dev = &plat_priv->plat_dev->dev;
4060  
4061  	INIT_LIST_HEAD(&plat_priv->icc.list_head);
4062  	ret = of_property_read_u32(dev->of_node,
4063  				   "qcom,icc-path-count",
4064  				   &plat_priv->icc.path_count);
4065  	if (ret) {
4066  		cnss_pr_dbg("Platform Bus Interconnect path not configured\n");
4067  		return 0;
4068  	}
4069  	ret = of_property_read_u32(plat_priv->plat_dev->dev.of_node,
4070  				   "qcom,bus-bw-cfg-count",
4071  				   &plat_priv->icc.bus_bw_cfg_count);
4072  	if (ret) {
4073  		cnss_pr_err("Failed to get Bus BW Config table size\n");
4074  		goto cleanup;
4075  	}
4076  	cfg_arr_size = plat_priv->icc.path_count *
4077  			 plat_priv->icc.bus_bw_cfg_count * CNSS_ICC_VOTE_MAX;
4078  	cfg_arr = kcalloc(cfg_arr_size, sizeof(*cfg_arr), GFP_KERNEL);
4079  	if (!cfg_arr) {
4080  		cnss_pr_err("Failed to alloc cfg table mem\n");
4081  		ret = -ENOMEM;
4082  		goto cleanup;
4083  	}
4084  
4085  	ret = of_property_read_u32_array(plat_priv->plat_dev->dev.of_node,
4086  					 "qcom,bus-bw-cfg", cfg_arr,
4087  					 cfg_arr_size);
4088  	if (ret) {
4089  		cnss_pr_err("Invalid Bus BW Config Table\n");
4090  		goto cleanup;
4091  	}
4092  
4093  	cnss_pr_dbg("ICC Path_Count: %d BW_CFG_Count: %d\n",
4094  		    plat_priv->icc.path_count, plat_priv->icc.bus_bw_cfg_count);
4095  
4096  	for (idx = 0; idx < plat_priv->icc.path_count; idx++) {
4097  		bus_bw_info = devm_kzalloc(dev, sizeof(*bus_bw_info),
4098  					   GFP_KERNEL);
4099  		if (!bus_bw_info) {
4100  			ret = -ENOMEM;
4101  			goto out;
4102  		}
4103  		ret = of_property_read_string_index(dev->of_node,
4104  						    "interconnect-names", idx,
4105  						    &bus_bw_info->icc_name);
4106  		if (ret)
4107  			goto out;
4108  
4109  		bus_bw_info->icc_path =
4110  			of_icc_get(&plat_priv->plat_dev->dev,
4111  				   bus_bw_info->icc_name);
4112  
4113  		if (IS_ERR(bus_bw_info->icc_path))  {
4114  			ret = PTR_ERR(bus_bw_info->icc_path);
4115  			if (ret != -EPROBE_DEFER) {
4116  				cnss_pr_err("Failed to get Interconnect path for %s. Err: %d\n",
4117  					    bus_bw_info->icc_name, ret);
4118  				goto out;
4119  			}
4120  		}
4121  
4122  		bus_bw_info->cfg_table =
4123  			devm_kcalloc(dev, plat_priv->icc.bus_bw_cfg_count,
4124  				     sizeof(*bus_bw_info->cfg_table),
4125  				     GFP_KERNEL);
4126  		if (!bus_bw_info->cfg_table) {
4127  			ret = -ENOMEM;
4128  			goto out;
4129  		}
4130  		cnss_pr_dbg("ICC Vote CFG for path: %s\n",
4131  			    bus_bw_info->icc_name);
4132  		for (i = 0, j = (idx * plat_priv->icc.bus_bw_cfg_count *
4133  		     CNSS_ICC_VOTE_MAX);
4134  		     i < plat_priv->icc.bus_bw_cfg_count;
4135  		     i++, j += 2) {
4136  			bus_bw_info->cfg_table[i].avg_bw = cfg_arr[j];
4137  			bus_bw_info->cfg_table[i].peak_bw = cfg_arr[j + 1];
4138  			cnss_pr_dbg("ICC Vote BW: %d avg: %d peak: %d\n",
4139  				    i, bus_bw_info->cfg_table[i].avg_bw,
4140  				    bus_bw_info->cfg_table[i].peak_bw);
4141  		}
4142  		list_add_tail(&bus_bw_info->list,
4143  			      &plat_priv->icc.list_head);
4144  	}
4145  	kfree(cfg_arr);
4146  	return 0;
4147  out:
4148  	list_for_each_entry_safe(bus_bw_info, tmp,
4149  				 &plat_priv->icc.list_head, list) {
4150  		list_del(&bus_bw_info->list);
4151  	}
4152  cleanup:
4153  	kfree(cfg_arr);
4154  	memset(&plat_priv->icc, 0, sizeof(plat_priv->icc));
4155  	return ret;
4156  }
4157  
cnss_unregister_bus_scale(struct cnss_plat_data * plat_priv)4158  static void cnss_unregister_bus_scale(struct cnss_plat_data *plat_priv)
4159  {
4160  	struct cnss_bus_bw_info *bus_bw_info, *tmp;
4161  
4162  	list_for_each_entry_safe(bus_bw_info, tmp,
4163  				 &plat_priv->icc.list_head, list) {
4164  		list_del(&bus_bw_info->list);
4165  		if (bus_bw_info->icc_path)
4166  			icc_put(bus_bw_info->icc_path);
4167  	}
4168  	memset(&plat_priv->icc, 0, sizeof(plat_priv->icc));
4169  }
4170  #else
cnss_register_bus_scale(struct cnss_plat_data * plat_priv)4171  static int cnss_register_bus_scale(struct cnss_plat_data *plat_priv)
4172  {
4173  	return 0;
4174  }
4175  
cnss_unregister_bus_scale(struct cnss_plat_data * plat_priv)4176  static void cnss_unregister_bus_scale(struct cnss_plat_data *plat_priv) {}
4177  #endif /* CONFIG_INTERCONNECT */
4178  
cnss_daemon_connection_update_cb(void * cb_ctx,bool status)4179  void cnss_daemon_connection_update_cb(void *cb_ctx, bool status)
4180  {
4181  	struct cnss_plat_data *plat_priv = cb_ctx;
4182  
4183  	if (!plat_priv) {
4184  		cnss_pr_err("%s: Invalid context\n", __func__);
4185  		return;
4186  	}
4187  	if (status) {
4188  		cnss_pr_info("CNSS Daemon connected\n");
4189  		set_bit(CNSS_DAEMON_CONNECTED, &plat_priv->driver_state);
4190  		complete(&plat_priv->daemon_connected);
4191  	} else {
4192  		cnss_pr_info("CNSS Daemon disconnected\n");
4193  		reinit_completion(&plat_priv->daemon_connected);
4194  		clear_bit(CNSS_DAEMON_CONNECTED, &plat_priv->driver_state);
4195  	}
4196  }
4197  
enable_hds_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4198  static ssize_t enable_hds_store(struct device *dev,
4199  				struct device_attribute *attr,
4200  				const char *buf, size_t count)
4201  {
4202  	struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
4203  	unsigned int enable_hds = 0;
4204  
4205  	if (!plat_priv)
4206  		return -ENODEV;
4207  
4208  	if (sscanf(buf, "%du", &enable_hds) != 1) {
4209  		cnss_pr_err("Invalid enable_hds sysfs command\n");
4210  		return -EINVAL;
4211  	}
4212  
4213  	if (enable_hds)
4214  		plat_priv->hds_enabled = true;
4215  	else
4216  		plat_priv->hds_enabled = false;
4217  
4218  	cnss_pr_dbg("%s HDS file download, count is %zu\n",
4219  		    plat_priv->hds_enabled ? "Enable" : "Disable", count);
4220  
4221  	return count;
4222  }
4223  
recovery_show(struct device * dev,struct device_attribute * attr,char * buf)4224  static ssize_t recovery_show(struct device *dev,
4225  			     struct device_attribute *attr,
4226  			     char *buf)
4227  {
4228  	struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
4229  	u32 buf_size = PAGE_SIZE;
4230  	u32 curr_len = 0;
4231  	u32 buf_written = 0;
4232  
4233  	if (!plat_priv)
4234  		return -ENODEV;
4235  
4236  	buf_written = scnprintf(buf, buf_size,
4237  				"Usage: echo [recovery_bitmap] > /sys/kernel/cnss/recovery\n"
4238  				"BIT0 -- wlan fw recovery\n"
4239  				"BIT1 -- wlan pcss recovery\n"
4240  				"---------------------------------\n");
4241  	curr_len += buf_written;
4242  
4243  	buf_written = scnprintf(buf + curr_len, buf_size - curr_len,
4244  				"WLAN recovery %s[%d]\n",
4245  				plat_priv->recovery_enabled ? "Enabled" : "Disabled",
4246  				plat_priv->recovery_enabled);
4247  	curr_len += buf_written;
4248  
4249  	buf_written = scnprintf(buf + curr_len, buf_size - curr_len,
4250  				"WLAN PCSS recovery %s[%d]\n",
4251  				plat_priv->recovery_pcss_enabled ? "Enabled" : "Disabled",
4252  				plat_priv->recovery_pcss_enabled);
4253  	curr_len += buf_written;
4254  
4255  	/*
4256  	 * Now size of curr_len is not over page size for sure,
4257  	 * later if new item or none-fixed size item added, need
4258  	 * add check to make sure curr_len is not over page size.
4259  	 */
4260  	return curr_len;
4261  }
4262  
tme_opt_file_download_show(struct device * dev,struct device_attribute * attr,char * buf)4263  static ssize_t tme_opt_file_download_show(struct device *dev,
4264  			     struct device_attribute *attr, char *buf)
4265  {
4266  	u32 buf_size = PAGE_SIZE;
4267  	u32 curr_len = 0;
4268  	u32 buf_written = 0;
4269  
4270  	buf_written = scnprintf(buf, buf_size,
4271  				"Usage: echo [file_type] > /sys/kernel/cnss/tme_opt_file_download\n"
4272  				"file_type = sec -- For OEM_FUSE file\n"
4273  				"file_type = rpr -- For RPR file\n"
4274  				"file_type = dpr -- For DPR file\n");
4275  
4276  	curr_len += buf_written;
4277  	return curr_len;
4278  }
4279  
time_sync_period_show(struct device * dev,struct device_attribute * attr,char * buf)4280  static ssize_t time_sync_period_show(struct device *dev,
4281  				     struct device_attribute *attr,
4282  				     char *buf)
4283  {
4284  	struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
4285  
4286  	return scnprintf(buf, PAGE_SIZE, "%u ms\n",
4287  			plat_priv->ctrl_params.time_sync_period);
4288  }
4289  
4290  /**
4291   * cnss_get_min_time_sync_period_by_vote() - Get minimum time sync period
4292   * @plat_priv: Platform data structure
4293   *
4294   * Result: return minimum time sync period present in vote from wlan and sys
4295   */
cnss_get_min_time_sync_period_by_vote(struct cnss_plat_data * plat_priv)4296  uint32_t cnss_get_min_time_sync_period_by_vote(struct cnss_plat_data *plat_priv)
4297  {
4298  	unsigned int i, min_time_sync_period = CNSS_TIME_SYNC_PERIOD_INVALID;
4299  	unsigned int time_sync_period;
4300  
4301  	for (i = 0; i < TIME_SYNC_VOTE_MAX; i++) {
4302  		time_sync_period = plat_priv->ctrl_params.time_sync_period_vote[i];
4303  		if (min_time_sync_period > time_sync_period)
4304  			min_time_sync_period = time_sync_period;
4305  	}
4306  
4307  	return min_time_sync_period;
4308  }
4309  
time_sync_period_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4310  static ssize_t time_sync_period_store(struct device *dev,
4311  				      struct device_attribute *attr,
4312  				      const char *buf, size_t count)
4313  {
4314  	struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
4315  	unsigned int time_sync_period = 0;
4316  
4317  	if (!plat_priv)
4318  		return -ENODEV;
4319  
4320  	if (sscanf(buf, "%du", &time_sync_period) != 1) {
4321  		cnss_pr_err("Invalid time sync sysfs command\n");
4322  		return -EINVAL;
4323  	}
4324  
4325  	if (time_sync_period < CNSS_MIN_TIME_SYNC_PERIOD) {
4326  		cnss_pr_err("Invalid time sync value\n");
4327  		return -EINVAL;
4328  	}
4329  	plat_priv->ctrl_params.time_sync_period_vote[TIME_SYNC_VOTE_CNSS] =
4330  		time_sync_period;
4331  	time_sync_period = cnss_get_min_time_sync_period_by_vote(plat_priv);
4332  
4333  	if (time_sync_period == CNSS_TIME_SYNC_PERIOD_INVALID) {
4334  		cnss_pr_err("Invalid min time sync value\n");
4335  		return -EINVAL;
4336  	}
4337  
4338  	cnss_bus_update_time_sync_period(plat_priv, time_sync_period);
4339  
4340  	return count;
4341  }
4342  
4343  /**
4344   * cnss_update_time_sync_period() - Set time sync period given by driver
4345   * @dev: device structure
4346   * @time_sync_period: time sync period value
4347   *
4348   * Update time sync period vote of driver and set minimum of time sync period
4349   * from stored vote through wlan and sys config
4350   * Result: return 0 for success, error in case of invalid value and no dev
4351   */
cnss_update_time_sync_period(struct device * dev,uint32_t time_sync_period)4352  int cnss_update_time_sync_period(struct device *dev, uint32_t time_sync_period)
4353  {
4354  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
4355  
4356  	if (!plat_priv)
4357  		return -ENODEV;
4358  
4359  	if (time_sync_period < CNSS_MIN_TIME_SYNC_PERIOD) {
4360  		cnss_pr_err("Invalid time sync value\n");
4361  		return -EINVAL;
4362  	}
4363  
4364  	plat_priv->ctrl_params.time_sync_period_vote[TIME_SYNC_VOTE_WLAN] =
4365  		time_sync_period;
4366  	time_sync_period = cnss_get_min_time_sync_period_by_vote(plat_priv);
4367  
4368  	if (time_sync_period == CNSS_TIME_SYNC_PERIOD_INVALID) {
4369  		cnss_pr_err("Invalid min time sync value\n");
4370  		return -EINVAL;
4371  	}
4372  
4373  	cnss_bus_update_time_sync_period(plat_priv, time_sync_period);
4374  	return 0;
4375  }
4376  EXPORT_SYMBOL(cnss_update_time_sync_period);
4377  
4378  /**
4379   * cnss_reset_time_sync_period() - Reset time sync period
4380   * @dev: device structure
4381   *
4382   * Update time sync period vote of driver as invalid
4383   * and reset minimum of time sync period from
4384   * stored vote through wlan and sys config
4385   * Result: return 0 for success, error in case of no dev
4386   */
cnss_reset_time_sync_period(struct device * dev)4387  int cnss_reset_time_sync_period(struct device *dev)
4388  {
4389  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
4390  	unsigned int time_sync_period = 0;
4391  
4392  	if (!plat_priv)
4393  		return -ENODEV;
4394  
4395  	/* Driver vote is set to invalid in case of reset
4396  	 * In this case, only vote valid to check is sys config
4397  	 */
4398  	plat_priv->ctrl_params.time_sync_period_vote[TIME_SYNC_VOTE_WLAN] =
4399  		CNSS_TIME_SYNC_PERIOD_INVALID;
4400  	time_sync_period = cnss_get_min_time_sync_period_by_vote(plat_priv);
4401  
4402  	if (time_sync_period == CNSS_TIME_SYNC_PERIOD_INVALID) {
4403  		cnss_pr_err("Invalid min time sync value\n");
4404  		return -EINVAL;
4405  	}
4406  
4407  	cnss_bus_update_time_sync_period(plat_priv, time_sync_period);
4408  
4409  	return 0;
4410  }
4411  EXPORT_SYMBOL(cnss_reset_time_sync_period);
4412  
recovery_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4413  static ssize_t recovery_store(struct device *dev,
4414  			      struct device_attribute *attr,
4415  			      const char *buf, size_t count)
4416  {
4417  	struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
4418  	unsigned int recovery = 0;
4419  
4420  	if (!plat_priv)
4421  		return -ENODEV;
4422  
4423  	if (sscanf(buf, "%du", &recovery) != 1) {
4424  		cnss_pr_err("Invalid recovery sysfs command\n");
4425  		return -EINVAL;
4426  	}
4427  
4428  	plat_priv->recovery_enabled = !!(recovery & CNSS_WLAN_RECOVERY);
4429  	plat_priv->recovery_pcss_enabled = !!(recovery & CNSS_PCSS_RECOVERY);
4430  
4431  	cnss_pr_dbg("%s WLAN recovery, count is %zu\n",
4432  		    plat_priv->recovery_enabled ? "Enable" : "Disable", count);
4433  	cnss_pr_dbg("%s PCSS recovery, count is %zu\n",
4434  		    plat_priv->recovery_pcss_enabled ? "Enable" : "Disable", count);
4435  
4436  	cnss_send_subsys_restart_level_msg(plat_priv);
4437  	return count;
4438  }
4439  
shutdown_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4440  static ssize_t shutdown_store(struct device *dev,
4441  			      struct device_attribute *attr,
4442  			      const char *buf, size_t count)
4443  {
4444  	struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
4445  
4446  	cnss_pr_dbg("Received shutdown notification\n");
4447  	if (plat_priv) {
4448  		set_bit(CNSS_IN_REBOOT, &plat_priv->driver_state);
4449  		cnss_bus_update_status(plat_priv, CNSS_SYS_REBOOT);
4450  		del_timer(&plat_priv->fw_boot_timer);
4451  		complete_all(&plat_priv->power_up_complete);
4452  		complete_all(&plat_priv->cal_complete);
4453  		cnss_pr_dbg("Shutdown notification handled\n");
4454  	}
4455  
4456  	return count;
4457  }
4458  
fs_ready_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4459  static ssize_t fs_ready_store(struct device *dev,
4460  			      struct device_attribute *attr,
4461  			      const char *buf, size_t count)
4462  {
4463  	int fs_ready = 0;
4464  	struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
4465  
4466  	if (sscanf(buf, "%du", &fs_ready) != 1)
4467  		return -EINVAL;
4468  
4469  	cnss_pr_dbg("File system is ready, fs_ready is %d, count is %zu\n",
4470  		    fs_ready, count);
4471  
4472  	if (!plat_priv) {
4473  		cnss_pr_err("plat_priv is NULL\n");
4474  		return count;
4475  	}
4476  
4477  	if (test_bit(QMI_BYPASS, &plat_priv->ctrl_params.quirks)) {
4478  		cnss_pr_dbg("QMI is bypassed\n");
4479  		return count;
4480  	}
4481  
4482  	set_bit(CNSS_FS_READY, &plat_priv->driver_state);
4483  	if (fs_ready == FILE_SYSTEM_READY && plat_priv->cbc_enabled) {
4484  		cnss_driver_event_post(plat_priv,
4485  				       CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START,
4486  				       0, NULL);
4487  	}
4488  
4489  	return count;
4490  }
4491  
qdss_trace_start_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4492  static ssize_t qdss_trace_start_store(struct device *dev,
4493  				      struct device_attribute *attr,
4494  				      const char *buf, size_t count)
4495  {
4496  	struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
4497  
4498  	wlfw_qdss_trace_start(plat_priv);
4499  	cnss_pr_dbg("Received QDSS start command\n");
4500  	return count;
4501  }
4502  
qdss_trace_stop_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4503  static ssize_t qdss_trace_stop_store(struct device *dev,
4504  				     struct device_attribute *attr,
4505  				     const char *buf, size_t count)
4506  {
4507  	struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
4508  	u32 option = 0;
4509  
4510  	if (sscanf(buf, "%du", &option) != 1)
4511  		return -EINVAL;
4512  
4513  	wlfw_qdss_trace_stop(plat_priv, option);
4514  	cnss_pr_dbg("Received QDSS stop command\n");
4515  	return count;
4516  }
4517  
qdss_conf_download_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4518  static ssize_t qdss_conf_download_store(struct device *dev,
4519  					struct device_attribute *attr,
4520  					const char *buf, size_t count)
4521  {
4522  	struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
4523  
4524  	cnss_wlfw_qdss_dnld_send_sync(plat_priv);
4525  	cnss_pr_dbg("Received QDSS download config command\n");
4526  	return count;
4527  }
4528  
tme_opt_file_download_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4529  static ssize_t tme_opt_file_download_store(struct device *dev,
4530  					struct device_attribute *attr,
4531  					const char *buf, size_t count)
4532  {
4533  	struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
4534  	char cmd[5];
4535  
4536  	if (sscanf(buf, "%s", cmd) != 1)
4537  		return -EINVAL;
4538  
4539  	if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
4540  		cnss_pr_err("Firmware is not ready yet\n");
4541  		return 0;
4542  	}
4543  
4544  	if (plat_priv->device_id == PEACH_DEVICE_ID &&
4545  	    cnss_bus_runtime_pm_get_sync(plat_priv) < 0)
4546  		goto runtime_pm_put;
4547  
4548  	if (strcmp(cmd, "sec") == 0) {
4549  		cnss_bus_load_tme_opt_file(plat_priv, WLFW_TME_LITE_OEM_FUSE_FILE_V01);
4550  		cnss_wlfw_tme_opt_file_dnld_send_sync(plat_priv, WLFW_TME_LITE_OEM_FUSE_FILE_V01);
4551  	} else if (strcmp(cmd, "rpr") == 0) {
4552  		cnss_bus_load_tme_opt_file(plat_priv, WLFW_TME_LITE_RPR_FILE_V01);
4553  		cnss_wlfw_tme_opt_file_dnld_send_sync(plat_priv, WLFW_TME_LITE_RPR_FILE_V01);
4554  	} else if (strcmp(cmd, "dpr") == 0) {
4555  		cnss_bus_load_tme_opt_file(plat_priv, WLFW_TME_LITE_DPR_FILE_V01);
4556  		cnss_wlfw_tme_opt_file_dnld_send_sync(plat_priv, WLFW_TME_LITE_DPR_FILE_V01);
4557  	}
4558  
4559  	cnss_pr_dbg("Received tme_opt_file_download indication cmd: %s\n", cmd);
4560  
4561  runtime_pm_put:
4562  	if (plat_priv->device_id == PEACH_DEVICE_ID)
4563  		cnss_bus_runtime_pm_put(plat_priv);
4564  	return count;
4565  }
4566  
hw_trace_override_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4567  static ssize_t hw_trace_override_store(struct device *dev,
4568  				       struct device_attribute *attr,
4569  				       const char *buf, size_t count)
4570  {
4571  	struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
4572  	int tmp = 0;
4573  
4574  	if (sscanf(buf, "%du", &tmp) != 1)
4575  		return -EINVAL;
4576  
4577  	plat_priv->hw_trc_override = tmp;
4578  	cnss_pr_dbg("Received QDSS hw_trc_override indication\n");
4579  	return count;
4580  }
4581  
charger_mode_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)4582  static ssize_t charger_mode_store(struct device *dev,
4583  				  struct device_attribute *attr,
4584  				  const char *buf, size_t count)
4585  {
4586  	struct cnss_plat_data *plat_priv = dev_get_drvdata(dev);
4587  	int tmp = 0;
4588  
4589  	if (sscanf(buf, "%du", &tmp) != 1)
4590  		return -EINVAL;
4591  
4592  	plat_priv->charger_mode = tmp;
4593  	cnss_pr_dbg("Received Charger Mode: %d\n", tmp);
4594  	return count;
4595  }
4596  
4597  static DEVICE_ATTR_WO(fs_ready);
4598  static DEVICE_ATTR_WO(shutdown);
4599  static DEVICE_ATTR_RW(recovery);
4600  static DEVICE_ATTR_WO(enable_hds);
4601  static DEVICE_ATTR_WO(qdss_trace_start);
4602  static DEVICE_ATTR_WO(qdss_trace_stop);
4603  static DEVICE_ATTR_WO(qdss_conf_download);
4604  static DEVICE_ATTR_RW(tme_opt_file_download);
4605  static DEVICE_ATTR_WO(hw_trace_override);
4606  static DEVICE_ATTR_WO(charger_mode);
4607  static DEVICE_ATTR_RW(time_sync_period);
4608  
4609  static struct attribute *cnss_attrs[] = {
4610  	&dev_attr_fs_ready.attr,
4611  	&dev_attr_shutdown.attr,
4612  	&dev_attr_recovery.attr,
4613  	&dev_attr_enable_hds.attr,
4614  	&dev_attr_qdss_trace_start.attr,
4615  	&dev_attr_qdss_trace_stop.attr,
4616  	&dev_attr_qdss_conf_download.attr,
4617  	&dev_attr_tme_opt_file_download.attr,
4618  	&dev_attr_hw_trace_override.attr,
4619  	&dev_attr_charger_mode.attr,
4620  	&dev_attr_time_sync_period.attr,
4621  	NULL,
4622  };
4623  
4624  static struct attribute_group cnss_attr_group = {
4625  	.attrs = cnss_attrs,
4626  };
4627  
cnss_create_sysfs_link(struct cnss_plat_data * plat_priv)4628  static int cnss_create_sysfs_link(struct cnss_plat_data *plat_priv)
4629  {
4630  	struct device *dev = &plat_priv->plat_dev->dev;
4631  	int ret;
4632  	char cnss_name[CNSS_FS_NAME_SIZE];
4633  	char shutdown_name[32];
4634  
4635  	if (cnss_is_dual_wlan_enabled()) {
4636  		snprintf(cnss_name, CNSS_FS_NAME_SIZE,
4637  			 CNSS_FS_NAME "_%d", plat_priv->plat_idx);
4638  		snprintf(shutdown_name, sizeof(shutdown_name),
4639  			 "shutdown_wlan_%d", plat_priv->plat_idx);
4640  	} else {
4641  		snprintf(cnss_name, CNSS_FS_NAME_SIZE, CNSS_FS_NAME);
4642  		snprintf(shutdown_name, sizeof(shutdown_name),
4643  			 "shutdown_wlan");
4644  	}
4645  
4646  	ret = sysfs_create_link(kernel_kobj, &dev->kobj, cnss_name);
4647  	if (ret) {
4648  		cnss_pr_err("Failed to create cnss link, err = %d\n",
4649  			    ret);
4650  		goto out;
4651  	}
4652  
4653  	/* This is only for backward compatibility. */
4654  	ret = sysfs_create_link(kernel_kobj, &dev->kobj, shutdown_name);
4655  	if (ret) {
4656  		cnss_pr_err("Failed to create shutdown_wlan link, err = %d\n",
4657  			    ret);
4658  		goto rm_cnss_link;
4659  	}
4660  
4661  	return 0;
4662  
4663  rm_cnss_link:
4664  	sysfs_remove_link(kernel_kobj, cnss_name);
4665  out:
4666  	return ret;
4667  }
4668  
cnss_remove_sysfs_link(struct cnss_plat_data * plat_priv)4669  static void cnss_remove_sysfs_link(struct cnss_plat_data *plat_priv)
4670  {
4671  	char cnss_name[CNSS_FS_NAME_SIZE];
4672  	char shutdown_name[32];
4673  
4674  	if (cnss_is_dual_wlan_enabled()) {
4675  		snprintf(cnss_name, CNSS_FS_NAME_SIZE,
4676  			 CNSS_FS_NAME "_%d", plat_priv->plat_idx);
4677  		snprintf(shutdown_name, sizeof(shutdown_name),
4678  			 "shutdown_wlan_%d", plat_priv->plat_idx);
4679  	} else {
4680  		snprintf(cnss_name, CNSS_FS_NAME_SIZE, CNSS_FS_NAME);
4681  		snprintf(shutdown_name, sizeof(shutdown_name),
4682  			 "shutdown_wlan");
4683  	}
4684  
4685  	sysfs_remove_link(kernel_kobj, shutdown_name);
4686  	sysfs_remove_link(kernel_kobj, cnss_name);
4687  }
4688  
cnss_create_sysfs(struct cnss_plat_data * plat_priv)4689  static int cnss_create_sysfs(struct cnss_plat_data *plat_priv)
4690  {
4691  	int ret = 0;
4692  
4693  	ret = devm_device_add_group(&plat_priv->plat_dev->dev,
4694  				    &cnss_attr_group);
4695  	if (ret) {
4696  		cnss_pr_err("Failed to create cnss device group, err = %d\n",
4697  			    ret);
4698  		goto out;
4699  	}
4700  
4701  	cnss_create_sysfs_link(plat_priv);
4702  
4703  	return 0;
4704  out:
4705  	return ret;
4706  }
4707  
4708  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 2, 0))
4709  union cnss_device_group_devres {
4710  	const struct attribute_group *group;
4711  };
4712  
devm_cnss_group_remove(struct device * dev,void * res)4713  static void devm_cnss_group_remove(struct device *dev, void *res)
4714  {
4715  	union cnss_device_group_devres *devres = res;
4716  	const struct attribute_group *group = devres->group;
4717  
4718  	cnss_pr_dbg("%s: removing group %p\n", __func__, group);
4719  	sysfs_remove_group(&dev->kobj, group);
4720  }
4721  
devm_cnss_group_match(struct device * dev,void * res,void * data)4722  static int devm_cnss_group_match(struct device *dev, void *res, void *data)
4723  {
4724  	return ((union cnss_device_group_devres *)res) == data;
4725  }
4726  
cnss_remove_sysfs(struct cnss_plat_data * plat_priv)4727  static void cnss_remove_sysfs(struct cnss_plat_data *plat_priv)
4728  {
4729  	cnss_remove_sysfs_link(plat_priv);
4730  	WARN_ON(devres_release(&plat_priv->plat_dev->dev,
4731  			       devm_cnss_group_remove, devm_cnss_group_match,
4732  			       (void *)&cnss_attr_group));
4733  }
4734  #else
cnss_remove_sysfs(struct cnss_plat_data * plat_priv)4735  static void cnss_remove_sysfs(struct cnss_plat_data *plat_priv)
4736  {
4737  	cnss_remove_sysfs_link(plat_priv);
4738  	devm_device_remove_group(&plat_priv->plat_dev->dev, &cnss_attr_group);
4739  }
4740  #endif
4741  
cnss_event_work_init(struct cnss_plat_data * plat_priv)4742  static int cnss_event_work_init(struct cnss_plat_data *plat_priv)
4743  {
4744  	spin_lock_init(&plat_priv->event_lock);
4745  	plat_priv->event_wq = alloc_workqueue("cnss_driver_event",
4746  					      WQ_UNBOUND, 1);
4747  	if (!plat_priv->event_wq) {
4748  		cnss_pr_err("Failed to create event workqueue!\n");
4749  		return -EFAULT;
4750  	}
4751  
4752  	INIT_WORK(&plat_priv->event_work, cnss_driver_event_work);
4753  	INIT_LIST_HEAD(&plat_priv->event_list);
4754  
4755  	return 0;
4756  }
4757  
cnss_event_work_deinit(struct cnss_plat_data * plat_priv)4758  static void cnss_event_work_deinit(struct cnss_plat_data *plat_priv)
4759  {
4760  	destroy_workqueue(plat_priv->event_wq);
4761  }
4762  
cnss_reboot_notifier(struct notifier_block * nb,unsigned long action,void * data)4763  static int cnss_reboot_notifier(struct notifier_block *nb,
4764  				unsigned long action,
4765  				void *data)
4766  {
4767  	struct cnss_plat_data *plat_priv =
4768  		container_of(nb, struct cnss_plat_data, reboot_nb);
4769  
4770  	set_bit(CNSS_IN_REBOOT, &plat_priv->driver_state);
4771  	cnss_bus_update_status(plat_priv, CNSS_SYS_REBOOT);
4772  	del_timer(&plat_priv->fw_boot_timer);
4773  	complete_all(&plat_priv->power_up_complete);
4774  	complete_all(&plat_priv->cal_complete);
4775  	cnss_pr_dbg("Reboot is in progress with action %d\n", action);
4776  
4777  	return NOTIFY_DONE;
4778  }
4779  
4780  #ifdef CONFIG_CNSS_HW_SECURE_DISABLE
4781  #ifdef CONFIG_CNSS_HW_SECURE_SMEM
cnss_wlan_hw_disable_check(struct cnss_plat_data * plat_priv)4782  int cnss_wlan_hw_disable_check(struct cnss_plat_data *plat_priv)
4783  {
4784  	uint32_t *peripheralStateInfo = NULL;
4785  	size_t size = 0;
4786  
4787  	/* Once this flag is set, secure peripheral feature
4788  	 * will not be supported till next reboot
4789  	 */
4790  	if (plat_priv->sec_peri_feature_disable)
4791  		return 0;
4792  
4793  	peripheralStateInfo = qcom_smem_get(QCOM_SMEM_HOST_ANY, PERISEC_SMEM_ID, &size);
4794  	if (IS_ERR_OR_NULL(peripheralStateInfo)) {
4795  		if (PTR_ERR(peripheralStateInfo) != -ENOENT &&
4796  		    PTR_ERR(peripheralStateInfo) != -ENODEV)
4797  			CNSS_ASSERT(0);
4798  
4799  		cnss_pr_dbg("Secure HW feature not enabled. ret = %d\n",
4800  			    PTR_ERR(peripheralStateInfo));
4801  		plat_priv->sec_peri_feature_disable = true;
4802  		return 0;
4803  	}
4804  
4805  	cnss_pr_dbg("Secure HW state: %d\n", *peripheralStateInfo);
4806  	if ((*peripheralStateInfo >> (HW_WIFI_UID - 0x500)) & 0x1)
4807  		set_bit(CNSS_WLAN_HW_DISABLED,
4808  			&plat_priv->driver_state);
4809  	else
4810  		clear_bit(CNSS_WLAN_HW_DISABLED,
4811  			  &plat_priv->driver_state);
4812  
4813  	return 0;
4814  }
4815  #else
cnss_wlan_hw_disable_check(struct cnss_plat_data * plat_priv)4816  int cnss_wlan_hw_disable_check(struct cnss_plat_data *plat_priv)
4817  {
4818  	struct Object client_env;
4819  	struct Object app_object;
4820  	u32 wifi_uid = HW_WIFI_UID;
4821  	union ObjectArg obj_arg[2] = {{{0, 0}}};
4822  	int ret;
4823  	u8 state = 0;
4824  
4825  	/* Once this flag is set, secure peripheral feature
4826  	 * will not be supported till next reboot
4827  	 */
4828  	if (plat_priv->sec_peri_feature_disable)
4829  		return 0;
4830  
4831  	/* get rootObj */
4832  	ret = get_client_env_object(&client_env);
4833  	if (ret) {
4834  		cnss_pr_dbg("Failed to get client_env_object, ret: %d\n", ret);
4835  		goto end;
4836  	}
4837  	ret = IClientEnv_open(client_env, HW_STATE_UID, &app_object);
4838  	if (ret) {
4839  		cnss_pr_dbg("Failed to get app_object, ret: %d\n",  ret);
4840  		if (ret == FEATURE_NOT_SUPPORTED) {
4841  			ret = 0; /* Do not Assert */
4842  			plat_priv->sec_peri_feature_disable = true;
4843  			cnss_pr_dbg("Secure HW feature not supported\n");
4844  		}
4845  		goto exit_release_clientenv;
4846  	}
4847  
4848  	obj_arg[0].b = (struct ObjectBuf) {&wifi_uid, sizeof(u32)};
4849  	obj_arg[1].b = (struct ObjectBuf) {&state, sizeof(u8)};
4850  	ret = Object_invoke(app_object, HW_OP_GET_STATE, obj_arg,
4851  			    ObjectCounts_pack(1, 1, 0, 0));
4852  
4853  	cnss_pr_dbg("SMC invoke ret: %d state: %d\n", ret, state);
4854  	if (ret) {
4855  		if (ret == PERIPHERAL_NOT_FOUND) {
4856  			ret = 0; /* Do not Assert */
4857  			plat_priv->sec_peri_feature_disable = true;
4858  			cnss_pr_dbg("Secure HW mode is not updated. Peripheral not found\n");
4859  		}
4860  		goto exit_release_app_obj;
4861  	}
4862  
4863  	if (state == 1)
4864  		set_bit(CNSS_WLAN_HW_DISABLED,
4865  			&plat_priv->driver_state);
4866  	else
4867  		clear_bit(CNSS_WLAN_HW_DISABLED,
4868  			  &plat_priv->driver_state);
4869  
4870  exit_release_app_obj:
4871  	Object_release(app_object);
4872  exit_release_clientenv:
4873  	Object_release(client_env);
4874  end:
4875  	if (ret) {
4876  		cnss_pr_err("Unable to get HW disable status\n");
4877  		CNSS_ASSERT(0);
4878  	}
4879  	return ret;
4880  }
4881  #endif
4882  #else
cnss_wlan_hw_disable_check(struct cnss_plat_data * plat_priv)4883  int cnss_wlan_hw_disable_check(struct cnss_plat_data *plat_priv)
4884  {
4885  	return 0;
4886  }
4887  #endif
4888  
4889  #ifdef CONFIG_DISABLE_CNSS_SRAM_DUMP
cnss_sram_dump_init(struct cnss_plat_data * plat_priv)4890  static void cnss_sram_dump_init(struct cnss_plat_data *plat_priv)
4891  {
4892  }
4893  #else
cnss_sram_dump_init(struct cnss_plat_data * plat_priv)4894  static void cnss_sram_dump_init(struct cnss_plat_data *plat_priv)
4895  {
4896  	if (plat_priv->device_id == QCA6490_DEVICE_ID &&
4897  	    cnss_get_host_build_type() == QMI_HOST_BUILD_TYPE_PRIMARY_V01)
4898  		plat_priv->sram_dump = kcalloc(SRAM_DUMP_SIZE, 1, GFP_KERNEL);
4899  }
4900  #endif
4901  
4902  #if IS_ENABLED(CONFIG_WCNSS_MEM_PRE_ALLOC)
cnss_initialize_mem_pool(unsigned long device_id)4903  static void cnss_initialize_mem_pool(unsigned long device_id)
4904  {
4905  	cnss_initialize_prealloc_pool(device_id);
4906  }
cnss_deinitialize_mem_pool(void)4907  static void cnss_deinitialize_mem_pool(void)
4908  {
4909  	cnss_deinitialize_prealloc_pool();
4910  }
4911  #else
cnss_initialize_mem_pool(unsigned long device_id)4912  static void cnss_initialize_mem_pool(unsigned long device_id)
4913  {
4914  }
cnss_deinitialize_mem_pool(void)4915  static void cnss_deinitialize_mem_pool(void)
4916  {
4917  }
4918  #endif
4919  
cnss_misc_init(struct cnss_plat_data * plat_priv)4920  static int cnss_misc_init(struct cnss_plat_data *plat_priv)
4921  {
4922  	int ret;
4923  
4924  	ret = cnss_init_sol_gpio(plat_priv);
4925  	if (ret)
4926  		return ret;
4927  
4928  	timer_setup(&plat_priv->fw_boot_timer,
4929  		    cnss_bus_fw_boot_timeout_hdlr, 0);
4930  
4931  	ret = device_init_wakeup(&plat_priv->plat_dev->dev, true);
4932  	if (ret)
4933  		cnss_pr_err("Failed to init platform device wakeup source, err = %d\n",
4934  			    ret);
4935  
4936  	INIT_WORK(&plat_priv->recovery_work, cnss_recovery_work_handler);
4937  	init_completion(&plat_priv->power_up_complete);
4938  	init_completion(&plat_priv->cal_complete);
4939  	init_completion(&plat_priv->rddm_complete);
4940  	init_completion(&plat_priv->recovery_complete);
4941  	init_completion(&plat_priv->daemon_connected);
4942  	mutex_init(&plat_priv->dev_lock);
4943  	mutex_init(&plat_priv->driver_ops_lock);
4944  
4945  	plat_priv->reboot_nb.notifier_call = cnss_reboot_notifier;
4946  	ret = register_reboot_notifier(&plat_priv->reboot_nb);
4947  	if (ret)
4948  		cnss_pr_err("Failed to register reboot notifier, err = %d\n",
4949  			    ret);
4950  
4951  	plat_priv->recovery_ws =
4952  		wakeup_source_register(&plat_priv->plat_dev->dev,
4953  				       "CNSS_FW_RECOVERY");
4954  	if (!plat_priv->recovery_ws)
4955  		cnss_pr_err("Failed to setup FW recovery wake source\n");
4956  
4957  	ret = cnss_plat_ipc_register(CNSS_PLAT_IPC_DAEMON_QMI_CLIENT_V01,
4958  				     cnss_daemon_connection_update_cb,
4959  				     plat_priv);
4960  	if (ret)
4961  		cnss_pr_err("QMI IPC connection call back register failed, err = %d\n",
4962  			    ret);
4963  
4964  	cnss_sram_dump_init(plat_priv);
4965  
4966  	if (of_property_read_bool(plat_priv->plat_dev->dev.of_node,
4967  				  "qcom,rc-ep-short-channel"))
4968  		cnss_set_feature_list(plat_priv, CNSS_RC_EP_ULTRASHORT_CHANNEL_V01);
4969  	if (plat_priv->device_id == PEACH_DEVICE_ID)
4970  		cnss_set_feature_list(plat_priv, CNSS_AUX_UC_SUPPORT_V01);
4971  
4972  	return 0;
4973  }
4974  
4975  #ifdef CONFIG_DISABLE_CNSS_SRAM_DUMP
cnss_sram_dump_deinit(struct cnss_plat_data * plat_priv)4976  static void cnss_sram_dump_deinit(struct cnss_plat_data *plat_priv)
4977  {
4978  }
4979  #else
cnss_sram_dump_deinit(struct cnss_plat_data * plat_priv)4980  static void cnss_sram_dump_deinit(struct cnss_plat_data *plat_priv)
4981  {
4982  	if (plat_priv->device_id == QCA6490_DEVICE_ID &&
4983  	    cnss_get_host_build_type() == QMI_HOST_BUILD_TYPE_PRIMARY_V01)
4984  		kfree(plat_priv->sram_dump);
4985  }
4986  #endif
4987  
cnss_misc_deinit(struct cnss_plat_data * plat_priv)4988  static void cnss_misc_deinit(struct cnss_plat_data *plat_priv)
4989  {
4990  	cnss_plat_ipc_unregister(CNSS_PLAT_IPC_DAEMON_QMI_CLIENT_V01,
4991  				 plat_priv);
4992  	complete_all(&plat_priv->recovery_complete);
4993  	complete_all(&plat_priv->rddm_complete);
4994  	complete_all(&plat_priv->cal_complete);
4995  	complete_all(&plat_priv->power_up_complete);
4996  	complete_all(&plat_priv->daemon_connected);
4997  	device_init_wakeup(&plat_priv->plat_dev->dev, false);
4998  	unregister_reboot_notifier(&plat_priv->reboot_nb);
4999  	del_timer(&plat_priv->fw_boot_timer);
5000  	wakeup_source_unregister(plat_priv->recovery_ws);
5001  	cnss_deinit_sol_gpio(plat_priv);
5002  	cnss_sram_dump_deinit(plat_priv);
5003  	kfree(plat_priv->on_chip_pmic_board_ids);
5004  }
5005  
cnss_init_time_sync_period_default(struct cnss_plat_data * plat_priv)5006  static void cnss_init_time_sync_period_default(struct cnss_plat_data *plat_priv)
5007  {
5008  	plat_priv->ctrl_params.time_sync_period_vote[TIME_SYNC_VOTE_WLAN] =
5009  		CNSS_TIME_SYNC_PERIOD_INVALID;
5010  	plat_priv->ctrl_params.time_sync_period_vote[TIME_SYNC_VOTE_CNSS] =
5011  		CNSS_TIME_SYNC_PERIOD_DEFAULT;
5012  }
5013  
cnss_init_control_params(struct cnss_plat_data * plat_priv)5014  static void cnss_init_control_params(struct cnss_plat_data *plat_priv)
5015  {
5016  	plat_priv->ctrl_params.quirks = CNSS_QUIRKS_DEFAULT;
5017  
5018  	plat_priv->cbc_enabled = !IS_ENABLED(CONFIG_CNSS_EMULATION) &&
5019  		of_property_read_bool(plat_priv->plat_dev->dev.of_node,
5020  				      "qcom,wlan-cbc-enabled");
5021  
5022  	plat_priv->ctrl_params.mhi_timeout = CNSS_MHI_TIMEOUT_DEFAULT;
5023  	plat_priv->ctrl_params.mhi_m2_timeout = CNSS_MHI_M2_TIMEOUT_DEFAULT;
5024  	plat_priv->ctrl_params.qmi_timeout = CNSS_QMI_TIMEOUT_DEFAULT;
5025  	plat_priv->ctrl_params.bdf_type = CNSS_BDF_TYPE_DEFAULT;
5026  	plat_priv->ctrl_params.time_sync_period = CNSS_TIME_SYNC_PERIOD_DEFAULT;
5027  	cnss_init_time_sync_period_default(plat_priv);
5028  	/* Set adsp_pc_enabled default value to true as ADSP pc is always
5029  	 * enabled by default
5030  	 */
5031  	plat_priv->adsp_pc_enabled = true;
5032  }
5033  
cnss_get_pm_domain_info(struct cnss_plat_data * plat_priv)5034  static void cnss_get_pm_domain_info(struct cnss_plat_data *plat_priv)
5035  {
5036  	struct device *dev = &plat_priv->plat_dev->dev;
5037  
5038  	plat_priv->use_pm_domain =
5039  		of_property_read_bool(dev->of_node, "use-pm-domain");
5040  
5041  	cnss_pr_dbg("use-pm-domain is %d\n", plat_priv->use_pm_domain);
5042  }
5043  
cnss_get_wlaon_pwr_ctrl_info(struct cnss_plat_data * plat_priv)5044  static void cnss_get_wlaon_pwr_ctrl_info(struct cnss_plat_data *plat_priv)
5045  {
5046  	struct device *dev = &plat_priv->plat_dev->dev;
5047  
5048  	plat_priv->set_wlaon_pwr_ctrl =
5049  		of_property_read_bool(dev->of_node, "qcom,set-wlaon-pwr-ctrl");
5050  
5051  	cnss_pr_dbg("set_wlaon_pwr_ctrl is %d\n",
5052  		    plat_priv->set_wlaon_pwr_ctrl);
5053  }
5054  
cnss_use_fw_path_with_prefix(struct cnss_plat_data * plat_priv)5055  static bool cnss_use_fw_path_with_prefix(struct cnss_plat_data *plat_priv)
5056  {
5057  	return (of_property_read_bool(plat_priv->plat_dev->dev.of_node,
5058  				      "qcom,converged-dt") ||
5059  		of_property_read_bool(plat_priv->plat_dev->dev.of_node,
5060  				      "qcom,same-dt-multi-dev") ||
5061  		of_property_read_bool(plat_priv->plat_dev->dev.of_node,
5062  				      "qcom,multi-wlan-exchg"));
5063  }
5064  
5065  static const struct platform_device_id cnss_platform_id_table[] = {
5066  	{ .name = "qca6174", .driver_data = QCA6174_DEVICE_ID, },
5067  	{ .name = "qca6290", .driver_data = QCA6290_DEVICE_ID, },
5068  	{ .name = "qca6390", .driver_data = QCA6390_DEVICE_ID, },
5069  	{ .name = "qca6490", .driver_data = QCA6490_DEVICE_ID, },
5070  	{ .name = "kiwi", .driver_data = KIWI_DEVICE_ID, },
5071  	{ .name = "mango", .driver_data = MANGO_DEVICE_ID, },
5072  	{ .name = "peach", .driver_data = PEACH_DEVICE_ID, },
5073  	{ .name = "qcaconv", .driver_data = 0, },
5074  	{ },
5075  };
5076  
5077  static const struct of_device_id cnss_of_match_table[] = {
5078  	{
5079  		.compatible = "qcom,cnss",
5080  		.data = (void *)&cnss_platform_id_table[0]},
5081  	{
5082  		.compatible = "qcom,cnss-qca6290",
5083  		.data = (void *)&cnss_platform_id_table[1]},
5084  	{
5085  		.compatible = "qcom,cnss-qca6390",
5086  		.data = (void *)&cnss_platform_id_table[2]},
5087  	{
5088  		.compatible = "qcom,cnss-qca6490",
5089  		.data = (void *)&cnss_platform_id_table[3]},
5090  	{
5091  		.compatible = "qcom,cnss-kiwi",
5092  		.data = (void *)&cnss_platform_id_table[4]},
5093  	{
5094  		.compatible = "qcom,cnss-mango",
5095  		.data = (void *)&cnss_platform_id_table[5]},
5096  	{
5097  		.compatible = "qcom,cnss-peach",
5098  		.data = (void *)&cnss_platform_id_table[6]},
5099  	{
5100  		.compatible = "qcom,cnss-qca-converged",
5101  		.data = (void *)&cnss_platform_id_table[7]},
5102  	{ },
5103  };
5104  MODULE_DEVICE_TABLE(of, cnss_of_match_table);
5105  
5106  static inline bool
cnss_use_nv_mac(struct cnss_plat_data * plat_priv)5107  cnss_use_nv_mac(struct cnss_plat_data *plat_priv)
5108  {
5109  	return of_property_read_bool(plat_priv->plat_dev->dev.of_node,
5110  				     "use-nv-mac");
5111  }
5112  
cnss_get_dev_cfg_node(struct cnss_plat_data * plat_priv)5113  static int cnss_get_dev_cfg_node(struct cnss_plat_data *plat_priv)
5114  {
5115  	struct device_node *child;
5116  	u32 id, i;
5117  	int id_n,  device_identifier_gpio, ret;
5118  	u8 gpio_value;
5119  
5120  
5121  	if (plat_priv->dt_type != CNSS_DTT_CONVERGED)
5122  		return 0;
5123  
5124  	/* Parses the wlan_sw_ctrl gpio which is used to identify device */
5125  	ret = cnss_get_wlan_sw_ctrl(plat_priv);
5126  	if (ret) {
5127  		cnss_pr_dbg("Failed to parse wlan_sw_ctrl gpio, error:%d", ret);
5128  		return ret;
5129  	}
5130  
5131  	device_identifier_gpio = plat_priv->pinctrl_info.wlan_sw_ctrl_gpio;
5132  
5133  	gpio_value = gpio_get_value(device_identifier_gpio);
5134  	cnss_pr_dbg("Value of Device Identifier GPIO: %d\n", gpio_value);
5135  
5136  	for_each_available_child_of_node(plat_priv->plat_dev->dev.of_node,
5137  					 child) {
5138  		if (strcmp(child->name, "chip_cfg"))
5139  			continue;
5140  
5141  		id_n = of_property_count_u32_elems(child, "supported-ids");
5142  		if (id_n <= 0) {
5143  			cnss_pr_err("Device id is NOT set\n");
5144  			return -EINVAL;
5145  		}
5146  
5147  		for (i = 0; i < id_n; i++) {
5148  			ret = of_property_read_u32_index(child,
5149  							 "supported-ids",
5150  							 i, &id);
5151  			if (ret) {
5152  				cnss_pr_err("Failed to read supported ids\n");
5153  				return -EINVAL;
5154  			}
5155  
5156  			if (gpio_value && id == QCA6490_DEVICE_ID) {
5157  				plat_priv->plat_dev->dev.of_node = child;
5158  				plat_priv->device_id = QCA6490_DEVICE_ID;
5159  				cnss_utils_update_device_type(CNSS_HSP_DEVICE_TYPE);
5160  				cnss_pr_dbg("got node[%s@%d] for device[0x%x]\n",
5161  					    child->name, i, id);
5162  				return 0;
5163  			} else if (!gpio_value && id == KIWI_DEVICE_ID) {
5164  				plat_priv->plat_dev->dev.of_node = child;
5165  				plat_priv->device_id = KIWI_DEVICE_ID;
5166  				cnss_utils_update_device_type(CNSS_HMT_DEVICE_TYPE);
5167  				cnss_pr_dbg("got node[%s@%d] for device[0x%x]\n",
5168  					    child->name, i, id);
5169  				return 0;
5170  			}
5171  		}
5172  	}
5173  
5174  	return -EINVAL;
5175  }
5176  
5177  static inline u32
cnss_dt_type(struct cnss_plat_data * plat_priv)5178  cnss_dt_type(struct cnss_plat_data *plat_priv)
5179  {
5180  	bool is_converged_dt = of_property_read_bool(
5181  		plat_priv->plat_dev->dev.of_node, "qcom,converged-dt");
5182  	bool is_multi_wlan_xchg;
5183  
5184  	if (is_converged_dt)
5185  		return CNSS_DTT_CONVERGED;
5186  
5187  	is_multi_wlan_xchg = of_property_read_bool(
5188  		plat_priv->plat_dev->dev.of_node, "qcom,multi-wlan-exchg");
5189  
5190  	if (is_multi_wlan_xchg)
5191  		return CNSS_DTT_MULTIEXCHG;
5192  	return CNSS_DTT_LEGACY;
5193  }
5194  
cnss_wlan_device_init(struct cnss_plat_data * plat_priv)5195  static int cnss_wlan_device_init(struct cnss_plat_data *plat_priv)
5196  {
5197  	int ret = 0;
5198  	int retry = 0;
5199  
5200  	if (test_bit(SKIP_DEVICE_BOOT, &plat_priv->ctrl_params.quirks))
5201  		return 0;
5202  
5203  retry:
5204  	ret = cnss_power_on_device(plat_priv, true);
5205  	if (ret)
5206  		goto end;
5207  
5208  	ret = cnss_bus_init(plat_priv);
5209  	if (ret) {
5210  		if ((ret != -EPROBE_DEFER) &&
5211  		    retry++ < POWER_ON_RETRY_MAX_TIMES) {
5212  			cnss_power_off_device(plat_priv);
5213  			cnss_pr_dbg("Retry cnss_bus_init #%d\n", retry);
5214  			msleep(POWER_ON_RETRY_DELAY_MS * retry);
5215  			goto retry;
5216  		}
5217  		goto power_off;
5218  	}
5219  	return 0;
5220  
5221  power_off:
5222  	cnss_power_off_device(plat_priv);
5223  end:
5224  	return ret;
5225  }
5226  
cnss_wlan_hw_enable(void)5227  int cnss_wlan_hw_enable(void)
5228  {
5229  	struct cnss_plat_data *plat_priv;
5230  	int ret = 0;
5231  
5232  	if (cnss_is_dual_wlan_enabled())
5233  		plat_priv = cnss_get_first_plat_priv(NULL);
5234  	else
5235  		plat_priv = cnss_get_plat_priv(NULL);
5236  
5237  	if (!plat_priv)
5238  		return -ENODEV;
5239  
5240  	clear_bit(CNSS_WLAN_HW_DISABLED, &plat_priv->driver_state);
5241  
5242  	if (test_bit(CNSS_PCI_PROBE_DONE, &plat_priv->driver_state))
5243  		goto register_driver;
5244  	ret = cnss_wlan_device_init(plat_priv);
5245  	if (ret) {
5246  		if (!test_bit(CNSS_WLAN_HW_DISABLED, &plat_priv->driver_state))
5247  			CNSS_ASSERT(0);
5248  		return ret;
5249  	}
5250  
5251  	if (test_bit(CNSS_FS_READY, &plat_priv->driver_state))
5252  		cnss_driver_event_post(plat_priv,
5253  				       CNSS_DRIVER_EVENT_COLD_BOOT_CAL_START,
5254  				       0, NULL);
5255  
5256  register_driver:
5257  	if (plat_priv->driver_ops)
5258  		ret = cnss_wlan_register_driver(plat_priv->driver_ops);
5259  
5260  	return ret;
5261  }
5262  EXPORT_SYMBOL(cnss_wlan_hw_enable);
5263  
cnss_set_wfc_mode(struct device * dev,struct cnss_wfc_cfg cfg)5264  int cnss_set_wfc_mode(struct device *dev, struct cnss_wfc_cfg cfg)
5265  {
5266  	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
5267  	int ret = 0;
5268  
5269  	if (!plat_priv)
5270  		return -ENODEV;
5271  
5272  	/* If IMS server is connected, return success without QMI send */
5273  	if (test_bit(CNSS_IMS_CONNECTED, &plat_priv->driver_state)) {
5274  		cnss_pr_dbg("Ignore host request as IMS server is connected");
5275  		return ret;
5276  	}
5277  
5278  	ret = cnss_wlfw_send_host_wfc_call_status(plat_priv, cfg);
5279  
5280  	return ret;
5281  }
5282  EXPORT_SYMBOL(cnss_set_wfc_mode);
5283  
cnss_tcdev_get_max_state(struct thermal_cooling_device * tcdev,unsigned long * thermal_state)5284  static int cnss_tcdev_get_max_state(struct thermal_cooling_device *tcdev,
5285  				    unsigned long *thermal_state)
5286  {
5287  	struct cnss_thermal_cdev *cnss_tcdev = NULL;
5288  
5289  	if (!tcdev || !tcdev->devdata) {
5290  		cnss_pr_err("tcdev or tcdev->devdata is null!\n");
5291  		return -EINVAL;
5292  	}
5293  
5294  	cnss_tcdev = tcdev->devdata;
5295  	*thermal_state = cnss_tcdev->max_thermal_state;
5296  
5297  	return 0;
5298  }
5299  
cnss_tcdev_get_cur_state(struct thermal_cooling_device * tcdev,unsigned long * thermal_state)5300  static int cnss_tcdev_get_cur_state(struct thermal_cooling_device *tcdev,
5301  				    unsigned long *thermal_state)
5302  {
5303  	struct cnss_thermal_cdev *cnss_tcdev = NULL;
5304  
5305  	if (!tcdev || !tcdev->devdata) {
5306  		cnss_pr_err("tcdev or tcdev->devdata is null!\n");
5307  		return -EINVAL;
5308  	}
5309  
5310  	cnss_tcdev = tcdev->devdata;
5311  	*thermal_state = cnss_tcdev->curr_thermal_state;
5312  
5313  	return 0;
5314  }
5315  
cnss_tcdev_set_cur_state(struct thermal_cooling_device * tcdev,unsigned long thermal_state)5316  static int cnss_tcdev_set_cur_state(struct thermal_cooling_device *tcdev,
5317  				    unsigned long thermal_state)
5318  {
5319  	struct cnss_thermal_cdev *cnss_tcdev = NULL;
5320  	struct cnss_plat_data *plat_priv =  cnss_get_plat_priv(NULL);
5321  	int ret = 0;
5322  
5323  	if (!tcdev || !tcdev->devdata) {
5324  		cnss_pr_err("tcdev or tcdev->devdata is null!\n");
5325  		return -EINVAL;
5326  	}
5327  
5328  	cnss_tcdev = tcdev->devdata;
5329  
5330  	if (thermal_state > cnss_tcdev->max_thermal_state)
5331  		return -EINVAL;
5332  
5333  	cnss_pr_vdbg("Cooling device set current state: %ld,for cdev id %d",
5334  		     thermal_state, cnss_tcdev->tcdev_id);
5335  
5336  	mutex_lock(&plat_priv->tcdev_lock);
5337  	ret = cnss_bus_set_therm_cdev_state(plat_priv,
5338  					    thermal_state,
5339  					    cnss_tcdev->tcdev_id);
5340  	if (!ret)
5341  		cnss_tcdev->curr_thermal_state = thermal_state;
5342  	mutex_unlock(&plat_priv->tcdev_lock);
5343  	if (ret) {
5344  		cnss_pr_err("Setting Current Thermal State Failed: %d,for cdev id %d",
5345  			    ret, cnss_tcdev->tcdev_id);
5346  		return ret;
5347  	}
5348  
5349  	return 0;
5350  }
5351  
5352  static struct thermal_cooling_device_ops cnss_cooling_ops = {
5353  	.get_max_state = cnss_tcdev_get_max_state,
5354  	.get_cur_state = cnss_tcdev_get_cur_state,
5355  	.set_cur_state = cnss_tcdev_set_cur_state,
5356  };
5357  
cnss_thermal_cdev_register(struct device * dev,unsigned long max_state,int tcdev_id)5358  int cnss_thermal_cdev_register(struct device *dev, unsigned long max_state,
5359  			       int tcdev_id)
5360  {
5361  	struct cnss_plat_data *priv = cnss_get_plat_priv(NULL);
5362  	struct cnss_thermal_cdev *cnss_tcdev = NULL;
5363  	char cdev_node_name[THERMAL_NAME_LENGTH] = "";
5364  	struct device_node *dev_node;
5365  	int ret = 0;
5366  
5367  	if (!priv) {
5368  		cnss_pr_err("Platform driver is not initialized!\n");
5369  		return -ENODEV;
5370  	}
5371  
5372  	cnss_tcdev = kzalloc(sizeof(*cnss_tcdev), GFP_KERNEL);
5373  	if (!cnss_tcdev) {
5374  		cnss_pr_err("Failed to allocate cnss_tcdev object!\n");
5375  		return -ENOMEM;
5376  	}
5377  
5378  	cnss_tcdev->tcdev_id = tcdev_id;
5379  	cnss_tcdev->max_thermal_state = max_state;
5380  
5381  	snprintf(cdev_node_name, THERMAL_NAME_LENGTH,
5382  		 "qcom,cnss_cdev%d", tcdev_id);
5383  
5384  	dev_node = of_find_node_by_name(NULL, cdev_node_name);
5385  	if (!dev_node) {
5386  		cnss_pr_err("Failed to get cooling device node\n");
5387  		kfree(cnss_tcdev);
5388  		return -EINVAL;
5389  	}
5390  
5391  	cnss_pr_dbg("tcdev node->name=%s\n", dev_node->name);
5392  
5393  	if (of_find_property(dev_node, "#cooling-cells", NULL)) {
5394  		cnss_tcdev->tcdev = thermal_of_cooling_device_register(dev_node,
5395  								       cdev_node_name,
5396  								       cnss_tcdev,
5397  								       &cnss_cooling_ops);
5398  		if (IS_ERR_OR_NULL(cnss_tcdev->tcdev)) {
5399  			ret = PTR_ERR(cnss_tcdev->tcdev);
5400  			cnss_pr_err("Cooling device register failed: %d, for cdev id %d\n",
5401  				    ret, cnss_tcdev->tcdev_id);
5402  			kfree(cnss_tcdev);
5403  		} else {
5404  			cnss_pr_dbg("Cooling device registered for cdev id %d",
5405  				    cnss_tcdev->tcdev_id);
5406  			mutex_lock(&priv->tcdev_lock);
5407  			list_add(&cnss_tcdev->tcdev_list,
5408  				 &priv->cnss_tcdev_list);
5409  			mutex_unlock(&priv->tcdev_lock);
5410  		}
5411  	} else {
5412  		cnss_pr_dbg("Cooling device registration not supported");
5413  		kfree(cnss_tcdev);
5414  		ret = -EOPNOTSUPP;
5415  	}
5416  
5417  	return ret;
5418  }
5419  EXPORT_SYMBOL(cnss_thermal_cdev_register);
5420  
cnss_thermal_cdev_unregister(struct device * dev,int tcdev_id)5421  void cnss_thermal_cdev_unregister(struct device *dev, int tcdev_id)
5422  {
5423  	struct cnss_plat_data *priv = cnss_get_plat_priv(NULL);
5424  	struct cnss_thermal_cdev *cnss_tcdev = NULL;
5425  
5426  	if (!priv) {
5427  		cnss_pr_err("Platform driver is not initialized!\n");
5428  		return;
5429  	}
5430  
5431  	mutex_lock(&priv->tcdev_lock);
5432  	while (!list_empty(&priv->cnss_tcdev_list)) {
5433  		cnss_tcdev = list_first_entry(&priv->cnss_tcdev_list,
5434  					      struct cnss_thermal_cdev,
5435  					      tcdev_list);
5436  		thermal_cooling_device_unregister(cnss_tcdev->tcdev);
5437  		list_del(&cnss_tcdev->tcdev_list);
5438  		kfree(cnss_tcdev);
5439  	}
5440  	mutex_unlock(&priv->tcdev_lock);
5441  }
5442  EXPORT_SYMBOL(cnss_thermal_cdev_unregister);
5443  
cnss_get_curr_therm_cdev_state(struct device * dev,unsigned long * thermal_state,int tcdev_id)5444  int cnss_get_curr_therm_cdev_state(struct device *dev,
5445  				   unsigned long *thermal_state,
5446  				   int tcdev_id)
5447  {
5448  	struct cnss_plat_data *priv = cnss_get_plat_priv(NULL);
5449  	struct cnss_thermal_cdev *cnss_tcdev = NULL;
5450  
5451  	if (!priv) {
5452  		cnss_pr_err("Platform driver is not initialized!\n");
5453  		return -ENODEV;
5454  	}
5455  
5456  	mutex_lock(&priv->tcdev_lock);
5457  	list_for_each_entry(cnss_tcdev, &priv->cnss_tcdev_list, tcdev_list) {
5458  		if (cnss_tcdev->tcdev_id != tcdev_id)
5459  			continue;
5460  
5461  		*thermal_state = cnss_tcdev->curr_thermal_state;
5462  		mutex_unlock(&priv->tcdev_lock);
5463  		cnss_pr_dbg("Cooling device current state: %ld, for cdev id %d",
5464  			    cnss_tcdev->curr_thermal_state, tcdev_id);
5465  		return 0;
5466  	}
5467  	mutex_unlock(&priv->tcdev_lock);
5468  	cnss_pr_dbg("Cooling device ID not found: %d", tcdev_id);
5469  	return -EINVAL;
5470  }
5471  EXPORT_SYMBOL(cnss_get_curr_therm_cdev_state);
5472  
cnss_probe(struct platform_device * plat_dev)5473  static int cnss_probe(struct platform_device *plat_dev)
5474  {
5475  	int ret = 0;
5476  	struct cnss_plat_data *plat_priv;
5477  	const struct of_device_id *of_id;
5478  	const struct platform_device_id *device_id;
5479  
5480  	if (cnss_get_plat_priv(plat_dev)) {
5481  		cnss_pr_err("Driver is already initialized!\n");
5482  		ret = -EEXIST;
5483  		goto out;
5484  	}
5485  
5486  	ret = cnss_plat_env_available();
5487  	if (ret)
5488  		goto out;
5489  
5490  	of_id = of_match_device(cnss_of_match_table, &plat_dev->dev);
5491  	if (!of_id || !of_id->data) {
5492  		cnss_pr_err("Failed to find of match device!\n");
5493  		ret = -ENODEV;
5494  		goto out;
5495  	}
5496  
5497  	device_id = of_id->data;
5498  
5499  	plat_priv = devm_kzalloc(&plat_dev->dev, sizeof(*plat_priv),
5500  				 GFP_KERNEL);
5501  	if (!plat_priv) {
5502  		ret = -ENOMEM;
5503  		goto out;
5504  	}
5505  
5506  	plat_priv->plat_dev = plat_dev;
5507  	plat_priv->dev_node = NULL;
5508  	plat_priv->device_id = device_id->driver_data;
5509  	plat_priv->dt_type = cnss_dt_type(plat_priv);
5510  	cnss_pr_dbg("Probing platform driver from dt type: %d\n",
5511  		    plat_priv->dt_type);
5512  
5513  	plat_priv->use_fw_path_with_prefix =
5514  		cnss_use_fw_path_with_prefix(plat_priv);
5515  
5516  	ret = cnss_get_dev_cfg_node(plat_priv);
5517  	if (ret) {
5518  		cnss_pr_err("Failed to get device cfg node, err = %d\n", ret);
5519  		goto reset_plat_dev;
5520  	}
5521  
5522  	cnss_initialize_mem_pool(plat_priv->device_id);
5523  
5524  	ret = cnss_get_pld_bus_ops_name(plat_priv);
5525  	if (ret)
5526  		cnss_pr_vdbg("Failed to find bus ops name, err = %d\n",
5527  			     ret);
5528  
5529  	ret = cnss_get_rc_num(plat_priv);
5530  
5531  	if (ret)
5532  		cnss_pr_err("Failed to find PCIe RC number, err = %d\n", ret);
5533  
5534  	cnss_pr_dbg("rc_num=%d\n", plat_priv->rc_num);
5535  
5536  	plat_priv->bus_type = cnss_get_bus_type(plat_priv);
5537  	plat_priv->use_nv_mac = cnss_use_nv_mac(plat_priv);
5538  	cnss_set_plat_priv(plat_dev, plat_priv);
5539  	cnss_set_device_name(plat_priv);
5540  	platform_set_drvdata(plat_dev, plat_priv);
5541  	INIT_LIST_HEAD(&plat_priv->vreg_list);
5542  	INIT_LIST_HEAD(&plat_priv->clk_list);
5543  
5544  	cnss_get_pm_domain_info(plat_priv);
5545  	cnss_get_wlaon_pwr_ctrl_info(plat_priv);
5546  	cnss_power_misc_params_init(plat_priv);
5547  	cnss_get_tcs_info(plat_priv);
5548  	cnss_get_cpr_info(plat_priv);
5549  	cnss_aop_interface_init(plat_priv);
5550  	cnss_init_control_params(plat_priv);
5551  
5552  	ret = cnss_get_resources(plat_priv);
5553  	if (ret)
5554  		goto reset_ctx;
5555  
5556  	ret = cnss_register_esoc(plat_priv);
5557  	if (ret)
5558  		goto free_res;
5559  
5560  	ret = cnss_register_bus_scale(plat_priv);
5561  	if (ret)
5562  		goto unreg_esoc;
5563  
5564  	ret = cnss_create_sysfs(plat_priv);
5565  	if (ret)
5566  		goto unreg_bus_scale;
5567  
5568  	ret = cnss_event_work_init(plat_priv);
5569  	if (ret)
5570  		goto remove_sysfs;
5571  
5572  	ret = cnss_dms_init(plat_priv);
5573  	if (ret)
5574  		goto deinit_event_work;
5575  
5576  	ret = cnss_debugfs_create(plat_priv);
5577  	if (ret)
5578  		goto deinit_dms;
5579  
5580  	ret = cnss_misc_init(plat_priv);
5581  	if (ret)
5582  		goto destroy_debugfs;
5583  
5584  	ret = cnss_wlan_hw_disable_check(plat_priv);
5585  	if (ret)
5586  		goto deinit_misc;
5587  
5588  	/* Make sure all platform related init are done before
5589  	 * device power on and bus init.
5590  	 */
5591  	if (!test_bit(CNSS_WLAN_HW_DISABLED, &plat_priv->driver_state)) {
5592  		ret = cnss_wlan_device_init(plat_priv);
5593  		if (ret)
5594  			goto deinit_misc;
5595  	} else {
5596  		cnss_pr_info("WLAN HW Disabled. Defer PCI enumeration\n");
5597  	}
5598  	cnss_register_coex_service(plat_priv);
5599  	cnss_register_ims_service(plat_priv);
5600  
5601  	mutex_init(&plat_priv->tcdev_lock);
5602  	INIT_LIST_HEAD(&plat_priv->cnss_tcdev_list);
5603  
5604  	cnss_pr_info("Platform driver probed successfully.\n");
5605  
5606  	return 0;
5607  
5608  deinit_misc:
5609  	cnss_misc_deinit(plat_priv);
5610  destroy_debugfs:
5611  	cnss_debugfs_destroy(plat_priv);
5612  deinit_dms:
5613  	cnss_dms_deinit(plat_priv);
5614  deinit_event_work:
5615  	cnss_event_work_deinit(plat_priv);
5616  remove_sysfs:
5617  	cnss_remove_sysfs(plat_priv);
5618  unreg_bus_scale:
5619  	cnss_unregister_bus_scale(plat_priv);
5620  unreg_esoc:
5621  	cnss_unregister_esoc(plat_priv);
5622  free_res:
5623  	cnss_put_resources(plat_priv);
5624  reset_ctx:
5625  	cnss_aop_interface_deinit(plat_priv);
5626  	platform_set_drvdata(plat_dev, NULL);
5627  	cnss_deinitialize_mem_pool();
5628  reset_plat_dev:
5629  	cnss_clear_plat_priv(plat_priv);
5630  out:
5631  	return ret;
5632  }
5633  
cnss_remove(struct platform_device * plat_dev)5634  static int cnss_remove(struct platform_device *plat_dev)
5635  {
5636  	struct cnss_plat_data *plat_priv = platform_get_drvdata(plat_dev);
5637  
5638  	plat_priv->audio_iommu_domain = NULL;
5639  	cnss_genl_exit();
5640  	cnss_unregister_ims_service(plat_priv);
5641  	cnss_unregister_coex_service(plat_priv);
5642  	cnss_bus_deinit(plat_priv);
5643  	cnss_misc_deinit(plat_priv);
5644  	cnss_debugfs_destroy(plat_priv);
5645  	cnss_dms_deinit(plat_priv);
5646  	cnss_qmi_deinit(plat_priv);
5647  	cnss_event_work_deinit(plat_priv);
5648  	cnss_cancel_dms_work();
5649  	cnss_remove_sysfs(plat_priv);
5650  	cnss_unregister_bus_scale(plat_priv);
5651  	cnss_unregister_esoc(plat_priv);
5652  	cnss_put_resources(plat_priv);
5653  	cnss_aop_interface_deinit(plat_priv);
5654  	cnss_deinitialize_mem_pool();
5655  	platform_set_drvdata(plat_dev, NULL);
5656  	cnss_clear_plat_priv(plat_priv);
5657  
5658  	return 0;
5659  }
5660  
5661  static struct platform_driver cnss_platform_driver = {
5662  	.probe  = cnss_probe,
5663  	.remove = cnss_remove,
5664  	.driver = {
5665  		.name = "cnss2",
5666  		.of_match_table = cnss_of_match_table,
5667  #ifdef CONFIG_CNSS_ASYNC
5668  		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
5669  #endif
5670  	},
5671  };
5672  
cnss_check_compatible_node(void)5673  static bool cnss_check_compatible_node(void)
5674  {
5675  	struct device_node *dn = NULL;
5676  
5677  	for_each_matching_node(dn, cnss_of_match_table) {
5678  		if (of_device_is_available(dn)) {
5679  			cnss_allow_driver_loading = true;
5680  			return true;
5681  		}
5682  	}
5683  
5684  	return false;
5685  }
5686  
5687  /**
5688   * cnss_is_valid_dt_node_found - Check if valid device tree node present
5689   *
5690   * Valid device tree node means a node with "compatible" property from the
5691   * device match table and "status" property is not disabled.
5692   *
5693   * Return: true if valid device tree node found, false if not found
5694   */
cnss_is_valid_dt_node_found(void)5695  static bool cnss_is_valid_dt_node_found(void)
5696  {
5697  	struct device_node *dn = NULL;
5698  
5699  	for_each_matching_node(dn, cnss_of_match_table) {
5700  		if (of_device_is_available(dn))
5701  			break;
5702  	}
5703  
5704  	if (dn)
5705  		return true;
5706  
5707  	return false;
5708  }
5709  
cnss_initialize(void)5710  static int __init cnss_initialize(void)
5711  {
5712  	int ret = 0;
5713  
5714  	if (!cnss_is_valid_dt_node_found())
5715  		return -ENODEV;
5716  
5717  	if (!cnss_check_compatible_node())
5718  		return ret;
5719  
5720  	cnss_debug_init();
5721  	ret = platform_driver_register(&cnss_platform_driver);
5722  	if (ret)
5723  		cnss_debug_deinit();
5724  
5725  	ret = cnss_genl_init();
5726  	if (ret < 0)
5727  		cnss_pr_err("CNSS genl init failed %d\n", ret);
5728  
5729  	cnss_init_plat_env_count();
5730  	return ret;
5731  }
5732  
cnss_exit(void)5733  static void __exit cnss_exit(void)
5734  {
5735  	cnss_genl_exit();
5736  	platform_driver_unregister(&cnss_platform_driver);
5737  	cnss_debug_deinit();
5738  }
5739  
5740  module_init(cnss_initialize);
5741  module_exit(cnss_exit);
5742  
5743  MODULE_LICENSE("GPL v2");
5744  MODULE_DESCRIPTION("CNSS2 Platform Driver");
5745