1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * This file is part of wl18xx
4  *
5  * Copyright (C) 2011 Texas Instruments Inc.
6  */
7 
8 #include "../wlcore/cmd.h"
9 #include "../wlcore/debug.h"
10 #include "../wlcore/hw_ops.h"
11 
12 #include "cmd.h"
13 
wl18xx_cmd_channel_switch(struct wl1271 * wl,struct wl12xx_vif * wlvif,struct ieee80211_channel_switch * ch_switch)14 int wl18xx_cmd_channel_switch(struct wl1271 *wl,
15 			      struct wl12xx_vif *wlvif,
16 			      struct ieee80211_channel_switch *ch_switch)
17 {
18 	struct wl18xx_cmd_channel_switch *cmd;
19 	u32 supported_rates;
20 	int ret;
21 
22 	wl1271_debug(DEBUG_ACX, "cmd channel switch (count=%d)",
23 		     ch_switch->count);
24 
25 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
26 	if (!cmd) {
27 		ret = -ENOMEM;
28 		goto out;
29 	}
30 
31 	cmd->role_id = wlvif->role_id;
32 	cmd->channel = ch_switch->chandef.chan->hw_value;
33 	cmd->switch_time = ch_switch->count;
34 	cmd->stop_tx = ch_switch->block_tx;
35 
36 	switch (ch_switch->chandef.chan->band) {
37 	case NL80211_BAND_2GHZ:
38 		cmd->band = WLCORE_BAND_2_4GHZ;
39 		break;
40 	case NL80211_BAND_5GHZ:
41 		cmd->band = WLCORE_BAND_5GHZ;
42 		break;
43 	default:
44 		wl1271_error("invalid channel switch band: %d",
45 			     ch_switch->chandef.chan->band);
46 		ret = -EINVAL;
47 		goto out_free;
48 	}
49 
50 	supported_rates = CONF_TX_ENABLED_RATES | CONF_TX_MCS_RATES;
51 	if (wlvif->bss_type == BSS_TYPE_STA_BSS)
52 		supported_rates |= wlcore_hw_sta_get_ap_rate_mask(wl, wlvif);
53 	else
54 		supported_rates |=
55 			wlcore_hw_ap_get_mimo_wide_rate_mask(wl, wlvif);
56 	if (wlvif->p2p)
57 		supported_rates &= ~CONF_TX_CCK_RATES;
58 	cmd->local_supported_rates = cpu_to_le32(supported_rates);
59 	cmd->channel_type = wlvif->channel_type;
60 
61 	ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0);
62 	if (ret < 0) {
63 		wl1271_error("failed to send channel switch command");
64 		goto out_free;
65 	}
66 
67 out_free:
68 	kfree(cmd);
69 out:
70 	return ret;
71 }
72 
wl18xx_cmd_smart_config_start(struct wl1271 * wl,u32 group_bitmap)73 int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap)
74 {
75 	struct wl18xx_cmd_smart_config_start *cmd;
76 	int ret = 0;
77 
78 	wl1271_debug(DEBUG_CMD, "cmd smart config start group_bitmap=0x%x",
79 		     group_bitmap);
80 
81 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
82 	if (!cmd) {
83 		ret = -ENOMEM;
84 		goto out;
85 	}
86 
87 	cmd->group_id_bitmask = cpu_to_le32(group_bitmap);
88 
89 	ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_START, cmd, sizeof(*cmd), 0);
90 	if (ret < 0) {
91 		wl1271_error("failed to send smart config start command");
92 		goto out_free;
93 	}
94 
95 out_free:
96 	kfree(cmd);
97 out:
98 	return ret;
99 }
100 
wl18xx_cmd_smart_config_stop(struct wl1271 * wl)101 int wl18xx_cmd_smart_config_stop(struct wl1271 *wl)
102 {
103 	struct wl1271_cmd_header *cmd;
104 	int ret = 0;
105 
106 	wl1271_debug(DEBUG_CMD, "cmd smart config stop");
107 
108 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
109 	if (!cmd) {
110 		ret = -ENOMEM;
111 		goto out;
112 	}
113 
114 	ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_STOP, cmd, sizeof(*cmd), 0);
115 	if (ret < 0) {
116 		wl1271_error("failed to send smart config stop command");
117 		goto out_free;
118 	}
119 
120 out_free:
121 	kfree(cmd);
122 out:
123 	return ret;
124 }
125 
wl18xx_cmd_smart_config_set_group_key(struct wl1271 * wl,u16 group_id,u8 key_len,u8 * key)126 int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id,
127 					  u8 key_len, u8 *key)
128 {
129 	struct wl18xx_cmd_smart_config_set_group_key *cmd;
130 	int ret = 0;
131 
132 	wl1271_debug(DEBUG_CMD, "cmd smart config set group key id=0x%x",
133 		     group_id);
134 
135 	if (key_len != sizeof(cmd->key)) {
136 		wl1271_error("invalid group key size: %d", key_len);
137 		return -E2BIG;
138 	}
139 
140 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
141 	if (!cmd) {
142 		ret = -ENOMEM;
143 		goto out;
144 	}
145 
146 	cmd->group_id = cpu_to_le32(group_id);
147 	memcpy(cmd->key, key, key_len);
148 
149 	ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_SET_GROUP_KEY, cmd,
150 			      sizeof(*cmd), 0);
151 	if (ret < 0) {
152 		wl1271_error("failed to send smart config set group key cmd");
153 		goto out_free;
154 	}
155 
156 out_free:
157 	kfree(cmd);
158 out:
159 	return ret;
160 }
161 
wl18xx_cmd_set_cac(struct wl1271 * wl,struct wl12xx_vif * wlvif,bool start)162 int wl18xx_cmd_set_cac(struct wl1271 *wl, struct wl12xx_vif *wlvif, bool start)
163 {
164 	struct wlcore_cmd_cac_start *cmd;
165 	int ret = 0;
166 
167 	wl1271_debug(DEBUG_CMD, "cmd cac (channel %d) %s",
168 		     wlvif->channel, start ? "start" : "stop");
169 
170 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
171 	if (!cmd)
172 		return -ENOMEM;
173 
174 	cmd->role_id = wlvif->role_id;
175 	cmd->channel = wlvif->channel;
176 	if (wlvif->band == NL80211_BAND_5GHZ)
177 		cmd->band = WLCORE_BAND_5GHZ;
178 	cmd->bandwidth = wlcore_get_native_channel_type(wlvif->channel_type);
179 
180 	ret = wl1271_cmd_send(wl,
181 			      start ? CMD_CAC_START : CMD_CAC_STOP,
182 			      cmd, sizeof(*cmd), 0);
183 	if (ret < 0) {
184 		wl1271_error("failed to send cac command");
185 		goto out_free;
186 	}
187 
188 out_free:
189 	kfree(cmd);
190 	return ret;
191 }
192 
wl18xx_cmd_radar_detection_debug(struct wl1271 * wl,u8 channel)193 int wl18xx_cmd_radar_detection_debug(struct wl1271 *wl, u8 channel)
194 {
195 	struct wl18xx_cmd_dfs_radar_debug *cmd;
196 	int ret = 0;
197 
198 	wl1271_debug(DEBUG_CMD, "cmd radar detection debug (chan %d)",
199 		     channel);
200 
201 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
202 	if (!cmd)
203 		return -ENOMEM;
204 
205 	cmd->channel = channel;
206 
207 	ret = wl1271_cmd_send(wl, CMD_DFS_RADAR_DETECTION_DEBUG,
208 			      cmd, sizeof(*cmd), 0);
209 	if (ret < 0) {
210 		wl1271_error("failed to send radar detection debug command");
211 		goto out_free;
212 	}
213 
214 out_free:
215 	kfree(cmd);
216 	return ret;
217 }
218 
wl18xx_cmd_dfs_master_restart(struct wl1271 * wl,struct wl12xx_vif * wlvif)219 int wl18xx_cmd_dfs_master_restart(struct wl1271 *wl, struct wl12xx_vif *wlvif)
220 {
221 	struct wl18xx_cmd_dfs_master_restart *cmd;
222 	int ret = 0;
223 
224 	wl1271_debug(DEBUG_CMD, "cmd dfs master restart (role %d)",
225 		     wlvif->role_id);
226 
227 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
228 	if (!cmd)
229 		return -ENOMEM;
230 
231 	cmd->role_id = wlvif->role_id;
232 
233 	ret = wl1271_cmd_send(wl, CMD_DFS_MASTER_RESTART,
234 			      cmd, sizeof(*cmd), 0);
235 	if (ret < 0) {
236 		wl1271_error("failed to send dfs master restart command");
237 		goto out_free;
238 	}
239 out_free:
240 	kfree(cmd);
241 	return ret;
242 }
243