ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else {
+ struct iwl_rxon_context *tmp;
/* Initialize our rx_config data */
- iwl_connection_init_rx_config(priv, NULL);
+ for_each_context(priv, tmp)
+ iwl_connection_init_rx_config(priv, tmp);
if (priv->cfg->ops->hcmd->set_rxon_chain)
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
{
int ret;
struct ieee80211_hw *hw = priv->hw;
+ struct iwl_rxon_context *ctx;
+
hw->rate_control_algorithm = "iwl-agn-rs";
/* Tell mac80211 our characteristics */
hw->sta_data_size = sizeof(struct iwl_station_priv);
hw->vif_data_size = sizeof(struct iwl_vif_priv);
- hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC);
+ for_each_context(priv, ctx) {
+ hw->wiphy->interface_modes |= ctx->interface_modes;
+ hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
+ }
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
WIPHY_FLAG_DISABLE_BEACON_HINTS;
priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo;
priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue;
+ priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
+ BIT(NL80211_IFTYPE_ADHOC);
+ priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
+ BIT(NL80211_IFTYPE_STATION);
+ priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
+ priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
+ priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd = REPLY_WIPAN_RXON_TIMING;
priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo;
priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue;
priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE;
+ priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
+ BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
+ priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
+ priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
+ priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
* initialize rxon structure with default values from eeprom
*/
void iwl_connection_init_rx_config(struct iwl_priv *priv,
- struct ieee80211_vif *vif)
+ struct iwl_rxon_context *ctx)
{
const struct iwl_channel_info *ch_info;
- enum nl80211_iftype type = NL80211_IFTYPE_STATION;
- struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
- if (vif) {
- type = vif->type;
- ctx = iwl_rxon_ctx_from_vif(vif);
- }
memset(&ctx->staging, 0, sizeof(ctx->staging));
- switch (type) {
+ if (!ctx->vif) {
+ ctx->staging.dev_type = ctx->unused_devtype;
+ } else switch (ctx->vif->type) {
case NL80211_IFTYPE_AP:
- ctx->staging.dev_type = RXON_DEV_TYPE_AP;
+ ctx->staging.dev_type = ctx->ap_devtype;
break;
case NL80211_IFTYPE_STATION:
- ctx->staging.dev_type = RXON_DEV_TYPE_ESS;
+ ctx->staging.dev_type = ctx->station_devtype;
ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
break;
case NL80211_IFTYPE_ADHOC:
- ctx->staging.dev_type = RXON_DEV_TYPE_IBSS;
+ ctx->staging.dev_type = ctx->ibss_devtype;
ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
RXON_FILTER_ACCEPT_GRP_MSK;
break;
default:
- IWL_ERR(priv, "Unsupported interface type %d\n", type);
+ IWL_ERR(priv, "Unsupported interface type %d\n",
+ ctx->vif->type);
break;
}
ctx->staging.channel = cpu_to_le16(ch_info->channel);
priv->band = ch_info->band;
- iwl_set_flags_for_band(priv, ctx, priv->band, vif);
+ iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
ctx->staging.ofdm_basic_rates =
(IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
/* clear both MIX and PURE40 mode flag */
ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
RXON_FLG_CHANNEL_MODE_PURE_40);
- if (vif)
- memcpy(ctx->staging.node_addr, vif->addr, ETH_ALEN);
+ if (ctx->vif)
+ memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN);
ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff;
ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff;
{
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
- iwl_connection_init_rx_config(priv, vif);
+ iwl_connection_init_rx_config(priv, ctx);
if (priv->cfg->ops->hcmd->set_rxon_chain)
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
{
struct iwl_priv *priv = hw->priv;
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
- struct iwl_rxon_context *ctx;
+ struct iwl_rxon_context *tmp, *ctx = NULL;
int err = 0;
IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
mutex_lock(&priv->mutex);
- /* For now always use this context. */
- ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
- vif_priv->ctx = ctx;
-
if (WARN_ON(!iwl_is_ready_rf(priv))) {
err = -EINVAL;
goto out;
}
- if (ctx->vif) {
- IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n");
+ for_each_context(priv, tmp) {
+ u32 possible_modes =
+ tmp->interface_modes | tmp->exclusive_interface_modes;
+
+ if (tmp->vif) {
+ /* check if this busy context is exclusive */
+ if (tmp->exclusive_interface_modes &
+ BIT(tmp->vif->type)) {
+ err = -EINVAL;
+ goto out;
+ }
+ continue;
+ }
+
+ if (!(possible_modes & BIT(vif->type)))
+ continue;
+
+ /* have maybe usable context w/o interface */
+ ctx = tmp;
+ break;
+ }
+
+ if (!ctx) {
err = -EOPNOTSUPP;
goto out;
}
+ vif_priv->ctx = ctx;
ctx->vif = vif;
+ /*
+ * This variable will be correct only when there's just
+ * a single context, but all code using it is for hardware
+ * that supports only one context.
+ */
priv->iw_mode = vif->type;
err = iwl_set_mode(priv, vif);
mutex_lock(&priv->mutex);
- if (iwl_is_ready_rf(priv)) {
- iwl_scan_cancel_timeout(priv, 100);
- ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwlcore_commit_rxon(priv, ctx);
- }
+ WARN_ON(ctx->vif != vif);
+ ctx->vif = NULL;
+
+ iwl_scan_cancel_timeout(priv, 100);
+ iwl_set_mode(priv, vif);
if (priv->scan_vif == vif) {
scan_completed = true;
if (vif->type == NL80211_IFTYPE_ADHOC)
priv->bt_traffic_load = priv->notif_bt_traffic_load;
- WARN_ON(ctx->vif != vif);
- ctx->vif = NULL;
memset(priv->bssid, 0, ETH_ALEN);
mutex_unlock(&priv->mutex);
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else {
/* Initialize our rx_config data */
- iwl_connection_init_rx_config(priv, NULL);
+ iwl_connection_init_rx_config(priv, ctx);
}
/* Configure Bluetooth device coexistence support */
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC);
+ priv->contexts[IWL_RXON_CTX_BSS].interface_modes;
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
WIPHY_FLAG_DISABLE_BEACON_HINTS;
priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
+ priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC);
+ priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
+ priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
+ priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
/*
* Disabling hardware scan means that mac80211 will perform scans