Fixes ipw2100 and ipw2200 after changes of modulations and rates definitions. As the ieee80211 code is very ipw2200-specific, breaking this tight binding is a pain and require many things in ipw2200 to be changed. This patch is just a quick fix, both ipw drivers need to be rewritten later. In particular, a/b/g mode selection probably doesn't work very well - it needs to be connected with rates selection (ie. selecting "g mode only" should be implemented as selecting bg mode and g-specific speeds only). Signed-off-by: Jiri Benc Signed-off-by: Jirka Bohac Index: netdev/drivers/net/wireless/ipw2100.c =================================================================== --- netdev.orig/drivers/net/wireless/ipw2100.c 2005-09-17 14:52:37.000000000 +0200 +++ netdev/drivers/net/wireless/ipw2100.c 2005-09-17 15:06:10.000000000 +0200 @@ -2560,7 +2560,7 @@ static inline void __ipw2100_rx_process( stats.mask = 0; if (stats.rssi != 0) stats.mask |= IEEE80211_STATMASK_RSSI; - stats.freq = IEEE80211_24GHZ_BAND; + stats.modulation = IEEE80211_DSSS_MODULATION; IPW_DEBUG_RX( "%s: '%s' frame type received (%d).\n", @@ -6335,6 +6335,10 @@ static struct net_device *ipw2100_alloc_ if (!ieee) return NULL; ieee->config &= ~IEEE80211_CFG_COMPUTE_FCS; + ieee->supported_modulations = ieee->modulations = + IEEE80211_B_MANDATORY_MODULATIONS; + ieee->supported_rates = ieee->rates = + IEEE80211_DSSS_RATES_MASK; dev = ieee80211_dev(ieee); priv = ieee80211_priv(ieee); priv->ieee = ieee; Index: netdev/drivers/net/wireless/ipw2200.h =================================================================== --- netdev.orig/drivers/net/wireless/ipw2200.h 2005-09-07 11:20:19.000000000 +0200 +++ netdev/drivers/net/wireless/ipw2200.h 2005-09-17 15:06:10.000000000 +0200 @@ -157,6 +157,41 @@ enum connection_manager_assoc_states { #define IPW_B_MODE 1 #define IPW_G_MODE 2 +#define IPW_CCK_RATE_1MB_MASK (1<<0) +#define IPW_CCK_RATE_2MB_MASK (1<<1) +#define IPW_CCK_RATE_5MB_MASK (1<<2) +#define IPW_CCK_RATE_11MB_MASK (1<<3) +#define IPW_OFDM_RATE_6MB_MASK (1<<4) +#define IPW_OFDM_RATE_9MB_MASK (1<<5) +#define IPW_OFDM_RATE_12MB_MASK (1<<6) +#define IPW_OFDM_RATE_18MB_MASK (1<<7) +#define IPW_OFDM_RATE_24MB_MASK (1<<8) +#define IPW_OFDM_RATE_36MB_MASK (1<<9) +#define IPW_OFDM_RATE_48MB_MASK (1<<10) +#define IPW_OFDM_RATE_54MB_MASK (1<<11) + +#define IPW_CCK_RATES_MASK 0x0000000F +#define IPW_CCK_BASIC_RATES_MASK (IPW_CCK_RATE_1MB_MASK | \ + IPW_CCK_RATE_2MB_MASK) +#define IPW_CCK_DEFAULT_RATES_MASK (IPW_CCK_BASIC_RATES_MASK | \ + IPW_CCK_RATE_5MB_MASK | \ + IPW_CCK_RATE_11MB_MASK) + +#define IPW_OFDM_RATES_MASK 0x00000FF0 +#define IPW_OFDM_BASIC_RATES_MASK (IPW_OFDM_RATE_6MB_MASK | \ + IPW_OFDM_RATE_12MB_MASK | \ + IPW_OFDM_RATE_24MB_MASK) +#define IPW_OFDM_DEFAULT_RATES_MASK (IPW_OFDM_BASIC_RATES_MASK | \ + IPW_OFDM_RATE_9MB_MASK | \ + IPW_OFDM_RATE_18MB_MASK | \ + IPW_OFDM_RATE_36MB_MASK | \ + IPW_OFDM_RATE_48MB_MASK | \ + IPW_OFDM_RATE_54MB_MASK) +#define IPW_DEFAULT_RATES_MASK (IPW_OFDM_DEFAULT_RATES_MASK | \ + IPW_CCK_DEFAULT_RATES_MASK) + +#define IPW_OFDM_SHIFT_MASK_A 4 + /* * TX Queue Flag Definitions */ Index: netdev/drivers/net/wireless/ipw2200.c =================================================================== --- netdev.orig/drivers/net/wireless/ipw2200.c 2005-09-17 14:52:37.000000000 +0200 +++ netdev/drivers/net/wireless/ipw2200.c 2005-09-17 15:09:21.000000000 +0200 @@ -82,24 +82,24 @@ static u8 band_a_active_channel[MAX_A_CH 36, 40, 44, 48, 149, 153, 157, 161, 165, 52, 56, 60, 64, 0 }; -static int is_valid_channel(int mode_mask, int channel) +static int is_valid_channel(int modulations, int channel) { int i; if (!channel) - return 0; + return -1; - if (mode_mask & IEEE_A) + if (modulations & IEEE80211_A_MODULATIONS) for (i = 0; i < MAX_A_CHANNELS; i++) if (band_a_active_channel[i] == channel) - return IEEE_A; + return IEEE80211_OFDM_MODULATION_MASK; - if (mode_mask & (IEEE_B | IEEE_G)) + if (modulations & IEEE80211_G_MODULATIONS) for (i = 0; i < MAX_B_CHANNELS; i++) if (band_b_active_channel[i] == channel) - return mode_mask & (IEEE_B | IEEE_G); + return modulations & IEEE80211_G_MODULATIONS; - return 0; + return -1; } static char *snprint_line(char *buf, size_t count, @@ -3068,7 +3068,7 @@ static inline u32 ipw_get_max_rate(struc /* If currently associated in B mode, restrict the maximum * rate match to B rates */ if (priv->assoc_request.ieee_mode == IPW_B_MODE) - mask &= IEEE80211_CCK_RATES_MASK; + mask &= IPW_CCK_RATES_MASK; /* TODO: Verify that the rate is supported by the current rates * list. */ @@ -3076,21 +3076,21 @@ static inline u32 ipw_get_max_rate(struc while (i && !(mask & i)) i >>= 1; switch (i) { - case IEEE80211_CCK_RATE_1MB_MASK: return 1000000; - case IEEE80211_CCK_RATE_2MB_MASK: return 2000000; - case IEEE80211_CCK_RATE_5MB_MASK: return 5500000; - case IEEE80211_OFDM_RATE_6MB_MASK: return 6000000; - case IEEE80211_OFDM_RATE_9MB_MASK: return 9000000; - case IEEE80211_CCK_RATE_11MB_MASK: return 11000000; - case IEEE80211_OFDM_RATE_12MB_MASK: return 12000000; - case IEEE80211_OFDM_RATE_18MB_MASK: return 18000000; - case IEEE80211_OFDM_RATE_24MB_MASK: return 24000000; - case IEEE80211_OFDM_RATE_36MB_MASK: return 36000000; - case IEEE80211_OFDM_RATE_48MB_MASK: return 48000000; - case IEEE80211_OFDM_RATE_54MB_MASK: return 54000000; + case IPW_CCK_RATE_1MB_MASK: return 1000000; + case IPW_CCK_RATE_2MB_MASK: return 2000000; + case IPW_CCK_RATE_5MB_MASK: return 5500000; + case IPW_OFDM_RATE_6MB_MASK: return 6000000; + case IPW_OFDM_RATE_9MB_MASK: return 9000000; + case IPW_CCK_RATE_11MB_MASK: return 11000000; + case IPW_OFDM_RATE_12MB_MASK: return 12000000; + case IPW_OFDM_RATE_18MB_MASK: return 18000000; + case IPW_OFDM_RATE_24MB_MASK: return 24000000; + case IPW_OFDM_RATE_36MB_MASK: return 36000000; + case IPW_OFDM_RATE_48MB_MASK: return 48000000; + case IPW_OFDM_RATE_54MB_MASK: return 54000000; } - if (priv->ieee->mode == IEEE_B) + if (!(priv->ieee->modulations & IEEE80211_ERP_OFDM_MODULATION_MASK)) return 11000000; else return 54000000; @@ -3132,6 +3132,33 @@ static u32 ipw_get_current_rate(struct i return 0; } +static int ipw_get_ieee80211_rate(u32 ipw_rate) +{ + switch (ipw_rate) { + case 1000000: return IEEE80211_RATE_1MB; + case 2000000: return IEEE80211_RATE_2MB; + case 5500000: return IEEE80211_RATE_5MB; + case 6000000: return IEEE80211_RATE_6MB; + case 9000000: return IEEE80211_RATE_9MB; + case 11000000: return IEEE80211_RATE_11MB; + case 12000000: return IEEE80211_RATE_12MB; + case 18000000: return IEEE80211_RATE_18MB; + case 24000000: return IEEE80211_RATE_24MB; + case 36000000: return IEEE80211_RATE_36MB; + case 48000000: return IEEE80211_RATE_48MB; + case 54000000: return IEEE80211_RATE_54MB; + } + + return -1; +} + +static int ipw_get_bg_modulation(u32 ipw_rate) +{ + if (ipw_rate == 6000000 || ipw_rate == 9000000 || ipw_rate >= 12000000) + return IEEE80211_ERP_OFDM_MODULATION; + return IEEE80211_DSSS_MODULATION; +} + #define PERFECT_RSSI (-50) #define WORST_RSSI (-85) #define IPW_STATS_INTERVAL (2 * HZ) @@ -4050,33 +4077,24 @@ static struct ipw_rx_queue *ipw_rx_queue static int ipw_is_rate_in_mask(struct ipw_priv *priv, int ieee_mode, u8 rate) { - rate &= ~IEEE80211_BASIC_RATE_MASK; - if (ieee_mode == IEEE_A) { + if (IEEE80211_A_MODE(modulations)) { switch (rate) { - case IEEE80211_OFDM_RATE_6MB: - return priv->rates_mask & IEEE80211_OFDM_RATE_6MB_MASK ? - 1 : 0; - case IEEE80211_OFDM_RATE_9MB: - return priv->rates_mask & IEEE80211_OFDM_RATE_9MB_MASK ? - 1 : 0; - case IEEE80211_OFDM_RATE_12MB: - return priv-> - rates_mask & IEEE80211_OFDM_RATE_12MB_MASK ? 1 : 0; - case IEEE80211_OFDM_RATE_18MB: - return priv-> - rates_mask & IEEE80211_OFDM_RATE_18MB_MASK ? 1 : 0; - case IEEE80211_OFDM_RATE_24MB: - return priv-> - rates_mask & IEEE80211_OFDM_RATE_24MB_MASK ? 1 : 0; - case IEEE80211_OFDM_RATE_36MB: - return priv-> - rates_mask & IEEE80211_OFDM_RATE_36MB_MASK ? 1 : 0; - case IEEE80211_OFDM_RATE_48MB: - return priv-> - rates_mask & IEEE80211_OFDM_RATE_48MB_MASK ? 1 : 0; - case IEEE80211_OFDM_RATE_54MB: - return priv-> - rates_mask & IEEE80211_OFDM_RATE_54MB_MASK ? 1 : 0; + case IEEE80211_RATE_6MB: + return priv->rates_mask & IPW_OFDM_RATE_6MB_MASK ? 1 : 0; + case IEEE80211_RATE_9MB: + return priv->rates_mask & IPW_OFDM_RATE_9MB_MASK ? 1 : 0; + case IEEE80211_RATE_12MB: + return priv->rates_mask & IPW_OFDM_RATE_12MB_MASK ? 1 : 0; + case IEEE80211_RATE_18MB: + return priv->rates_mask & IPW_OFDM_RATE_18MB_MASK ? 1 : 0; + case IEEE80211_RATE_24MB: + return priv->rates_mask & IPW_OFDM_RATE_24MB_MASK ? 1 : 0; + case IEEE80211_RATE_36MB: + return priv->rates_mask & IPW_OFDM_RATE_36MB_MASK ? 1 : 0; + case IEEE80211_RATE_48MB: + return priv->rates_mask & IPW_OFDM_RATE_48MB_MASK ? 1 : 0; + case IEEE80211_RATE_54MB: + return priv->rates_mask & IPW_OFDM_RATE_54MB_MASK ? 1 : 0; default: return 0; } @@ -4084,38 +4102,38 @@ static int ipw_is_rate_in_mask(struct ip /* B and G mixed */ switch (rate) { - case IEEE80211_CCK_RATE_1MB: - return priv->rates_mask & IEEE80211_CCK_RATE_1MB_MASK ? 1 : 0; - case IEEE80211_CCK_RATE_2MB: - return priv->rates_mask & IEEE80211_CCK_RATE_2MB_MASK ? 1 : 0; - case IEEE80211_CCK_RATE_5MB: - return priv->rates_mask & IEEE80211_CCK_RATE_5MB_MASK ? 1 : 0; - case IEEE80211_CCK_RATE_11MB: - return priv->rates_mask & IEEE80211_CCK_RATE_11MB_MASK ? 1 : 0; + case IEEE80211_RATE_1MB: + return priv->rates_mask & IPW_CCK_RATE_1MB_MASK ? 1 : 0; + case IEEE80211_RATE_2MB: + return priv->rates_mask & IPW_CCK_RATE_2MB_MASK ? 1 : 0; + case IEEE80211_RATE_5MB: + return priv->rates_mask & IPW_CCK_RATE_5MB_MASK ? 1 : 0; + case IEEE80211_RATE_11MB: + return priv->rates_mask & IPW_CCK_RATE_11MB_MASK ? 1 : 0; } /* If we are limited to B modulations, bail at this point */ - if (ieee_mode == IEEE_B) + if (!IEEE80211_G_MODE(modulations)) return 0; /* G */ switch (rate) { - case IEEE80211_OFDM_RATE_6MB: - return priv->rates_mask & IEEE80211_OFDM_RATE_6MB_MASK ? 1 : 0; - case IEEE80211_OFDM_RATE_9MB: - return priv->rates_mask & IEEE80211_OFDM_RATE_9MB_MASK ? 1 : 0; - case IEEE80211_OFDM_RATE_12MB: - return priv->rates_mask & IEEE80211_OFDM_RATE_12MB_MASK ? 1 : 0; - case IEEE80211_OFDM_RATE_18MB: - return priv->rates_mask & IEEE80211_OFDM_RATE_18MB_MASK ? 1 : 0; - case IEEE80211_OFDM_RATE_24MB: - return priv->rates_mask & IEEE80211_OFDM_RATE_24MB_MASK ? 1 : 0; - case IEEE80211_OFDM_RATE_36MB: - return priv->rates_mask & IEEE80211_OFDM_RATE_36MB_MASK ? 1 : 0; - case IEEE80211_OFDM_RATE_48MB: - return priv->rates_mask & IEEE80211_OFDM_RATE_48MB_MASK ? 1 : 0; - case IEEE80211_OFDM_RATE_54MB: - return priv->rates_mask & IEEE80211_OFDM_RATE_54MB_MASK ? 1 : 0; + case IEEE80211_RATE_6MB: + return priv->rates_mask & IPW_OFDM_RATE_6MB_MASK ? 1 : 0; + case IEEE80211_RATE_9MB: + return priv->rates_mask & IPW_OFDM_RATE_9MB_MASK ? 1 : 0; + case IEEE80211_RATE_12MB: + return priv->rates_mask & IPW_OFDM_RATE_12MB_MASK ? 1 : 0; + case IEEE80211_RATE_18MB: + return priv->rates_mask & IPW_OFDM_RATE_18MB_MASK ? 1 : 0; + case IEEE80211_RATE_24MB: + return priv->rates_mask & IPW_OFDM_RATE_24MB_MASK ? 1 : 0; + case IEEE80211_RATE_36MB: + return priv->rates_mask & IPW_OFDM_RATE_36MB_MASK ? 1 : 0; + case IEEE80211_RATE_48MB: + return priv->rates_mask & IPW_OFDM_RATE_48MB_MASK ? 1 : 0; + case IEEE80211_RATE_54MB: + return priv->rates_mask & IPW_OFDM_RATE_54MB_MASK ? 1 : 0; } return 0; @@ -4125,34 +4143,22 @@ static int ipw_compatible_rates(struct i const struct ieee80211_network *network, struct ipw_supported_rates *rates) { - int num_rates, i; + int i; memset(rates, 0, sizeof(*rates)); - num_rates = min(network->rates_len, (u8) IPW_MAX_RATES); rates->num_rates = 0; - for (i = 0; i < num_rates; i++) { - if (!ipw_is_rate_in_mask - (priv, network->mode, network->rates[i])) { - IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n", - network->rates[i], priv->rates_mask); + for (i = 0; i < IEEE80211_NUM_RATES; i++) { + if (((network->rates | network->rates_ex) & (1 << i)) == 0) continue; - } - - rates->supported_rates[rates->num_rates++] = network->rates[i]; - } - - num_rates = - min(network->rates_ex_len, (u8) (IPW_MAX_RATES - num_rates)); - for (i = 0; i < num_rates; i++) { if (!ipw_is_rate_in_mask - (priv, network->mode, network->rates_ex[i])) { + (priv, network->modulations, i)) { IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n", - network->rates_ex[i], priv->rates_mask); + ieee80211_rate_values[i], priv->rates_mask); continue; } rates->supported_rates[rates->num_rates++] = - network->rates_ex[i]; + ieee80211_rate_values[i]; } return rates->num_rates; @@ -4173,24 +4179,26 @@ static inline void ipw_copy_rates(struct static void ipw_add_cck_scan_rates(struct ipw_supported_rates *rates, u8 modulation, u32 rate_mask) { - u8 basic_mask = (IEEE80211_OFDM_MODULATION == modulation) ? + u8 basic_mask = (IEEE80211_ERP_OFDM_MODULATION == modulation) ? IEEE80211_BASIC_RATE_MASK : 0; - if (rate_mask & IEEE80211_CCK_RATE_1MB_MASK) + if (rate_mask & IEEE80211_RATE_1MB_MASK) rates->supported_rates[rates->num_rates++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; + IEEE80211_BASIC_RATE_MASK | + ieee80211_rate_values[IEEE80211_RATE_1MB]; - if (rate_mask & IEEE80211_CCK_RATE_2MB_MASK) + if (rate_mask & IEEE80211_RATE_2MB_MASK) rates->supported_rates[rates->num_rates++] = - IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; + IEEE80211_BASIC_RATE_MASK | + ieee80211_rate_values[IEEE80211_RATE_2MB]; - if (rate_mask & IEEE80211_CCK_RATE_5MB_MASK) + if (rate_mask & IEEE80211_RATE_5MB_MASK) rates->supported_rates[rates->num_rates++] = basic_mask | - IEEE80211_CCK_RATE_5MB; + ieee80211_rate_values[IEEE80211_RATE_5MB]; - if (rate_mask & IEEE80211_CCK_RATE_11MB_MASK) + if (rate_mask & IEEE80211_RATE_11MB_MASK) rates->supported_rates[rates->num_rates++] = basic_mask | - IEEE80211_CCK_RATE_11MB; + ieee80211_rate_values[IEEE80211_RATE_11MB]; } static void ipw_add_ofdm_scan_rates(struct ipw_supported_rates *rates, @@ -4199,37 +4207,37 @@ static void ipw_add_ofdm_scan_rates(stru u8 basic_mask = (IEEE80211_OFDM_MODULATION == modulation) ? IEEE80211_BASIC_RATE_MASK : 0; - if (rate_mask & IEEE80211_OFDM_RATE_6MB_MASK) + if (rate_mask & IEEE80211_RATE_6MB_MASK) rates->supported_rates[rates->num_rates++] = basic_mask | - IEEE80211_OFDM_RATE_6MB; + ieee80211_rate_values[IEEE80211_RATE_6MB]; - if (rate_mask & IEEE80211_OFDM_RATE_9MB_MASK) + if (rate_mask & IEEE80211_RATE_9MB_MASK) rates->supported_rates[rates->num_rates++] = - IEEE80211_OFDM_RATE_9MB; + ieee80211_rate_values[IEEE80211_RATE_9MB]; - if (rate_mask & IEEE80211_OFDM_RATE_12MB_MASK) + if (rate_mask & IEEE80211_RATE_12MB_MASK) rates->supported_rates[rates->num_rates++] = basic_mask | - IEEE80211_OFDM_RATE_12MB; + ieee80211_rate_values[IEEE80211_RATE_12MB]; - if (rate_mask & IEEE80211_OFDM_RATE_18MB_MASK) + if (rate_mask & IEEE80211_RATE_18MB_MASK) rates->supported_rates[rates->num_rates++] = - IEEE80211_OFDM_RATE_18MB; + ieee80211_rate_values[IEEE80211_RATE_18MB]; - if (rate_mask & IEEE80211_OFDM_RATE_24MB_MASK) + if (rate_mask & IEEE80211_RATE_24MB_MASK) rates->supported_rates[rates->num_rates++] = basic_mask | - IEEE80211_OFDM_RATE_24MB; + ieee80211_rate_values[IEEE80211_RATE_24MB]; - if (rate_mask & IEEE80211_OFDM_RATE_36MB_MASK) + if (rate_mask & IEEE80211_RATE_36MB_MASK) rates->supported_rates[rates->num_rates++] = - IEEE80211_OFDM_RATE_36MB; + ieee80211_rate_values[IEEE80211_RATE_36MB]; - if (rate_mask & IEEE80211_OFDM_RATE_48MB_MASK) + if (rate_mask & IEEE80211_RATE_48MB_MASK) rates->supported_rates[rates->num_rates++] = - IEEE80211_OFDM_RATE_48MB; + ieee80211_rate_values[IEEE80211_RATE_48MB]; - if (rate_mask & IEEE80211_OFDM_RATE_54MB_MASK) + if (rate_mask & IEEE80211_RATE_54MB_MASK) rates->supported_rates[rates->num_rates++] = - IEEE80211_OFDM_RATE_54MB; + ieee80211_rate_values[IEEE80211_RATE_54MB]; } struct ipw_network_match { @@ -4373,7 +4381,7 @@ static int ipw_best_network(struct ipw_p } /* Filter out any incompatible freq / mode combinations */ - if (!ieee80211_is_valid_mode(priv->ieee, network->mode)) { + if (!ieee80211_is_valid_mode(priv->ieee, network)) { IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded " "because of invalid frequency/mode " "combination.\n", @@ -4409,6 +4417,8 @@ static int ipw_best_network(struct ipw_p static void ipw_adhoc_create(struct ipw_priv *priv, struct ieee80211_network *network) { + int res, i; + /* * For the purposes of scanning, we can set our wireless mode * to trigger scans across combinations of bands, but when it @@ -4420,19 +4430,18 @@ static void ipw_adhoc_create(struct ipw_ * with an invalid channel for wireless mode will trigger a * FW fatal error. */ - network->mode = is_valid_channel(priv->ieee->mode, priv->channel); - if (network->mode) { + res = is_valid_channel(priv->ieee->modulations, priv->channel); + if (res) { + network->modulations = (unsigned)res; network->channel = priv->channel; } else { IPW_WARNING("Overriding invalid channel\n"); - if (priv->ieee->mode & IEEE_A) { - network->mode = IEEE_A; + if (IEEE80211_A_MODE(priv->ieee->modulations)) { + network->modulations = IEEE80211_A_MANDATORY_MODULATIONS; priv->channel = band_a_active_channel[0]; - } else if (priv->ieee->mode & IEEE_G) { - network->mode = IEEE_G; - priv->channel = band_b_active_channel[0]; } else { - network->mode = IEEE_B; + network->modulations = priv->ieee->modulations & + IEEE80211_G_MANDATORY_MODULATIONS; priv->channel = band_b_active_channel[0]; } } @@ -4446,12 +4455,16 @@ static void ipw_adhoc_create(struct ipw_ network->capability = WLAN_CAPABILITY_IBSS; if (priv->capability & CAP_PRIVACY_ON) network->capability |= WLAN_CAPABILITY_PRIVACY; - network->rates_len = min(priv->rates.num_rates, MAX_RATES_LENGTH); - memcpy(network->rates, priv->rates.supported_rates, network->rates_len); - network->rates_ex_len = priv->rates.num_rates - network->rates_len; - memcpy(network->rates_ex, - &priv->rates.supported_rates[network->rates_len], - network->rates_ex_len); + network->rates = network->rates_ex = 0; + for (i = 0; i < priv->rates.num_rates; i++) { + res = ieee80211_value_to_rate(priv->rates.supported_rates[i]); + if (res < 0) + continue; + if (priv->rates.supported_rates[i] & IEEE80211_BASIC_RATE_MASK) + network->rates |= 1 << res; + else + network->rates_ex |= 1 << res; + } network->last_scanned = 0; network->flags = 0; network->last_associate = 0; @@ -4552,55 +4565,51 @@ static inline void ipw_set_fixed_rate(st /* Identify 'current FW band' and match it with the fixed * Tx rates */ - switch (priv->ieee->freq_band) { - case IEEE80211_52GHZ_BAND: /* A only */ + if (IEEE80211_A_MODE(priv->ieee->modulations)) { /* IEEE_A */ - if (priv->rates_mask & ~IEEE80211_OFDM_RATES_MASK) { + if (priv->rates_mask & ~IPW_OFDM_RATES_MASK) { /* Invalid fixed rate mask */ fr.tx_rates = 0; - break; + goto write; } - fr.tx_rates >>= IEEE80211_OFDM_SHIFT_MASK_A; - break; - - default: /* 2.4Ghz or Mixed */ + fr.tx_rates >>= IPW_OFDM_SHIFT_MASK_A; + } else { /* IEEE_B */ - if (network->mode == IEEE_B) { - if (fr.tx_rates & ~IEEE80211_CCK_RATES_MASK) { + if (!(network->modulations & IEEE80211_ERP_OFDM_MODULATION_MASK)) { + if (fr.tx_rates & ~IPW_CCK_RATES_MASK) { /* Invalid fixed rate mask */ fr.tx_rates = 0; } - break; + goto write; } /* IEEE_G */ - if (fr.tx_rates & ~(IEEE80211_CCK_RATES_MASK | - IEEE80211_OFDM_RATES_MASK)) { + if (fr.tx_rates & ~(IPW_CCK_RATES_MASK | + IPW_OFDM_RATES_MASK)) { /* Invalid fixed rate mask */ fr.tx_rates = 0; - break; + goto write; } - if (IEEE80211_OFDM_RATE_6MB_MASK & fr.tx_rates) { - mask |= (IEEE80211_OFDM_RATE_6MB_MASK >> 1); - fr.tx_rates &= ~IEEE80211_OFDM_RATE_6MB_MASK; + if (IPW_OFDM_RATE_6MB_MASK & fr.tx_rates) { + mask |= (IPW_OFDM_RATE_6MB_MASK >> 1); + fr.tx_rates &= ~IPW_OFDM_RATE_6MB_MASK; } - if (IEEE80211_OFDM_RATE_9MB_MASK & fr.tx_rates) { - mask |= (IEEE80211_OFDM_RATE_9MB_MASK >> 1); - fr.tx_rates &= ~IEEE80211_OFDM_RATE_9MB_MASK; + if (IPW_OFDM_RATE_9MB_MASK & fr.tx_rates) { + mask |= (IPW_OFDM_RATE_9MB_MASK >> 1); + fr.tx_rates &= ~IPW_OFDM_RATE_9MB_MASK; } - if (IEEE80211_OFDM_RATE_12MB_MASK & fr.tx_rates) { - mask |= (IEEE80211_OFDM_RATE_12MB_MASK >> 1); - fr.tx_rates &= ~IEEE80211_OFDM_RATE_12MB_MASK; + if (IPW_OFDM_RATE_12MB_MASK & fr.tx_rates) { + mask |= (IPW_OFDM_RATE_12MB_MASK >> 1); + fr.tx_rates &= ~IPW_OFDM_RATE_12MB_MASK; } fr.tx_rates |= mask; - break; } - +write: reg = ipw_read32(priv, IPW_MEM_FIXED_OVERRIDE); ipw_write_reg32(priv, reg, *(u32 *) & fr); } @@ -4641,11 +4650,12 @@ static int ipw_associate_network(struct * when it comes to associating to a given network we have to choose * just one mode. */ - if (network->mode & priv->ieee->mode & IEEE_A) + if (IEEE80211_A_MODE(network->modulations & priv->ieee->modulations)) priv->assoc_request.ieee_mode = IPW_A_MODE; - else if (network->mode & priv->ieee->mode & IEEE_G) + else if (network->modulations & priv->ieee->modulations + & IEEE80211_ERP_OFDM_MODULATION_MASK) priv->assoc_request.ieee_mode = IPW_G_MODE; - else if (network->mode & priv->ieee->mode & IEEE_B) + else if (IEEE80211_B_MODE(network->modulations & priv->ieee->modulations)) priv->assoc_request.ieee_mode = IPW_B_MODE; IPW_DEBUG_ASSOC("%sssocation attempt: '%s', channel %d, " @@ -4937,15 +4947,15 @@ static void ipw_rx(struct ipw_priv *priv .rssi = pkt->u.frame.rssi_dbm - IPW_RSSI_TO_DBM, .signal = pkt->u.frame.signal, - .rate = pkt->u.frame.rate, + .rate = ipw_get_ieee80211_rate(pkt->u.frame.rate), .mac_time = jiffies, .received_channel = pkt->u.frame.received_channel, - .freq = + .modulation = (pkt->u.frame. control & (1 << 0)) ? - IEEE80211_24GHZ_BAND : - IEEE80211_52GHZ_BAND, + ipw_get_bg_modulation(pkt->u.frame.rate) : + IEEE80211_OFDM_MODULATION, .len = pkt->u.frame.length, }; @@ -5174,7 +5184,7 @@ static int ipw_request_scan(struct ipw_p scan_type = IPW_SCAN_ACTIVE_BROADCAST_SCAN; } - if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) { + if (IEEE80211_HAS_52GHZ_MODE(priv->ieee->modulations)) { int start = channel_index; for (i = 0; i < MAX_A_CHANNELS; i++) { if (band_a_active_channel[i] == 0) @@ -5195,7 +5205,7 @@ static int ipw_request_scan(struct ipw_p } } - if (priv->ieee->freq_band & IEEE80211_24GHZ_BAND) { + if (IEEE80211_HAS_24GHZ_MODE(priv->ieee->modulations)) { int start = channel_index; for (i = 0; i < MAX_B_CHANNELS; i++) { if (band_b_active_channel[i] == 0) @@ -6002,45 +6012,31 @@ static int ipw_wx_set_wireless_mode(stru { struct ipw_priv *priv = ieee80211_dev_to_priv(dev); int mode = *(int *)extra; - u8 band = 0, modulation = 0; + unsigned modulations = 0; - if (mode == 0 || mode & ~IEEE_MODE_MASK) { + if (mode <= 0 || mode > 7) { IPW_WARNING("Attempt to set invalid wireless mode: %d\n", mode); return -EINVAL; } if (priv->adapter == IPW_2915ABG) { - priv->ieee->abg_true = 1; - if (mode & IEEE_A) { - band |= IEEE80211_52GHZ_BAND; - modulation |= IEEE80211_OFDM_MODULATION; - } else - priv->ieee->abg_true = 0; + if (mode & (1 << IPW_A_MODE)) + modulations |= IEEE80211_OFDM_MODULATION_MASK; } else { - if (mode & IEEE_A) { + if (mode & (1 << IPW_A_MODE)) { IPW_WARNING("Attempt to set 2200BG into " "802.11a mode\n"); return -EINVAL; } - - priv->ieee->abg_true = 0; } - if (mode & IEEE_B) { - band |= IEEE80211_24GHZ_BAND; - modulation |= IEEE80211_CCK_MODULATION; - } else - priv->ieee->abg_true = 0; + if (mode & (1 << IPW_B_MODE)) + modulations |= IEEE80211_DSSS_MODULATION_MASK; - if (mode & IEEE_G) { - band |= IEEE80211_24GHZ_BAND; - modulation |= IEEE80211_OFDM_MODULATION; - } else - priv->ieee->abg_true = 0; + if (mode & (1 << IPW_G_MODE)) + modulations |= IEEE80211_ERP_OFDM_MODULATION_MASK; - priv->ieee->mode = mode; - priv->ieee->freq_band = band; - priv->ieee->modulation = modulation; + priv->ieee->modulations = modulations; init_supported_rates(priv, &priv->rates); /* If we are currently associated, or trying to associate @@ -6055,8 +6051,9 @@ static int ipw_wx_set_wireless_mode(stru ipw_send_supported_rates(priv, &priv->rates); IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n", - mode & IEEE_A ? 'a' : '.', - mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.'); + mode & (1 << IPW_A_MODE) ? 'a' : '.', + mode & (1 << IPW_B_MODE) ? 'b' : '.', + mode & (1 << IPW_G_MODE) ? 'g' : '.'); return 0; } @@ -6065,38 +6062,36 @@ static int ipw_wx_get_wireless_mode(stru union iwreq_data *wrqu, char *extra) { struct ipw_priv *priv = ieee80211_dev_to_priv(dev); + int ipw_mode = 0; - switch (priv->ieee->freq_band) { - case IEEE80211_24GHZ_BAND: - switch (priv->ieee->modulation) { - case IEEE80211_CCK_MODULATION: - strncpy(extra, "802.11b (2)", MAX_WX_STRING); - break; - case IEEE80211_OFDM_MODULATION: - strncpy(extra, "802.11g (4)", MAX_WX_STRING); - break; - default: - strncpy(extra, "802.11bg (6)", MAX_WX_STRING); - break; - } - break; + if (priv->ieee->modulations & IEEE80211_OFDM_MODULATION_MASK) + ipw_mode |= (1 << IPW_A_MODE); + if (priv->ieee->modulations & IEEE80211_DSSS_MODULATION_MASK) + ipw_mode |= (1 << IPW_B_MODE); + if (priv->ieee->modulations & IEEE80211_ERP_OFDM_MODULATION_MASK) + ipw_mode |= (1 << IPW_G_MODE); - case IEEE80211_52GHZ_BAND: + switch (ipw_mode) { + case 2: + strncpy(extra, "802.11b (2)", MAX_WX_STRING); + break; + case 4: + strncpy(extra, "802.11g (4)", MAX_WX_STRING); + break; + case 6: + strncpy(extra, "802.11bg (6)", MAX_WX_STRING); + break; + case 1: strncpy(extra, "802.11a (1)", MAX_WX_STRING); break; - - default: /* Mixed Band */ - switch (priv->ieee->modulation) { - case IEEE80211_CCK_MODULATION: - strncpy(extra, "802.11ab (3)", MAX_WX_STRING); - break; - case IEEE80211_OFDM_MODULATION: - strncpy(extra, "802.11ag (5)", MAX_WX_STRING); - break; - default: - strncpy(extra, "802.11abg (7)", MAX_WX_STRING); - break; - } + case 3: + strncpy(extra, "802.11ab (3)", MAX_WX_STRING); + break; + case 5: + strncpy(extra, "802.11ag (5)", MAX_WX_STRING); + break; + default: + strncpy(extra, "802.11abg (7)", MAX_WX_STRING); break; } @@ -6760,24 +6755,20 @@ static int init_supported_rates(struct i memset(rates, 0, sizeof(*rates)); /* configure supported rates */ - switch (priv->ieee->freq_band) { - case IEEE80211_52GHZ_BAND: + if (IEEE80211_HAS_52GHZ_MODE(priv->ieee->modulations)) { rates->ieee_mode = IPW_A_MODE; rates->purpose = IPW_RATE_CAPABILITIES; - ipw_add_ofdm_scan_rates(rates, IEEE80211_CCK_MODULATION, - IEEE80211_OFDM_DEFAULT_RATES_MASK); - break; - - default: /* Mixed or 2.4Ghz */ + ipw_add_ofdm_scan_rates(rates, IEEE80211_OFDM_MODULATION, + IEEE80211_OFDM_RATES_MASK); + } else { /* Mixed or 2.4Ghz */ rates->ieee_mode = IPW_G_MODE; rates->purpose = IPW_RATE_CAPABILITIES; - ipw_add_cck_scan_rates(rates, IEEE80211_CCK_MODULATION, - IEEE80211_CCK_DEFAULT_RATES_MASK); - if (priv->ieee->modulation & IEEE80211_OFDM_MODULATION) { - ipw_add_ofdm_scan_rates(rates, IEEE80211_CCK_MODULATION, - IEEE80211_OFDM_DEFAULT_RATES_MASK); + ipw_add_cck_scan_rates(rates, IEEE80211_DSSS_MODULATION, + IEEE80211_DSSS_RATES_MASK); + if (priv->ieee->modulations & IEEE80211_ERP_OFDM_MODULATION_MASK) { + ipw_add_ofdm_scan_rates(rates, IEEE80211_DSSS_MODULATION, + IEEE80211_OFDM_RATES_MASK); } - break; } return 0; @@ -6999,7 +6990,6 @@ static int ipw_pci_probe(struct pci_dev void __iomem *base; u32 length, val; struct ipw_priv *priv; - int band, modulation; ieee = alloc_ieee80211(sizeof(struct ipw_priv)); if (ieee == NULL) { @@ -7112,12 +7102,11 @@ static int ipw_pci_probe(struct pci_dev printk(KERN_INFO DRV_NAME ": Detected Intel PRO/Wireless 2915ABG Network " "Connection\n"); - priv->ieee->abg_true = 1; - band = IEEE80211_52GHZ_BAND | IEEE80211_24GHZ_BAND; - modulation = IEEE80211_OFDM_MODULATION | - IEEE80211_CCK_MODULATION; priv->adapter = IPW_2915ABG; - priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B; + priv->ieee->supported_modulations = priv->ieee->modulations = + IEEE80211_A_MANDATORY_MODULATIONS | + IEEE80211_B_MANDATORY_MODULATIONS | + IEEE80211_G_MANDATORY_MODULATIONS; } else { if (priv->pci_dev->device == 0x4221) printk(KERN_INFO DRV_NAME @@ -7128,18 +7117,15 @@ static int ipw_pci_probe(struct pci_dev ": Detected Intel PRO/Wireless 2200BG Network " "Connection\n"); - priv->ieee->abg_true = 0; - band = IEEE80211_24GHZ_BAND; - modulation = IEEE80211_OFDM_MODULATION | - IEEE80211_CCK_MODULATION; priv->adapter = IPW_2200BG; - priv->ieee->mode = IEEE_G | IEEE_B; + priv->ieee->supported_modulations = priv->ieee->modulations = + IEEE80211_B_MANDATORY_MODULATIONS | + IEEE80211_G_MANDATORY_MODULATIONS; } - priv->ieee->freq_band = band; - priv->ieee->modulation = modulation; - - priv->rates_mask = IEEE80211_DEFAULT_RATES_MASK; + priv->ieee->supported_rates = priv->ieee->rates = + IEEE80211_DSSS_RATES_MASK | IEEE80211_OFDM_RATES_MASK; + priv->rates_mask = IPW_DEFAULT_RATES_MASK; priv->missed_beacon_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT; priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT;