cmd.c (11489B)
1// SPDX-License-Identifier: GPL-2.0 2#include "cmd.h" 3 4#include <linux/module.h> 5#include <linux/slab.h> 6#include <linux/etherdevice.h> 7 8#include "wl1251.h" 9#include "reg.h" 10#include "io.h" 11#include "ps.h" 12#include "acx.h" 13 14/** 15 * wl1251_cmd_send - Send command to firmware 16 * 17 * @wl: wl struct 18 * @id: command id 19 * @buf: buffer containing the command, must work with dma 20 * @len: length of the buffer 21 */ 22int wl1251_cmd_send(struct wl1251 *wl, u16 id, void *buf, size_t len) 23{ 24 struct wl1251_cmd_header *cmd; 25 unsigned long timeout; 26 u32 intr; 27 int ret = 0; 28 29 cmd = buf; 30 cmd->id = id; 31 cmd->status = 0; 32 33 WARN_ON(len % 4 != 0); 34 35 wl1251_mem_write(wl, wl->cmd_box_addr, buf, len); 36 37 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); 38 39 timeout = jiffies + msecs_to_jiffies(WL1251_COMMAND_TIMEOUT); 40 41 intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); 42 while (!(intr & WL1251_ACX_INTR_CMD_COMPLETE)) { 43 if (time_after(jiffies, timeout)) { 44 wl1251_error("command complete timeout"); 45 ret = -ETIMEDOUT; 46 goto out; 47 } 48 49 msleep(1); 50 51 intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); 52 } 53 54 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK, 55 WL1251_ACX_INTR_CMD_COMPLETE); 56 57out: 58 return ret; 59} 60 61/** 62 * wl1251_cmd_test - Send test command to firmware 63 * 64 * @wl: wl struct 65 * @buf: buffer containing the command, with all headers, must work with dma 66 * @buf_len: length of the buffer 67 * @answer: is answer needed 68 */ 69int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer) 70{ 71 int ret; 72 73 wl1251_debug(DEBUG_CMD, "cmd test"); 74 75 ret = wl1251_cmd_send(wl, CMD_TEST, buf, buf_len); 76 77 if (ret < 0) { 78 wl1251_warning("TEST command failed"); 79 return ret; 80 } 81 82 if (answer) { 83 struct wl1251_command *cmd_answer; 84 85 /* 86 * The test command got in, we can read the answer. 87 * The answer would be a wl1251_command, where the 88 * parameter array contains the actual answer. 89 */ 90 wl1251_mem_read(wl, wl->cmd_box_addr, buf, buf_len); 91 92 cmd_answer = buf; 93 94 if (cmd_answer->header.status != CMD_STATUS_SUCCESS) 95 wl1251_error("TEST command answer error: %d", 96 cmd_answer->header.status); 97 } 98 99 return 0; 100} 101 102/** 103 * wl1251_cmd_interrogate - Read acx from firmware 104 * 105 * @wl: wl struct 106 * @id: acx id 107 * @buf: buffer for the response, including all headers, must work with dma 108 * @len: length of buf 109 */ 110int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len) 111{ 112 struct acx_header *acx = buf; 113 int ret; 114 115 wl1251_debug(DEBUG_CMD, "cmd interrogate"); 116 117 acx->id = id; 118 119 /* payload length, does not include any headers */ 120 acx->len = len - sizeof(*acx); 121 122 ret = wl1251_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx)); 123 if (ret < 0) { 124 wl1251_error("INTERROGATE command failed"); 125 goto out; 126 } 127 128 /* the interrogate command got in, we can read the answer */ 129 wl1251_mem_read(wl, wl->cmd_box_addr, buf, len); 130 131 acx = buf; 132 if (acx->cmd.status != CMD_STATUS_SUCCESS) 133 wl1251_error("INTERROGATE command error: %d", 134 acx->cmd.status); 135 136out: 137 return ret; 138} 139 140/** 141 * wl1251_cmd_configure - Write acx value to firmware 142 * 143 * @wl: wl struct 144 * @id: acx id 145 * @buf: buffer containing acx, including all headers, must work with dma 146 * @len: length of buf 147 */ 148int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len) 149{ 150 struct acx_header *acx = buf; 151 int ret; 152 153 wl1251_debug(DEBUG_CMD, "cmd configure"); 154 155 acx->id = id; 156 157 /* payload length, does not include any headers */ 158 acx->len = len - sizeof(*acx); 159 160 ret = wl1251_cmd_send(wl, CMD_CONFIGURE, acx, len); 161 if (ret < 0) { 162 wl1251_warning("CONFIGURE command NOK"); 163 return ret; 164 } 165 166 return 0; 167} 168 169int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity, 170 void *bitmap, u16 bitmap_len, u8 bitmap_control) 171{ 172 struct wl1251_cmd_vbm_update *vbm; 173 int ret; 174 175 wl1251_debug(DEBUG_CMD, "cmd vbm"); 176 177 vbm = kzalloc(sizeof(*vbm), GFP_KERNEL); 178 if (!vbm) 179 return -ENOMEM; 180 181 /* Count and period will be filled by the target */ 182 vbm->tim.bitmap_ctrl = bitmap_control; 183 if (bitmap_len > PARTIAL_VBM_MAX) { 184 wl1251_warning("cmd vbm len is %d B, truncating to %d", 185 bitmap_len, PARTIAL_VBM_MAX); 186 bitmap_len = PARTIAL_VBM_MAX; 187 } 188 memcpy(vbm->tim.pvb_field, bitmap, bitmap_len); 189 vbm->tim.identity = identity; 190 vbm->tim.length = bitmap_len + 3; 191 192 vbm->len = cpu_to_le16(bitmap_len + 5); 193 194 ret = wl1251_cmd_send(wl, CMD_VBM, vbm, sizeof(*vbm)); 195 if (ret < 0) { 196 wl1251_error("VBM command failed"); 197 goto out; 198 } 199 200out: 201 kfree(vbm); 202 return ret; 203} 204 205int wl1251_cmd_data_path_rx(struct wl1251 *wl, u8 channel, bool enable) 206{ 207 struct cmd_enabledisable_path *cmd; 208 int ret; 209 u16 cmd_rx; 210 211 wl1251_debug(DEBUG_CMD, "cmd data path"); 212 213 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 214 if (!cmd) 215 return -ENOMEM; 216 217 cmd->channel = channel; 218 219 if (enable) 220 cmd_rx = CMD_ENABLE_RX; 221 else 222 cmd_rx = CMD_DISABLE_RX; 223 224 ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd)); 225 if (ret < 0) { 226 wl1251_error("rx %s cmd for channel %d failed", 227 enable ? "start" : "stop", channel); 228 goto out; 229 } 230 231 wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d", 232 enable ? "start" : "stop", channel); 233 234out: 235 kfree(cmd); 236 return ret; 237} 238 239int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable) 240{ 241 struct cmd_enabledisable_path *cmd; 242 int ret; 243 u16 cmd_tx; 244 245 wl1251_debug(DEBUG_CMD, "cmd data path"); 246 247 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 248 if (!cmd) 249 return -ENOMEM; 250 251 cmd->channel = channel; 252 253 if (enable) 254 cmd_tx = CMD_ENABLE_TX; 255 else 256 cmd_tx = CMD_DISABLE_TX; 257 258 ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd)); 259 if (ret < 0) 260 wl1251_error("tx %s cmd for channel %d failed", 261 enable ? "start" : "stop", channel); 262 else 263 wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d", 264 enable ? "start" : "stop", channel); 265 266 kfree(cmd); 267 return ret; 268} 269 270int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel, 271 u16 beacon_interval, u8 dtim_interval) 272{ 273 struct cmd_join *join; 274 int ret, i; 275 u8 *bssid; 276 277 join = kzalloc(sizeof(*join), GFP_KERNEL); 278 if (!join) 279 return -ENOMEM; 280 281 wl1251_debug(DEBUG_CMD, "cmd join%s ch %d %d/%d", 282 bss_type == BSS_TYPE_IBSS ? " ibss" : "", 283 channel, beacon_interval, dtim_interval); 284 285 /* Reverse order BSSID */ 286 bssid = (u8 *) &join->bssid_lsb; 287 for (i = 0; i < ETH_ALEN; i++) 288 bssid[i] = wl->bssid[ETH_ALEN - i - 1]; 289 290 join->rx_config_options = wl->rx_config; 291 join->rx_filter_options = wl->rx_filter; 292 293 join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | 294 RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; 295 296 join->beacon_interval = beacon_interval; 297 join->dtim_interval = dtim_interval; 298 join->bss_type = bss_type; 299 join->channel = channel; 300 join->ctrl = JOIN_CMD_CTRL_TX_FLUSH; 301 302 ret = wl1251_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join)); 303 if (ret < 0) { 304 wl1251_error("failed to initiate cmd join"); 305 goto out; 306 } 307 308out: 309 kfree(join); 310 return ret; 311} 312 313int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode) 314{ 315 struct wl1251_cmd_ps_params *ps_params = NULL; 316 int ret = 0; 317 318 wl1251_debug(DEBUG_CMD, "cmd set ps mode"); 319 320 ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); 321 if (!ps_params) 322 return -ENOMEM; 323 324 ps_params->ps_mode = ps_mode; 325 ps_params->send_null_data = 1; 326 ps_params->retries = 5; 327 ps_params->hang_over_period = 128; 328 ps_params->null_data_rate = 1; /* 1 Mbps */ 329 330 ret = wl1251_cmd_send(wl, CMD_SET_PS_MODE, ps_params, 331 sizeof(*ps_params)); 332 if (ret < 0) { 333 wl1251_error("cmd set_ps_mode failed"); 334 goto out; 335 } 336 337out: 338 kfree(ps_params); 339 return ret; 340} 341 342int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer, 343 size_t len) 344{ 345 struct cmd_read_write_memory *cmd; 346 int ret = 0; 347 348 wl1251_debug(DEBUG_CMD, "cmd read memory"); 349 350 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 351 if (!cmd) 352 return -ENOMEM; 353 354 WARN_ON(len > MAX_READ_SIZE); 355 len = min_t(size_t, len, MAX_READ_SIZE); 356 357 cmd->addr = addr; 358 cmd->size = len; 359 360 ret = wl1251_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd)); 361 if (ret < 0) { 362 wl1251_error("read memory command failed: %d", ret); 363 goto out; 364 } 365 366 /* the read command got in, we can now read the answer */ 367 wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); 368 369 if (cmd->header.status != CMD_STATUS_SUCCESS) 370 wl1251_error("error in read command result: %d", 371 cmd->header.status); 372 373 memcpy(answer, cmd->value, len); 374 375out: 376 kfree(cmd); 377 return ret; 378} 379 380int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id, 381 void *buf, size_t buf_len) 382{ 383 struct wl1251_cmd_packet_template *cmd; 384 size_t cmd_len; 385 int ret = 0; 386 387 wl1251_debug(DEBUG_CMD, "cmd template %d", cmd_id); 388 389 WARN_ON(buf_len > WL1251_MAX_TEMPLATE_SIZE); 390 buf_len = min_t(size_t, buf_len, WL1251_MAX_TEMPLATE_SIZE); 391 cmd_len = ALIGN(sizeof(*cmd) + buf_len, 4); 392 393 cmd = kzalloc(cmd_len, GFP_KERNEL); 394 if (!cmd) 395 return -ENOMEM; 396 397 cmd->size = cpu_to_le16(buf_len); 398 399 if (buf) 400 memcpy(cmd->data, buf, buf_len); 401 402 ret = wl1251_cmd_send(wl, cmd_id, cmd, cmd_len); 403 if (ret < 0) { 404 wl1251_warning("cmd set_template failed: %d", ret); 405 goto out; 406 } 407 408out: 409 kfree(cmd); 410 return ret; 411} 412 413int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, 414 struct ieee80211_channel *channels[], 415 unsigned int n_channels, unsigned int n_probes) 416{ 417 struct wl1251_cmd_scan *cmd; 418 int i, ret = 0; 419 420 wl1251_debug(DEBUG_CMD, "cmd scan channels %d", n_channels); 421 422 WARN_ON(n_channels > SCAN_MAX_NUM_OF_CHANNELS); 423 424 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 425 if (!cmd) 426 return -ENOMEM; 427 428 cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); 429 cmd->params.rx_filter_options = cpu_to_le32(CFG_RX_PRSP_EN | 430 CFG_RX_MGMT_EN | 431 CFG_RX_BCN_EN); 432 cmd->params.scan_options = 0; 433 /* 434 * Use high priority scan when not associated to prevent fw issue 435 * causing never-ending scans (sometimes 20+ minutes). 436 * Note: This bug may be caused by the fw's DTIM handling. 437 */ 438 if (is_zero_ether_addr(wl->bssid)) 439 cmd->params.scan_options |= cpu_to_le16(WL1251_SCAN_OPT_PRIORITY_HIGH); 440 cmd->params.num_channels = n_channels; 441 cmd->params.num_probe_requests = n_probes; 442 cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ 443 cmd->params.tid_trigger = 0; 444 445 for (i = 0; i < n_channels; i++) { 446 cmd->channels[i].min_duration = 447 cpu_to_le32(WL1251_SCAN_MIN_DURATION); 448 cmd->channels[i].max_duration = 449 cpu_to_le32(WL1251_SCAN_MAX_DURATION); 450 memset(&cmd->channels[i].bssid_lsb, 0xff, 4); 451 memset(&cmd->channels[i].bssid_msb, 0xff, 2); 452 cmd->channels[i].early_termination = 0; 453 cmd->channels[i].tx_power_att = 0; 454 cmd->channels[i].channel = channels[i]->hw_value; 455 } 456 457 if (ssid) { 458 int len = clamp_val(ssid_len, 0, IEEE80211_MAX_SSID_LEN); 459 460 cmd->params.ssid_len = len; 461 memcpy(cmd->params.ssid, ssid, len); 462 } 463 464 ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); 465 if (ret < 0) { 466 wl1251_error("cmd scan failed: %d", ret); 467 goto out; 468 } 469 470 wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); 471 472 if (cmd->header.status != CMD_STATUS_SUCCESS) { 473 wl1251_error("cmd scan status wasn't success: %d", 474 cmd->header.status); 475 ret = -EIO; 476 goto out; 477 } 478 479out: 480 kfree(cmd); 481 return ret; 482} 483 484int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout) 485{ 486 struct wl1251_cmd_trigger_scan_to *cmd; 487 int ret; 488 489 wl1251_debug(DEBUG_CMD, "cmd trigger scan to"); 490 491 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 492 if (!cmd) 493 return -ENOMEM; 494 495 cmd->timeout = timeout; 496 497 ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, cmd, sizeof(*cmd)); 498 if (ret < 0) { 499 wl1251_error("cmd trigger scan to failed: %d", ret); 500 goto out; 501 } 502 503out: 504 kfree(cmd); 505 return ret; 506}