static void iwlagn_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { int ret; if (!ctx->is_active) return; ctx->qos_data.def_qos_parm.qos_flags = 0; if (ctx->qos_data.qos_active) ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_UPDATE_EDCA_MSK; if (ctx->ht.enabled) ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", ctx->qos_data.qos_active, ctx->qos_data.def_qos_parm.qos_flags); ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->qos_cmd, CMD_SYNC, sizeof(struct iwl_qosparam_cmd), &ctx->qos_data.def_qos_parm); if (ret) IWL_ERR(priv, "Failed to update QoS\n"); }
static int iwlagn_disable_pan(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_rxon_cmd *send) { struct iwl_notification_wait disable_wait; __le32 old_filter = send->filter_flags; u8 old_dev_type = send->dev_type; int ret; iwlagn_init_notification_wait(priv, &disable_wait, REPLY_WIPAN_DEACTIVATION_COMPLETE, NULL, NULL); send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->dev_type = RXON_DEV_TYPE_P2P; ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; send->dev_type = old_dev_type; if (ret) { IWL_ERR(priv, "Error disabling PAN (%d)\n", ret); iwlagn_remove_notification(priv, &disable_wait); } else { ret = iwlagn_wait_notification(priv, &disable_wait, HZ); if (ret) IWL_ERR(priv, "Timed out waiting for PAN disable\n"); } return ret; }
static int iwlagn_disconn_pan(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_rxon_cmd *send) { __le32 old_filter = send->filter_flags; int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; return ret; }
static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) { IWL_DEBUG_POWER(priv, "Sending power/sleep command\n"); IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags); IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); IWL_DEBUG_POWER(priv, "Sleep interval vector = { %d , %d , %d , %d , %d }\n", le32_to_cpu(cmd->sleep_interval[0]), le32_to_cpu(cmd->sleep_interval[1]), le32_to_cpu(cmd->sleep_interval[2]), le32_to_cpu(cmd->sleep_interval[3]), le32_to_cpu(cmd->sleep_interval[4])); return iwl_trans_send_cmd_pdu(trans(priv), POWER_TABLE_CMD, CMD_SYNC, sizeof(struct iwl_powertable_cmd), cmd); }
static int iwlagn_disable_bss(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_rxon_cmd *send) { __le32 old_filter = send->filter_flags; int ret; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, sizeof(*send), send); send->filter_flags = old_filter; if (ret) IWL_ERR(priv, "Error clearing ASSOC_MSK on BSS (%d)\n", ret); return ret; }
static int iwlagn_send_rxon_assoc(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { int ret = 0; struct iwl_rxon_assoc_cmd rxon_assoc; const struct iwl_rxon_cmd *rxon1 = &ctx->staging; const struct iwl_rxon_cmd *rxon2 = &ctx->active; if ((rxon1->flags == rxon2->flags) && (rxon1->filter_flags == rxon2->filter_flags) && (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && (rxon1->ofdm_ht_single_stream_basic_rates == rxon2->ofdm_ht_single_stream_basic_rates) && (rxon1->ofdm_ht_dual_stream_basic_rates == rxon2->ofdm_ht_dual_stream_basic_rates) && (rxon1->ofdm_ht_triple_stream_basic_rates == rxon2->ofdm_ht_triple_stream_basic_rates) && (rxon1->acquisition_data == rxon2->acquisition_data) && (rxon1->rx_chain == rxon2->rx_chain) && (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); return 0; } rxon_assoc.flags = ctx->staging.flags; rxon_assoc.filter_flags = ctx->staging.filter_flags; rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates; rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates; rxon_assoc.reserved1 = 0; rxon_assoc.reserved2 = 0; rxon_assoc.reserved3 = 0; rxon_assoc.ofdm_ht_single_stream_basic_rates = ctx->staging.ofdm_ht_single_stream_basic_rates; rxon_assoc.ofdm_ht_dual_stream_basic_rates = ctx->staging.ofdm_ht_dual_stream_basic_rates; rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain; rxon_assoc.ofdm_ht_triple_stream_basic_rates = ctx->staging.ofdm_ht_triple_stream_basic_rates; rxon_assoc.acquisition_data = ctx->staging.acquisition_data; ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_assoc_cmd, CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc); return ret; }
int iwlagn_send_tx_power(struct iwl_priv *priv) { struct iwlagn_tx_power_dbm_cmd tx_power_cmd; u8 tx_ant_cfg_cmd; if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->shrd->status), "TX Power requested while scanning!\n")) return -EAGAIN; /* half dBm need to multiply */ tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); if (priv->tx_power_lmt_in_half_dbm && priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { /* * For the newer devices which using enhanced/extend tx power * table in EEPROM, the format is in half dBm. driver need to * convert to dBm format before report to mac80211. * By doing so, there is a possibility of 1/2 dBm resolution * lost. driver will perform "round-up" operation before * reporting, but it will cause 1/2 dBm tx power over the * regulatory limit. Perform the checking here, if the * "tx_power_user_lmt" is higher than EEPROM value (in * half-dBm format), lower the tx power based on EEPROM */ tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; } tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED; tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO; if (IWL_UCODE_API(priv->ucode_ver) == 1) tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; else tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; return iwl_trans_send_cmd_pdu(trans(priv), tx_ant_cfg_cmd, CMD_SYNC, sizeof(tx_power_cmd), &tx_power_cmd); }
static int iwlagn_rxon_connect(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { int ret; struct iwl_rxon_cmd *active = (void *)&ctx->active; /* RXON timing must be before associated RXON */ if (ctx->ctxid == IWL_RXON_CTX_BSS) { ret = iwl_send_rxon_timing(priv, ctx); if (ret) { IWL_ERR(priv, "Failed to send timing (%d)!\n", ret); return ret; } } /* QoS info may be cleared by previous un-assoc RXON */ iwlagn_update_qos(priv, ctx); /* * We'll run into this code path when beaconing is * enabled, but then we also need to send the beacon * to the device. */ if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) { ret = iwlagn_update_beacon(priv, ctx->vif); if (ret) { IWL_ERR(priv, "Error sending required beacon (%d)!\n", ret); return ret; } } priv->start_calib = 0; /* * Apply the new configuration. * * Associated RXON doesn't clear the station table in uCode, * so we don't need to restore stations etc. after this. */ ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC, sizeof(struct iwl_rxon_cmd), &ctx->staging); if (ret) { IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); return ret; } memcpy(active, &ctx->staging, sizeof(*active)); iwl_reprogram_ap_sta(priv, ctx); /* IBSS beacon needs to be sent after setting assoc */ if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC)) if (iwlagn_update_beacon(priv, ctx->vif)) IWL_ERR(priv, "Error sending IBSS beacon\n"); iwl_init_sensitivity(priv); /* * If we issue a new RXON command which required a tune then * we must send a new TXPOWER command or we won't be able to * Tx any frames. * * It's expected we set power here if channel is changing. */ ret = iwl_set_tx_power(priv, priv->tx_power_next, true); if (ret) { IWL_ERR(priv, "Error sending TX power (%d)\n", ret); return ret; } if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION && priv->cfg->ht_params && priv->cfg->ht_params->smps_mode) ieee80211_request_smps(ctx->vif, priv->cfg->ht_params->smps_mode); return 0; }
int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { u64 tsf; s32 interval_tm, rem; struct ieee80211_conf *conf = NULL; u16 beacon_int; struct ieee80211_vif *vif = ctx->vif; conf = &priv->hw->conf; lockdep_assert_held(&priv->shrd->mutex); memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd)); ctx->timing.timestamp = cpu_to_le64(priv->timestamp); ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval); beacon_int = vif ? vif->bss_conf.beacon_int : 0; /* * TODO: For IBSS we need to get atim_window from mac80211, * for now just always use 0 */ ctx->timing.atim_window = 0; if (ctx->ctxid == IWL_RXON_CTX_PAN && (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION) && iwl_is_associated(priv, IWL_RXON_CTX_BSS) && priv->contexts[IWL_RXON_CTX_BSS].vif && priv->contexts[IWL_RXON_CTX_BSS].vif->bss_conf.beacon_int) { ctx->timing.beacon_interval = priv->contexts[IWL_RXON_CTX_BSS].timing.beacon_interval; beacon_int = le16_to_cpu(ctx->timing.beacon_interval); } else if (ctx->ctxid == IWL_RXON_CTX_BSS && iwl_is_associated(priv, IWL_RXON_CTX_PAN) && priv->contexts[IWL_RXON_CTX_PAN].vif && priv->contexts[IWL_RXON_CTX_PAN].vif->bss_conf.beacon_int && (!iwl_is_associated_ctx(ctx) || !ctx->vif || !ctx->vif->bss_conf.beacon_int)) { ctx->timing.beacon_interval = priv->contexts[IWL_RXON_CTX_PAN].timing.beacon_interval; beacon_int = le16_to_cpu(ctx->timing.beacon_interval); } else { beacon_int = iwl_adjust_beacon_interval(beacon_int, IWL_MAX_UCODE_BEACON_INTERVAL * TIME_UNIT); ctx->timing.beacon_interval = cpu_to_le16(beacon_int); } ctx->beacon_int = beacon_int; tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ interval_tm = beacon_int * TIME_UNIT; rem = do_div(tsf, interval_tm); ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem); ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ?: 1) : 1; IWL_DEBUG_ASSOC(priv, "beacon interval %d beacon timer %d beacon tim %d\n", le16_to_cpu(ctx->timing.beacon_interval), le32_to_cpu(ctx->timing.beacon_init_val), le16_to_cpu(ctx->timing.atim_window)); return iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_timing_cmd, CMD_SYNC, sizeof(ctx->timing), &ctx->timing); }