diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-08-23 04:46:58 -0400 |
---|---|---|
committer | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2010-08-27 12:49:38 -0400 |
commit | d0fe478c9f42dbc4916aa8d1d7a05d7f669d2209 (patch) | |
tree | bb710248e2298dffa76fd336a74b647947140d1f /drivers/net/wireless/iwlwifi/iwl-core.c | |
parent | bde4530e9d2fa013b5674e4c9b066ed6d87ab45c (diff) |
iwlwifi: allow using multiple contexts
We're now ready to start using multiple contexts.
We do this by keeping track of the valid interface
types per context (exclusive [ibss] and normal)
and checking which context is "free" when a new
interface is added.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-core.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 80 |
1 files changed, 48 insertions, 32 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index a2b39fd4081e..87a2e40972ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -1028,38 +1028,34 @@ EXPORT_SYMBOL(iwl_set_flags_for_band); | |||
1028 | * initialize rxon structure with default values from eeprom | 1028 | * initialize rxon structure with default values from eeprom |
1029 | */ | 1029 | */ |
1030 | void iwl_connection_init_rx_config(struct iwl_priv *priv, | 1030 | void iwl_connection_init_rx_config(struct iwl_priv *priv, |
1031 | struct ieee80211_vif *vif) | 1031 | struct iwl_rxon_context *ctx) |
1032 | { | 1032 | { |
1033 | const struct iwl_channel_info *ch_info; | 1033 | const struct iwl_channel_info *ch_info; |
1034 | enum nl80211_iftype type = NL80211_IFTYPE_STATION; | ||
1035 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
1036 | |||
1037 | if (vif) { | ||
1038 | type = vif->type; | ||
1039 | ctx = iwl_rxon_ctx_from_vif(vif); | ||
1040 | } | ||
1041 | 1034 | ||
1042 | memset(&ctx->staging, 0, sizeof(ctx->staging)); | 1035 | memset(&ctx->staging, 0, sizeof(ctx->staging)); |
1043 | 1036 | ||
1044 | switch (type) { | 1037 | if (!ctx->vif) { |
1038 | ctx->staging.dev_type = ctx->unused_devtype; | ||
1039 | } else switch (ctx->vif->type) { | ||
1045 | case NL80211_IFTYPE_AP: | 1040 | case NL80211_IFTYPE_AP: |
1046 | ctx->staging.dev_type = RXON_DEV_TYPE_AP; | 1041 | ctx->staging.dev_type = ctx->ap_devtype; |
1047 | break; | 1042 | break; |
1048 | 1043 | ||
1049 | case NL80211_IFTYPE_STATION: | 1044 | case NL80211_IFTYPE_STATION: |
1050 | ctx->staging.dev_type = RXON_DEV_TYPE_ESS; | 1045 | ctx->staging.dev_type = ctx->station_devtype; |
1051 | ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; | 1046 | ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; |
1052 | break; | 1047 | break; |
1053 | 1048 | ||
1054 | case NL80211_IFTYPE_ADHOC: | 1049 | case NL80211_IFTYPE_ADHOC: |
1055 | ctx->staging.dev_type = RXON_DEV_TYPE_IBSS; | 1050 | ctx->staging.dev_type = ctx->ibss_devtype; |
1056 | ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; | 1051 | ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; |
1057 | ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | | 1052 | ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | |
1058 | RXON_FILTER_ACCEPT_GRP_MSK; | 1053 | RXON_FILTER_ACCEPT_GRP_MSK; |
1059 | break; | 1054 | break; |
1060 | 1055 | ||
1061 | default: | 1056 | default: |
1062 | IWL_ERR(priv, "Unsupported interface type %d\n", type); | 1057 | IWL_ERR(priv, "Unsupported interface type %d\n", |
1058 | ctx->vif->type); | ||
1063 | break; | 1059 | break; |
1064 | } | 1060 | } |
1065 | 1061 | ||
@@ -1081,7 +1077,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, | |||
1081 | ctx->staging.channel = cpu_to_le16(ch_info->channel); | 1077 | ctx->staging.channel = cpu_to_le16(ch_info->channel); |
1082 | priv->band = ch_info->band; | 1078 | priv->band = ch_info->band; |
1083 | 1079 | ||
1084 | iwl_set_flags_for_band(priv, ctx, priv->band, vif); | 1080 | iwl_set_flags_for_band(priv, ctx, priv->band, ctx->vif); |
1085 | 1081 | ||
1086 | ctx->staging.ofdm_basic_rates = | 1082 | ctx->staging.ofdm_basic_rates = |
1087 | (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; | 1083 | (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; |
@@ -1091,8 +1087,8 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, | |||
1091 | /* clear both MIX and PURE40 mode flag */ | 1087 | /* clear both MIX and PURE40 mode flag */ |
1092 | ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | | 1088 | ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | |
1093 | RXON_FLG_CHANNEL_MODE_PURE_40); | 1089 | RXON_FLG_CHANNEL_MODE_PURE_40); |
1094 | if (vif) | 1090 | if (ctx->vif) |
1095 | memcpy(ctx->staging.node_addr, vif->addr, ETH_ALEN); | 1091 | memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN); |
1096 | 1092 | ||
1097 | ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff; | 1093 | ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff; |
1098 | ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff; | 1094 | ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff; |
@@ -1952,7 +1948,7 @@ static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
1952 | { | 1948 | { |
1953 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); | 1949 | struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); |
1954 | 1950 | ||
1955 | iwl_connection_init_rx_config(priv, vif); | 1951 | iwl_connection_init_rx_config(priv, ctx); |
1956 | 1952 | ||
1957 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 1953 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
1958 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); | 1954 | priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx); |
@@ -1964,7 +1960,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
1964 | { | 1960 | { |
1965 | struct iwl_priv *priv = hw->priv; | 1961 | struct iwl_priv *priv = hw->priv; |
1966 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; | 1962 | struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; |
1967 | struct iwl_rxon_context *ctx; | 1963 | struct iwl_rxon_context *tmp, *ctx = NULL; |
1968 | int err = 0; | 1964 | int err = 0; |
1969 | 1965 | ||
1970 | IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", | 1966 | IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", |
@@ -1972,23 +1968,45 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
1972 | 1968 | ||
1973 | mutex_lock(&priv->mutex); | 1969 | mutex_lock(&priv->mutex); |
1974 | 1970 | ||
1975 | /* For now always use this context. */ | ||
1976 | ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
1977 | |||
1978 | vif_priv->ctx = ctx; | ||
1979 | |||
1980 | if (WARN_ON(!iwl_is_ready_rf(priv))) { | 1971 | if (WARN_ON(!iwl_is_ready_rf(priv))) { |
1981 | err = -EINVAL; | 1972 | err = -EINVAL; |
1982 | goto out; | 1973 | goto out; |
1983 | } | 1974 | } |
1984 | 1975 | ||
1985 | if (ctx->vif) { | 1976 | for_each_context(priv, tmp) { |
1986 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); | 1977 | u32 possible_modes = |
1978 | tmp->interface_modes | tmp->exclusive_interface_modes; | ||
1979 | |||
1980 | if (tmp->vif) { | ||
1981 | /* check if this busy context is exclusive */ | ||
1982 | if (tmp->exclusive_interface_modes & | ||
1983 | BIT(tmp->vif->type)) { | ||
1984 | err = -EINVAL; | ||
1985 | goto out; | ||
1986 | } | ||
1987 | continue; | ||
1988 | } | ||
1989 | |||
1990 | if (!(possible_modes & BIT(vif->type))) | ||
1991 | continue; | ||
1992 | |||
1993 | /* have maybe usable context w/o interface */ | ||
1994 | ctx = tmp; | ||
1995 | break; | ||
1996 | } | ||
1997 | |||
1998 | if (!ctx) { | ||
1987 | err = -EOPNOTSUPP; | 1999 | err = -EOPNOTSUPP; |
1988 | goto out; | 2000 | goto out; |
1989 | } | 2001 | } |
1990 | 2002 | ||
2003 | vif_priv->ctx = ctx; | ||
1991 | ctx->vif = vif; | 2004 | ctx->vif = vif; |
2005 | /* | ||
2006 | * This variable will be correct only when there's just | ||
2007 | * a single context, but all code using it is for hardware | ||
2008 | * that supports only one context. | ||
2009 | */ | ||
1992 | priv->iw_mode = vif->type; | 2010 | priv->iw_mode = vif->type; |
1993 | 2011 | ||
1994 | err = iwl_set_mode(priv, vif); | 2012 | err = iwl_set_mode(priv, vif); |
@@ -2029,11 +2047,11 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2029 | 2047 | ||
2030 | mutex_lock(&priv->mutex); | 2048 | mutex_lock(&priv->mutex); |
2031 | 2049 | ||
2032 | if (iwl_is_ready_rf(priv)) { | 2050 | WARN_ON(ctx->vif != vif); |
2033 | iwl_scan_cancel_timeout(priv, 100); | 2051 | ctx->vif = NULL; |
2034 | ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2052 | |
2035 | iwlcore_commit_rxon(priv, ctx); | 2053 | iwl_scan_cancel_timeout(priv, 100); |
2036 | } | 2054 | iwl_set_mode(priv, vif); |
2037 | 2055 | ||
2038 | if (priv->scan_vif == vif) { | 2056 | if (priv->scan_vif == vif) { |
2039 | scan_completed = true; | 2057 | scan_completed = true; |
@@ -2051,8 +2069,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2051 | if (vif->type == NL80211_IFTYPE_ADHOC) | 2069 | if (vif->type == NL80211_IFTYPE_ADHOC) |
2052 | priv->bt_traffic_load = priv->notif_bt_traffic_load; | 2070 | priv->bt_traffic_load = priv->notif_bt_traffic_load; |
2053 | 2071 | ||
2054 | WARN_ON(ctx->vif != vif); | ||
2055 | ctx->vif = NULL; | ||
2056 | memset(priv->bssid, 0, ETH_ALEN); | 2072 | memset(priv->bssid, 0, ETH_ALEN); |
2057 | mutex_unlock(&priv->mutex); | 2073 | mutex_unlock(&priv->mutex); |
2058 | 2074 | ||