GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / net / wireless / ti / wl18xx / cmd.c
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
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
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
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
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
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
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
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 }