static int iwl_send_phy_db_cmd(struct iwl_phy_db *phy_db, u16 type, u16 length, void *data) { struct iwl_phy_db_cmd phy_db_cmd; struct iwl_host_cmd cmd = { .id = PHY_DB_CMD, }; IWL_DEBUG_INFO(phy_db->trans, "Sending PHY-DB hcmd of type %d, of length %d\n", type, length); /* Set phy db cmd variables */ phy_db_cmd.type = cpu_to_le16(type); phy_db_cmd.length = cpu_to_le16(length); /* Set hcmd variables */ cmd.data[0] = &phy_db_cmd; cmd.len[0] = sizeof(struct iwl_phy_db_cmd); cmd.data[1] = data; cmd.len[1] = length; cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; return iwl_trans_send_cmd(phy_db->trans, &cmd); }
/* * Will return 0 even if the cmd failed when RFKILL is asserted unless * CMD_WANT_SKB is set in cmd->flags. */ int iwl_mvm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd) { int ret; #if defined(CONFIG_IWLWIFI_DEBUGFS) && defined(CONFIG_PM_SLEEP) if (WARN_ON(mvm->d3_test_active)) return -EIO; #endif /* * Synchronous commands from this op-mode must hold * the mutex, this ensures we don't try to send two * (or more) synchronous commands at a time. */ if (!(cmd->flags & CMD_ASYNC)) lockdep_assert_held(&mvm->mutex); ret = iwl_trans_send_cmd(mvm->trans, cmd); /* * If the caller wants the SKB, then don't hide any problems, the * caller might access the response buffer which will be NULL if * the command failed. */ if (cmd->flags & CMD_WANT_SKB) return ret; /* Silently ignore failures if RFKILL is asserted */ if (!ret || ret == -ERFKILL) return 0; return ret; }
static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, bool send_if_empty) { int i, not_empty = 0; u8 buff[sizeof(struct iwl_wep_cmd) + sizeof(struct iwl_wep_key) * WEP_KEYS_MAX]; struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff; size_t cmd_size = sizeof(struct iwl_wep_cmd); struct iwl_host_cmd cmd = { .id = ctx->wep_key_cmd, .data = { wep_cmd, }, .flags = CMD_SYNC, }; might_sleep(); memset(wep_cmd, 0, cmd_size + (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX)); for (i = 0; i < WEP_KEYS_MAX ; i++) { wep_cmd->key[i].key_index = i; if (ctx->wep_keys[i].key_size) { wep_cmd->key[i].key_offset = i; not_empty = 1; } else { wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET; } wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size; memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key, ctx->wep_keys[i].key_size); } wep_cmd->global_key_type = WEP_KEY_WEP_TYPE; wep_cmd->num_keys = WEP_KEYS_MAX; cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX; cmd.len[0] = cmd_size; if (not_empty || send_if_empty) return iwl_trans_send_cmd(trans(priv), &cmd); else return 0; } int iwl_restore_default_wep_keys(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { lockdep_assert_held(&priv->shrd->mutex); return iwl_send_static_wepkey_cmd(priv, ctx, false); }
/* * This function handles the user application commands to the ucode. * * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_CMD_ID and * IWL_TM_ATTR_UCODE_CMD_DATA and calls to the handler to send the * host command to the ucode. * * If any mandatory field is missing, -ENOMSG is replied to the user space * application; otherwise, the actual execution result of the host command to * ucode is replied. * * @hw: ieee80211_hw object that represents the device * @tb: gnl message fields from the user space */ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) { struct iwl_priv *priv = hw->priv; struct iwl_host_cmd cmd; memset(&cmd, 0, sizeof(struct iwl_host_cmd)); if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] || !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) { IWL_DEBUG_INFO(priv, "Error finding ucode command mandatory fields\n"); return -ENOMSG; } cmd.flags = CMD_ON_DEMAND; cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); cmd.data[0] = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); cmd.len[0] = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," " len %d\n", cmd.id, cmd.flags, cmd.len[0]); /* ok, let's submit the command to ucode */ return iwl_trans_send_cmd(trans(priv), &cmd); }
int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags) { int ret = 0; u8 data[sizeof(*sta)]; struct iwl_host_cmd cmd = { .id = REPLY_ADD_STA, .flags = flags, .data = { data, }, }; u8 sta_id __maybe_unused = sta->sta.sta_id; IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n", sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); if (!(flags & CMD_ASYNC)) { cmd.flags |= CMD_WANT_SKB; might_sleep(); } cmd.len[0] = iwlagn_build_addsta_hcmd(sta, data); ret = iwl_trans_send_cmd(trans(priv), &cmd); if (ret || (flags & CMD_ASYNC)) return ret; /*else the command was successfully sent in SYNC mode, need to free * the reply page */ iwl_free_pages(priv->shrd, cmd.reply_page); if (cmd.handler_status) IWL_ERR(priv, "%s - error in the CMD response %d", __func__, cmd.handler_status); return cmd.handler_status; }
static int iwl_send_scan_abort(struct iwl_priv *priv) { int ret; struct iwl_rx_packet *pkt; struct iwl_host_cmd cmd = { .id = REPLY_SCAN_ABORT_CMD, .flags = CMD_SYNC | CMD_WANT_SKB, }; /* Exit instantly with error when device is not ready * to receive scan abort command or it does not perform * hardware scan currently */ if (!test_bit(STATUS_READY, &priv->shrd->status) || !test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) || !test_bit(STATUS_SCAN_HW, &priv->shrd->status) || test_bit(STATUS_FW_ERROR, &priv->shrd->status) || test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) return -EIO; ret = iwl_trans_send_cmd(trans(priv), &cmd); if (ret) return ret; pkt = (struct iwl_rx_packet *)cmd.reply_page; if (pkt->u.status != CAN_ABORT_STATUS) { /* The scan abort will return 1 for success or * 2 for "failure". A failure condition can be * due to simply not being in an active scan which * can occur if we send the scan abort before we * the microcode has notified us that a scan is * completed. */ IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status); ret = -EIO; } iwl_free_pages(priv->shrd, cmd.reply_page); return ret; } static void iwl_complete_scan(struct iwl_priv *priv, bool aborted) { /* check if scan was requested from mac80211 */ if (priv->scan_request) { IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n"); ieee80211_scan_completed(priv->hw, aborted); } if (priv->scan_type == IWL_SCAN_ROC) { ieee80211_remain_on_channel_expired(priv->hw); priv->hw_roc_channel = NULL; schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); } priv->scan_type = IWL_SCAN_NORMAL; priv->scan_vif = NULL; priv->scan_request = NULL; } static void iwl_process_scan_complete(struct iwl_priv *priv) { bool aborted; lockdep_assert_held(&priv->shrd->mutex); if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status)) return; IWL_DEBUG_SCAN(priv, "Completed scan.\n"); cancel_delayed_work(&priv->scan_check); aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status); if (aborted) IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n"); if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) { IWL_DEBUG_SCAN(priv, "Scan already completed.\n"); goto out_settings; } if (priv->scan_type == IWL_SCAN_ROC) { ieee80211_remain_on_channel_expired(priv->hw); priv->hw_roc_channel = NULL; schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ); } if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { int err; /* Check if mac80211 requested scan during our internal scan */ if (priv->scan_request == NULL) goto out_complete; /* If so request a new scan */ err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL, priv->scan_request->channels[0]->band); if (err) { IWL_DEBUG_SCAN(priv, "failed to initiate pending scan: %d\n", err); aborted = true; goto out_complete; } return; } out_complete: iwl_complete_scan(priv, aborted); out_settings: /* Can we still talk to firmware ? */ if (!iwl_is_ready_rf(priv->shrd)) return; iwlagn_post_scan(priv); }
struct iwl_rem_sta_cmd rm_sta_cmd; struct iwl_host_cmd cmd = { .id = REPLY_REMOVE_STA, .len = { sizeof(struct iwl_rem_sta_cmd), }, .flags = CMD_SYNC, .data = { &rm_sta_cmd, }, }; memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); rm_sta_cmd.num_sta = 1; memcpy(&rm_sta_cmd.addr, addr, ETH_ALEN); cmd.flags |= CMD_WANT_SKB; ret = iwl_trans_send_cmd(trans(priv), &cmd); if (ret) return ret; pkt = (struct iwl_rx_packet *)cmd.reply_page; if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", pkt->hdr.flags); ret = -EIO; } if (!ret) { switch (pkt->u.rem_sta.status) { case REM_STA_SUCCESS_MSK: if (!temporary) {