int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) { struct cmd_enabledisable_path *cmd; int ret; u16 cmd_rx, cmd_tx; wl1271_debug(DEBUG_CMD, "cmd data path"); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } /* the channel here is only used for calibration, so hardcoded to 1 */ cmd->channel = 1; if (enable) { cmd_rx = CMD_ENABLE_RX; cmd_tx = CMD_ENABLE_TX; } else { cmd_rx = CMD_DISABLE_RX; cmd_tx = CMD_DISABLE_TX; } ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("rx %s cmd for channel %d failed", enable ? "start" : "stop", cmd->channel); goto out; } wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", enable ? "start" : "stop", cmd->channel); ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("tx %s cmd for channel %d failed", enable ? "start" : "stop", cmd->channel); goto out; } wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", enable ? "start" : "stop", cmd->channel); out: kfree(cmd); return ret; }
int wl18xx_cmd_smart_config_start(struct wl1271 *wl, u32 group_bitmap) { struct wl18xx_cmd_smart_config_start *cmd; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd smart config start group_bitmap=0x%x", group_bitmap); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } cmd->group_id_bitmask = cpu_to_le32(group_bitmap); ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_START, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("failed to send smart config start command"); goto out_free; } out_free: kfree(cmd); out: return ret; }
int wl18xx_cmd_smart_config_set_group_key(struct wl1271 *wl, u16 group_id, u8 key_len, u8 *key) { struct wl18xx_cmd_smart_config_set_group_key *cmd; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd smart config set group key id=0x%x", group_id); if (key_len != sizeof(cmd->key)) { wl1271_error("invalid group key size: %d", key_len); return -E2BIG; } cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } cmd->group_id = cpu_to_le32(group_id); memcpy(cmd->key, key, key_len); ret = wl1271_cmd_send(wl, CMD_SMART_CONFIG_SET_GROUP_KEY, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("failed to send smart config set group key cmd"); goto out_free; } out_free: kfree(cmd); out: return ret; }
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) { struct acx_header *acx = buf; int ret; wl1271_debug(DEBUG_CMD, "cmd interrogate"); acx->id = id; acx->len = len - sizeof(*acx); ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx)); if (ret < 0) { wl1271_error("INTERROGATE command failed"); goto out; } wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, len); acx = buf; if (acx->cmd.status != CMD_STATUS_SUCCESS) wl1271_error("INTERROGATE command error: %d", acx->cmd.status); out: return ret; }
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer) { int ret; wl1271_debug(DEBUG_CMD, "cmd test"); ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len); if (ret < 0) { wl1271_warning("TEST command failed"); return ret; } if (answer) { struct wl1271_command *cmd_answer; wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len); cmd_answer = buf; if (cmd_answer->header.status != CMD_STATUS_SUCCESS) wl1271_error("TEST command answer error: %d", cmd_answer->header.status); } return 0; }
void wl1271_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl1271_cmd_sched_scan_stop *stop; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd periodic scan stop"); /* FIXME: what to do if alloc'ing to stop fails? */ stop = kzalloc(sizeof(*stop), GFP_KERNEL); if (!stop) { wl1271_error("failed to alloc memory to send sched scan stop"); return; } stop->role_id = wlvif->dev_role_id; stop->tag = WL1271_SCAN_DEFAULT_TAG; ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, sizeof(*stop), 0); if (ret < 0) { wl1271_error("failed to send sched scan stop command"); /* * sched scan is expected to be stopped even if cmd execution * failed. clear the state correctly. */ wl->sched_vif = NULL; ieee80211_sched_scan_stopped(wl->hw); goto out_free; } out_free: kfree(stop); }
int wl12xx_cmd_role_start_ibss(struct wl1271 *wl) { struct wl12xx_cmd_role_start *cmd; struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; int ret; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wl->role_id); cmd->role_id = wl->role_id; if (wl->band == IEEE80211_BAND_5GHZ) cmd->band = WL12XX_BAND_5GHZ; cmd->channel = wl->channel; cmd->ibss.basic_rate_set = cpu_to_le32(wl->basic_rate_set); cmd->ibss.beacon_interval = cpu_to_le16(wl->beacon_int); cmd->ibss.dtim_interval = bss_conf->dtim_period; cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY; cmd->ibss.ssid_len = wl->ssid_len; memcpy(cmd->ibss.ssid, wl->ssid, wl->ssid_len); memcpy(cmd->ibss.bssid, wl->bssid, ETH_ALEN); cmd->sta.local_rates = cpu_to_le32(wl->rate_set); if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { ret = wl12xx_allocate_link(wl, &wl->sta_hlid); if (ret) goto out_free; } cmd->ibss.hlid = wl->sta_hlid; cmd->ibss.remote_rates = cpu_to_le32(wl->rate_set); wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " "basic_rate_set: 0x%x, remote_rates: 0x%x", wl->role_id, cmd->sta.hlid, cmd->sta.session, wl->basic_rate_set, wl->rate_set); wl1271_debug(DEBUG_CMD, "wl->bssid = %pM", wl->bssid); ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("failed to initiate cmd role enable"); goto err_hlid; } goto out_free; err_hlid: /* clear links on error. */ wl12xx_free_link(wl, &wl->sta_hlid); out_free: kfree(cmd); out: return ret; }
static int __wl18xx_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 scan_type) { struct wl18xx_cmd_scan_stop *stop; int ret; wl1271_debug(DEBUG_CMD, "cmd periodic scan stop"); stop = kzalloc(sizeof(*stop), GFP_KERNEL); if (!stop) { wl1271_error("failed to alloc memory to send sched scan stop"); return -ENOMEM; } stop->role_id = wlvif->role_id; stop->scan_type = scan_type; ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, stop, sizeof(*stop), 0); if (ret < 0) { wl1271_error("failed to send sched scan stop command"); goto out_free; } out_free: kfree(stop); return ret; }
/** * send test command to firmware * * @wl: wl struct * @buf: buffer containing the command, with all headers, must work with dma * @len: length of the buffer * @answer: is answer needed */ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer) { int ret; wl1271_debug(DEBUG_CMD, "cmd test"); ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len); if (ret < 0) { wl1271_warning("TEST command failed"); return ret; } if (answer) { struct wl1271_command *cmd_answer; /* * The test command got in, we can read the answer. * The answer would be a wl1271_command, where the * parameter array contains the actual answer. */ wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len); cmd_answer = buf; if (cmd_answer->header.status != CMD_STATUS_SUCCESS) wl1271_error("TEST command answer error: %d", cmd_answer->header.status); } return 0; }
int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id) { struct wl12xx_cmd_role_disable *cmd; int ret; wl1271_debug(DEBUG_CMD, "cmd role disable"); if (WARN_ON(*role_id == WL12XX_INVALID_ROLE_ID)) return -ENOENT; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } cmd->role_id = *role_id; ret = wl1271_cmd_send(wl, CMD_ROLE_DISABLE, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("failed to initiate cmd role disable"); goto out_free; } __clear_bit(*role_id, wl->roles_map); *role_id = WL12XX_INVALID_ROLE_ID; out_free: kfree(cmd); out: return ret; }
void wl1271_scan_sched_scan_stop(struct wl1271 *wl) { struct wl1271_cmd_sched_scan_stop *stop; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd periodic scan stop"); /* FIXME: what to do if alloc'ing to stop fails? */ stop = kzalloc(sizeof(*stop), GFP_KERNEL); if (!stop) { wl1271_error("failed to alloc memory to send sched scan stop"); return; } stop->tag = WL1271_SCAN_DEFAULT_TAG; ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, sizeof(*stop), 0); if (ret < 0) { wl1271_error("failed to send sched scan stop command"); goto out_free; } wl->sched_scanning = false; out_free: kfree(stop); }
/* TODO: unify stop functions */ void wl1271_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl12xx_cmd_scan_stop *stop; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd periodic scan stop"); /* FIXME: what to do if alloc'ing to stop fails? */ stop = kzalloc(sizeof(*stop), GFP_KERNEL); if (!stop) { wl1271_error("failed to alloc memory to send sched scan stop"); return; } stop->role_id = wlvif->role_id; stop->scan_type = SCAN_TYPE_PERIODIC; ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, stop, sizeof(*stop), 0); if (ret < 0) { wl1271_error("failed to send sched scan stop command"); goto out_free; } out_free: kfree(stop); }
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, size_t len) { struct cmd_read_write_memory *cmd; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd read memory"); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } WARN_ON(len > MAX_READ_SIZE); len = min_t(size_t, len, MAX_READ_SIZE); cmd->addr = cpu_to_le32(addr); cmd->size = cpu_to_le32(len); ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd), sizeof(*cmd)); if (ret < 0) { wl1271_error("read memory command failed: %d", ret); goto out; } /* the read command got in */ memcpy(answer, cmd->value, len); out: kfree(cmd); return ret; }
int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl12xx_cmd_role_stop *cmd; int ret; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wlvif->role_id); cmd->role_id = wlvif->role_id; ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("failed to initiate cmd role stop ap"); goto out_free; } wl12xx_free_link(wl, wlvif, &wlvif->ap.bcast_hlid); wl12xx_free_link(wl, wlvif, &wlvif->ap.global_hlid); out_free: kfree(cmd); out: return ret; }
int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 ps_mode, u16 auto_ps_timeout) { struct wl1271_cmd_ps_params *ps_params = NULL; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd set ps mode"); ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); if (!ps_params) { ret = -ENOMEM; goto out; } ps_params->role_id = wlvif->role_id; ps_params->ps_mode = ps_mode; ps_params->auto_ps_timeout = auto_ps_timeout; ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, sizeof(*ps_params), 0); if (ret < 0) { wl1271_error("cmd set_ps_mode failed"); goto out; } out: kfree(ps_params); return ret; }
int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl1271_cmd_sched_scan_start *start; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd periodic scan start"); if (wlvif->bss_type != BSS_TYPE_STA_BSS) return -EOPNOTSUPP; if ((wl->quirks & WLCORE_QUIRK_NO_SCHED_SCAN_WHILE_CONN) && test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) return -EBUSY; start = kzalloc(sizeof(*start), GFP_KERNEL); if (!start) return -ENOMEM; start->role_id = wlvif->role_id; start->tag = WL1271_SCAN_DEFAULT_TAG; ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start, sizeof(*start), 0); if (ret < 0) { wl1271_error("failed to send scan start command"); goto out_free; } out_free: kfree(start); return ret; }
/* use this function to stop ibss as well */ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl12xx_cmd_role_stop *cmd; int ret; if (WARN_ON(wlvif->sta.hlid == WL12XX_INVALID_LINK_ID)) return -EINVAL; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wlvif->role_id); cmd->role_id = wlvif->role_id; cmd->disc_type = DISCONNECT_IMMEDIATE; cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("failed to initiate cmd role stop sta"); goto out_free; } wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); out_free: kfree(cmd); out: return ret; }
int wl1271_scan_stop(struct wl1271 *wl) { struct wl1271_cmd_header *cmd = NULL; int ret = 0; if (WARN_ON(wl->scan.state == WL1271_SCAN_STATE_IDLE)) return -EINVAL; wl1271_debug(DEBUG_CMD, "cmd scan stop"); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } ret = wl1271_cmd_send(wl, CMD_STOP_SCAN, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("cmd stop_scan failed"); goto out; } out: kfree(cmd); return ret; }
int wl1271_scan_sched_scan_start(struct wl1271 *wl) { struct wl1271_cmd_sched_scan_start *start; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd periodic scan start"); if (wl->bss_type != BSS_TYPE_STA_BSS) return -EOPNOTSUPP; if (!test_bit(WL1271_FLAG_IDLE, &wl->flags)) return -EBUSY; start = kzalloc(sizeof(*start), GFP_KERNEL); if (!start) return -ENOMEM; start->tag = WL1271_SCAN_DEFAULT_TAG; ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start, sizeof(*start), 0); if (ret < 0) { wl1271_error("failed to send scan start command"); goto out_free; } out_free: kfree(start); return ret; }
int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send) { struct wl1271_cmd_ps_params *ps_params = NULL; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd set ps mode"); ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); if (!ps_params) { ret = -ENOMEM; goto out; } ps_params->ps_mode = ps_mode; ps_params->send_null_data = send; ps_params->retries = wl->conf.conn.psm_entry_nullfunc_retries; ps_params->hang_over_period = wl->conf.conn.psm_entry_hangover_period; ps_params->null_data_rate = cpu_to_le32(rates); ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, sizeof(*ps_params), 0); if (ret < 0) { wl1271_error("cmd set_ps_mode failed"); goto out; } out: kfree(ps_params); return ret; }
int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct wl12xx_cmd_role_start *cmd; int ret; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wlvif->role_id); cmd->role_id = wlvif->role_id; if (wlvif->band == IEEE80211_BAND_5GHZ) cmd->band = WLCORE_BAND_5GHZ; cmd->channel = wlvif->channel; cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set); cmd->sta.beacon_interval = cpu_to_le16(wlvif->beacon_int); cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY; cmd->sta.ssid_len = wlvif->ssid_len; memcpy(cmd->sta.ssid, wlvif->ssid, wlvif->ssid_len); memcpy(cmd->sta.bssid, vif->bss_conf.bssid, ETH_ALEN); cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); cmd->channel_type = wlcore_get_native_channel_type(wlvif->channel_type); if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid); if (ret) goto out_free; } cmd->sta.hlid = wlvif->sta.hlid; cmd->sta.session = wl12xx_get_new_session_id(wl, wlvif); cmd->sta.remote_rates = cpu_to_le32(wlvif->rate_set); wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " "basic_rate_set: 0x%x, remote_rates: 0x%x", wlvif->role_id, cmd->sta.hlid, cmd->sta.session, wlvif->basic_rate_set, wlvif->rate_set); ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("failed to initiate cmd role start sta"); goto err_hlid; } goto out_free; err_hlid: /* clear links on error. */ wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); out_free: kfree(cmd); out: return ret; }
int wl18xx_cmd_channel_switch(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct ieee80211_channel_switch *ch_switch) { struct wl18xx_cmd_channel_switch *cmd; u32 supported_rates; int ret; wl1271_debug(DEBUG_ACX, "cmd channel switch"); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } cmd->role_id = wlvif->role_id; cmd->channel = ch_switch->chandef.chan->hw_value; cmd->switch_time = ch_switch->count; cmd->stop_tx = ch_switch->block_tx; switch (ch_switch->chandef.chan->band) { case IEEE80211_BAND_2GHZ: cmd->band = WLCORE_BAND_2_4GHZ; break; case IEEE80211_BAND_5GHZ: cmd->band = WLCORE_BAND_5GHZ; break; default: wl1271_error("invalid channel switch band: %d", ch_switch->chandef.chan->band); ret = -EINVAL; goto out_free; } supported_rates = CONF_TX_ENABLED_RATES | CONF_TX_MCS_RATES; if (wlvif->bss_type == BSS_TYPE_STA_BSS) supported_rates |= wlcore_hw_sta_get_ap_rate_mask(wl, wlvif); else supported_rates |= wlcore_hw_ap_get_mimo_wide_rate_mask(wl, wlvif); if (wlvif->p2p) supported_rates &= ~CONF_TX_CCK_RATES; cmd->local_supported_rates = cpu_to_le32(supported_rates); cmd->channel_type = wlvif->channel_type; ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("failed to send channel switch command"); goto out_free; } out_free: kfree(cmd); out: return ret; }
int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) { struct wl1271_cmd_join *join; int ret, i; u8 *bssid; join = kzalloc(sizeof(*join), GFP_KERNEL); if (!join) { ret = -ENOMEM; goto out; } wl1271_debug(DEBUG_CMD, "cmd join"); /* Reverse order BSSID */ bssid = (u8 *) &join->bssid_lsb; for (i = 0; i < ETH_ALEN; i++) bssid[i] = wl->bssid[ETH_ALEN - i - 1]; join->rx_config_options = cpu_to_le32(wl->rx_config); join->rx_filter_options = cpu_to_le32(wl->rx_filter); join->bss_type = bss_type; join->basic_rate_set = cpu_to_le32(wl->basic_rate_set); if (wl->band == IEEE80211_BAND_5GHZ) join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; join->beacon_interval = cpu_to_le16(wl->beacon_int); join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; join->channel = wl->channel; join->ssid_len = wl->ssid_len; memcpy(join->ssid, wl->ssid, wl->ssid_len); join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; /* reset TX security counters */ wl->tx_security_last_seq = 0; wl->tx_security_seq = 0; ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); if (ret < 0) { wl1271_error("failed to initiate cmd join"); goto out_free; } ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID); if (ret < 0) wl1271_error("cmd join event completion error"); out_free: kfree(join); out: return ret; }
static int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif, enum ieee80211_band band, int channel) { struct wl12xx_cmd_role_start *cmd; int ret; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wlvif->dev_role_id); cmd->role_id = wlvif->dev_role_id; if (band == IEEE80211_BAND_5GHZ) cmd->band = WLCORE_BAND_5GHZ; cmd->channel = channel; if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) { ret = wl12xx_allocate_link(wl, wlvif, &wlvif->dev_hlid); if (ret) goto out_free; } cmd->device.hlid = wlvif->dev_hlid; cmd->device.session = wl->session_ids[wlvif->dev_hlid]; wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d", cmd->role_id, cmd->device.hlid, cmd->device.session); ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("failed to initiate cmd role enable"); goto err_hlid; } goto out_free; err_hlid: /* clear links on error */ wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid); out_free: kfree(cmd); out: return ret; }
/* use this function to stop ibss as well */ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct wl12xx_cmd_role_stop *cmd; int ret; bool timeout = false; if (WARN_ON(wlvif->sta.hlid == WL12XX_INVALID_LINK_ID)) return -EINVAL; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wlvif->role_id); cmd->role_id = wlvif->role_id; cmd->disc_type = DISCONNECT_IMMEDIATE; cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("failed to initiate cmd role stop sta"); goto out_free; } /* * Sometimes the firmware doesn't send this event, so we just * time out without failing. Queue recovery for other * failures. */ ret = wl1271_cmd_wait_for_event_or_timeout(wl, ROLE_STOP_COMPLETE_EVENT_ID, &timeout); if (ret) wl12xx_queue_recovery_work(wl); wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid); out_free: kfree(cmd); out: return ret; }
/** * read acx from firmware * * @wl: wl struct * @id: acx id * @buf: buffer for the response, including all headers, must work with dma * @len: lenght of buf */ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) { struct acx_header *acx = buf; int ret; wl1271_debug(DEBUG_CMD, "cmd interrogate"); acx->id = cpu_to_le16(id); /* payload length, does not include any headers */ acx->len = cpu_to_le16(len - sizeof(*acx)); ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx), len); if (ret < 0) wl1271_error("INTERROGATE command failed"); return ret; }
int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, u8 *role_id) { struct wl12xx_cmd_role_enable *cmd; int ret; wl1271_debug(DEBUG_CMD, "cmd role enable"); wl12xx_change_fw_if_needed(wl); if (WARN_ON(*role_id != WL12XX_INVALID_ROLE_ID)) return -EBUSY; cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } /* get role id */ cmd->role_id = find_first_zero_bit(wl->roles_map, WL12XX_MAX_ROLES); if (cmd->role_id >= WL12XX_MAX_ROLES) { ret = -EBUSY; goto out_free; } memcpy(cmd->mac_address, addr, ETH_ALEN); cmd->role_type = role_type; ret = wl1271_cmd_send(wl, CMD_ROLE_ENABLE, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_error("failed to initiate cmd role enable"); goto out_free; } __set_bit(cmd->role_id, wl->roles_map); *role_id = cmd->role_id; out_free: kfree(cmd); out: return ret; }
int wl1271_cmd_template_set(struct wl1271 *wl, u8 role_id, u16 template_id, void *buf, size_t buf_len, int index, u32 rates) { struct wl1271_cmd_template_set *cmd; int ret = 0; wl1271_debug(DEBUG_CMD, "cmd template_set %d (role %d)", template_id, role_id); WARN_ON(buf_len > WL1271_CMD_TEMPL_MAX_SIZE); buf_len = min_t(size_t, buf_len, WL1271_CMD_TEMPL_MAX_SIZE); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) { ret = -ENOMEM; goto out; } /* during initialization wlvif is NULL */ cmd->role_id = role_id; cmd->len = cpu_to_le16(buf_len); cmd->template_type = template_id; cmd->enabled_rates = cpu_to_le32(rates); cmd->short_retry_limit = wl->conf.tx.tmpl_short_retry_limit; cmd->long_retry_limit = wl->conf.tx.tmpl_long_retry_limit; cmd->index = index; if (buf) memcpy(cmd->template_data, buf, buf_len); ret = wl1271_cmd_send(wl, CMD_SET_TEMPLATE, cmd, sizeof(*cmd), 0); if (ret < 0) { wl1271_warning("cmd set_template failed: %d", ret); goto out_free; } out_free: kfree(cmd); out: return ret; }
/** * send test command to firmware * * @wl: wl struct * @buf: buffer containing the command, with all headers, must work with dma * @len: length of the buffer * @answer: is answer needed */ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer) { int ret; size_t res_len = 0; wl1271_debug(DEBUG_CMD, "cmd test"); if (answer) res_len = buf_len; ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len, res_len); if (ret < 0) { wl1271_warning("TEST command failed"); return ret; } return ret; }
/** * write acx value to firmware * * @wl: wl struct * @id: acx id * @buf: buffer containing acx, including all headers, must work with dma * @len: length of buf */ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) { struct acx_header *acx = buf; int ret; wl1271_debug(DEBUG_CMD, "cmd configure"); acx->id = cpu_to_le16(id); /* payload length, does not include any headers */ acx->len = cpu_to_le16(len - sizeof(*acx)); ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len, 0); if (ret < 0) { wl1271_warning("CONFIGURE command NOK"); return ret; } return 0; }