1 /*
2  * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: wlan_hdd_sysfs_fw_mode_config.c
21  *
22  * Implementation for creating sysfs file fw_mode_config
23  */
24 
25 #include <wlan_hdd_includes.h>
26 #include "osif_psoc_sync.h"
27 #include <wlan_hdd_sysfs.h>
28 #include <wlan_hdd_sysfs_fw_mode_config.h>
29 #include "wlan_policy_mgr_ucfg.h"
30 
31 static ssize_t
__wlan_hdd_store_fw_mode_config_sysfs(struct hdd_context * hdd_ctx,struct kobj_attribute * attr,const char * buf,size_t count)32 __wlan_hdd_store_fw_mode_config_sysfs(struct hdd_context *hdd_ctx,
33 				      struct kobj_attribute *attr,
34 				       const char *buf,
35 				       size_t count)
36 {
37 	uint8_t dual_mac_feature = DISABLE_DBS_CXN_AND_SCAN;
38 	char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1];
39 	char *sptr, *token;
40 	uint32_t val1, val2;
41 	QDF_STATUS status;
42 	int ret;
43 
44 	ret = wlan_hdd_validate_context(hdd_ctx);
45 	if (ret != 0)
46 		return ret;
47 
48 	if (!wlan_hdd_validate_modules_state(hdd_ctx))
49 		return -EINVAL;
50 
51 	ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
52 					      buf, count);
53 	if (ret) {
54 		hdd_err_rl("invalid input");
55 		return ret;
56 	}
57 
58 	hdd_debug("set_fw_mode_cfg: count %zu buf_local:(%s)",
59 		  count, buf_local);
60 
61 	sptr = buf_local;
62 	/* Get val1 */
63 	token = strsep(&sptr, " ");
64 	if (!token)
65 		return -EINVAL;
66 	if (kstrtou32(token, 0, &val1))
67 		return -EINVAL;
68 
69 	/* Get val2 */
70 	token = strsep(&sptr, " ");
71 	if (!token)
72 		return -EINVAL;
73 	if (kstrtou32(token, 0, &val2))
74 		return -EINVAL;
75 
76 	hdd_debug("Sysfs to set dual fw mode config");
77 	status = ucfg_policy_mgr_get_dual_mac_feature(hdd_ctx->psoc,
78 						      &dual_mac_feature);
79 	if (status != QDF_STATUS_SUCCESS)
80 		hdd_err_rl("can't get dual mac feature val, use def");
81 	if (dual_mac_feature == DISABLE_DBS_CXN_AND_SCAN) {
82 		hdd_err_rl("Dual mac feature is disabled from INI");
83 		return -EPERM;
84 	}
85 	hdd_debug("%d %d", val1, val2);
86 	policy_mgr_set_dual_mac_fw_mode_config(hdd_ctx->psoc,
87 					       val1, val2);
88 
89 	return count;
90 }
91 
92 static ssize_t
wlan_hdd_store_fw_mode_config_sysfs(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)93 wlan_hdd_store_fw_mode_config_sysfs(struct kobject *kobj,
94 				    struct kobj_attribute *attr,
95 				    const char *buf,
96 				    size_t count)
97 {
98 	struct osif_psoc_sync *psoc_sync;
99 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
100 	ssize_t errno_size;
101 	int ret;
102 
103 	ret = wlan_hdd_validate_context(hdd_ctx);
104 	if (ret != 0)
105 		return ret;
106 
107 	errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy),
108 					     &psoc_sync);
109 	if (errno_size)
110 		return errno_size;
111 
112 	errno_size = __wlan_hdd_store_fw_mode_config_sysfs(hdd_ctx, attr,
113 							   buf, count);
114 
115 	osif_psoc_sync_op_stop(psoc_sync);
116 
117 	return errno_size;
118 }
119 
120 static struct kobj_attribute set_fw_mode_cfg_attribute =
121 	__ATTR(fw_mode_config, 0220, NULL,
122 	       wlan_hdd_store_fw_mode_config_sysfs);
123 
hdd_sysfs_fw_mode_config_create(struct kobject * driver_kobject)124 int hdd_sysfs_fw_mode_config_create(struct kobject *driver_kobject)
125 {
126 	int error;
127 
128 	if (!driver_kobject) {
129 		hdd_err("could not get driver kobject!");
130 		return -EINVAL;
131 	}
132 
133 	error = sysfs_create_file(driver_kobject,
134 				  &set_fw_mode_cfg_attribute.attr);
135 	if (error)
136 		hdd_err("could not create fw_mode_config sysfs file");
137 
138 	return error;
139 }
140 
141 void
hdd_sysfs_fw_mode_config_destroy(struct kobject * driver_kobject)142 hdd_sysfs_fw_mode_config_destroy(struct kobject *driver_kobject)
143 {
144 	if (!driver_kobject) {
145 		hdd_err("could not get driver kobject!");
146 		return;
147 	}
148 	sysfs_remove_file(driver_kobject, &set_fw_mode_cfg_attribute.attr);
149 }
150