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 } 243