aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ipw2200.c
diff options
context:
space:
mode:
authorLiu Hong <hong.liu@intel.com>2005-08-19 10:33:10 -0400
committerJames Ketrenos <jketreno@linux.intel.com>2005-11-07 18:51:03 -0500
commit1fe0adb4314009362d28205bbf09f6d758e82002 (patch)
tree63809744601a0f97ed8499c72377ab49d78a78ab /drivers/net/wireless/ipw2200.c
parentf6c5cb7c6f8a85045996bfc3442af963d6578d60 (diff)
Migrated some of the channel verification code back into the driver to
keep regulatory consistency in one location. Signed-off-by: James Ketrenos
Diffstat (limited to 'drivers/net/wireless/ipw2200.c')
-rw-r--r--drivers/net/wireless/ipw2200.c173
1 files changed, 152 insertions, 21 deletions
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index bcb5993b68bd..40759e5f3cc5 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -149,6 +149,12 @@ static int init_supported_rates(struct ipw_priv *priv,
149static void ipw_set_hwcrypto_keys(struct ipw_priv *); 149static void ipw_set_hwcrypto_keys(struct ipw_priv *);
150static void ipw_send_wep_keys(struct ipw_priv *, int); 150static void ipw_send_wep_keys(struct ipw_priv *, int);
151 151
152static int ipw_is_valid_channel(struct ieee80211_device *, u8);
153static int ipw_channel_to_index(struct ieee80211_device *, u8);
154static u8 ipw_freq_to_channel(struct ieee80211_device *, u32);
155static int ipw_set_geo(struct ieee80211_device *, const struct ieee80211_geo *);
156static const struct ieee80211_geo *ipw_get_geo(struct ieee80211_device *);
157
152static int snprint_line(char *buf, size_t count, 158static int snprint_line(char *buf, size_t count,
153 const u8 * data, u32 len, u32 ofs) 159 const u8 * data, u32 len, u32 ofs)
154{ 160{
@@ -1596,7 +1602,7 @@ static ssize_t store_speed_scan(struct device *d, struct device_attribute *attr,
1596 break; 1602 break;
1597 } 1603 }
1598 1604
1599 if (ieee80211_is_valid_channel(priv->ieee, channel)) 1605 if (ipw_is_valid_channel(priv->ieee, channel))
1600 priv->speed_scan[pos++] = channel; 1606 priv->speed_scan[pos++] = channel;
1601 else 1607 else
1602 IPW_WARNING("Skipping invalid channel request: %d\n", 1608 IPW_WARNING("Skipping invalid channel request: %d\n",
@@ -2194,7 +2200,7 @@ static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power)
2194 2200
2195static int ipw_set_tx_power(struct ipw_priv *priv) 2201static int ipw_set_tx_power(struct ipw_priv *priv)
2196{ 2202{
2197 const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); 2203 const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
2198 struct ipw_tx_power tx_power; 2204 struct ipw_tx_power tx_power;
2199 s8 max_power; 2205 s8 max_power;
2200 int i; 2206 int i;
@@ -5503,6 +5509,15 @@ static int ipw_best_network(struct ipw_priv *priv,
5503 return 0; 5509 return 0;
5504 } 5510 }
5505 5511
5512 /* Filter out invalid channel in current GEO */
5513 if (!ipw_is_valid_channel(priv->ieee, network->channel)) {
5514 IPW_DEBUG_ASSOC("Network '%s (" MAC_FMT ")' excluded "
5515 "because of invalid channel in current GEO\n",
5516 escape_essid(network->ssid, network->ssid_len),
5517 MAC_ARG(network->bssid));
5518 return 0;
5519 }
5520
5506 /* Ensure that the rates supported by the driver are compatible with 5521 /* Ensure that the rates supported by the driver are compatible with
5507 * this AP, including verification of basic rates (mandatory) */ 5522 * this AP, including verification of basic rates (mandatory) */
5508 if (!ipw_compatible_rates(priv, network, &rates)) { 5523 if (!ipw_compatible_rates(priv, network, &rates)) {
@@ -5540,7 +5555,7 @@ static int ipw_best_network(struct ipw_priv *priv,
5540static void ipw_adhoc_create(struct ipw_priv *priv, 5555static void ipw_adhoc_create(struct ipw_priv *priv,
5541 struct ieee80211_network *network) 5556 struct ieee80211_network *network)
5542{ 5557{
5543 const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); 5558 const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
5544 int i; 5559 int i;
5545 5560
5546 /* 5561 /*
@@ -5555,10 +5570,10 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
5555 * FW fatal error. 5570 * FW fatal error.
5556 * 5571 *
5557 */ 5572 */
5558 switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) { 5573 switch (ipw_is_valid_channel(priv->ieee, priv->channel)) {
5559 case IEEE80211_52GHZ_BAND: 5574 case IEEE80211_52GHZ_BAND:
5560 network->mode = IEEE_A; 5575 network->mode = IEEE_A;
5561 i = ieee80211_channel_to_index(priv->ieee, priv->channel); 5576 i = ipw_channel_to_index(priv->ieee, priv->channel);
5562 if (i == -1) 5577 if (i == -1)
5563 BUG(); 5578 BUG();
5564 if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { 5579 if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
@@ -5572,6 +5587,13 @@ static void ipw_adhoc_create(struct ipw_priv *priv,
5572 network->mode = IEEE_G; 5587 network->mode = IEEE_G;
5573 else 5588 else
5574 network->mode = IEEE_B; 5589 network->mode = IEEE_B;
5590 i = ipw_channel_to_index(priv->ieee, priv->channel);
5591 if (i == -1)
5592 BUG();
5593 if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) {
5594 IPW_WARNING("Overriding invalid channel\n");
5595 priv->channel = geo->bg[0].channel;
5596 }
5575 break; 5597 break;
5576 5598
5577 default: 5599 default:
@@ -5899,7 +5921,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv,
5899 const struct ieee80211_geo *geo; 5921 const struct ieee80211_geo *geo;
5900 int i; 5922 int i;
5901 5923
5902 geo = ieee80211_get_geo(priv->ieee); 5924 geo = ipw_get_geo(priv->ieee);
5903 5925
5904 if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) { 5926 if (priv->ieee->freq_band & IEEE80211_52GHZ_BAND) {
5905 int start = channel_index; 5927 int start = channel_index;
@@ -5909,7 +5931,11 @@ static void ipw_add_scan_channels(struct ipw_priv *priv,
5909 continue; 5931 continue;
5910 channel_index++; 5932 channel_index++;
5911 scan->channels_list[channel_index] = geo->a[i].channel; 5933 scan->channels_list[channel_index] = geo->a[i].channel;
5912 ipw_set_scan_type(scan, channel_index, scan_type); 5934 ipw_set_scan_type(scan, channel_index,
5935 geo->a[i].
5936 flags & IEEE80211_CH_PASSIVE_ONLY ?
5937 IPW_SCAN_PASSIVE_FULL_DWELL_SCAN :
5938 scan_type);
5913 } 5939 }
5914 5940
5915 if (start != channel_index) { 5941 if (start != channel_index) {
@@ -5922,6 +5948,7 @@ static void ipw_add_scan_channels(struct ipw_priv *priv,
5922 if (priv->ieee->freq_band & IEEE80211_24GHZ_BAND) { 5948 if (priv->ieee->freq_band & IEEE80211_24GHZ_BAND) {
5923 int start = channel_index; 5949 int start = channel_index;
5924 if (priv->config & CFG_SPEED_SCAN) { 5950 if (priv->config & CFG_SPEED_SCAN) {
5951 int index;
5925 u8 channels[IEEE80211_24GHZ_CHANNELS] = { 5952 u8 channels[IEEE80211_24GHZ_CHANNELS] = {
5926 /* nop out the list */ 5953 /* nop out the list */
5927 [0] = 0 5954 [0] = 0
@@ -5953,8 +5980,14 @@ static void ipw_add_scan_channels(struct ipw_priv *priv,
5953 priv->speed_scan_pos++; 5980 priv->speed_scan_pos++;
5954 channel_index++; 5981 channel_index++;
5955 scan->channels_list[channel_index] = channel; 5982 scan->channels_list[channel_index] = channel;
5983 index =
5984 ipw_channel_to_index(priv->ieee, channel);
5956 ipw_set_scan_type(scan, channel_index, 5985 ipw_set_scan_type(scan, channel_index,
5957 scan_type); 5986 geo->bg[index].
5987 flags &
5988 IEEE80211_CH_PASSIVE_ONLY ?
5989 IPW_SCAN_PASSIVE_FULL_DWELL_SCAN
5990 : scan_type);
5958 } 5991 }
5959 } else { 5992 } else {
5960 for (i = 0; i < geo->bg_channels; i++) { 5993 for (i = 0; i < geo->bg_channels; i++) {
@@ -5965,7 +5998,11 @@ static void ipw_add_scan_channels(struct ipw_priv *priv,
5965 scan->channels_list[channel_index] = 5998 scan->channels_list[channel_index] =
5966 geo->bg[i].channel; 5999 geo->bg[i].channel;
5967 ipw_set_scan_type(scan, channel_index, 6000 ipw_set_scan_type(scan, channel_index,
5968 scan_type); 6001 geo->bg[i].
6002 flags &
6003 IEEE80211_CH_PASSIVE_ONLY ?
6004 IPW_SCAN_PASSIVE_FULL_DWELL_SCAN
6005 : scan_type);
5969 } 6006 }
5970 } 6007 }
5971 6008
@@ -6017,7 +6054,7 @@ static int ipw_request_scan(struct ipw_priv *priv)
6017 6054
6018 scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = 6055 scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] =
6019 cpu_to_le16(20); 6056 cpu_to_le16(20);
6020 scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(20); 6057 scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120);
6021 6058
6022 scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee)); 6059 scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee));
6023 6060
@@ -6026,7 +6063,7 @@ static int ipw_request_scan(struct ipw_priv *priv)
6026 u8 channel; 6063 u8 channel;
6027 u8 band = 0; 6064 u8 band = 0;
6028 6065
6029 switch (ieee80211_is_valid_channel(priv->ieee, priv->channel)) { 6066 switch (ipw_is_valid_channel(priv->ieee, priv->channel)) {
6030 case IEEE80211_52GHZ_BAND: 6067 case IEEE80211_52GHZ_BAND:
6031 band = (u8) (IPW_A_MODE << 6) | 1; 6068 band = (u8) (IPW_A_MODE << 6) | 1;
6032 channel = priv->channel; 6069 channel = priv->channel;
@@ -8401,10 +8438,11 @@ static int ipw_wx_set_freq(struct net_device *dev,
8401 union iwreq_data *wrqu, char *extra) 8438 union iwreq_data *wrqu, char *extra)
8402{ 8439{
8403 struct ipw_priv *priv = ieee80211_priv(dev); 8440 struct ipw_priv *priv = ieee80211_priv(dev);
8404 const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); 8441 const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
8405 struct iw_freq *fwrq = &wrqu->freq; 8442 struct iw_freq *fwrq = &wrqu->freq;
8406 int ret = 0, i; 8443 int ret = 0, i;
8407 u8 channel; 8444 u8 channel, flags;
8445 int band;
8408 8446
8409 if (fwrq->m == 0) { 8447 if (fwrq->m == 0) {
8410 IPW_DEBUG_WX("SET Freq/Channel -> any\n"); 8448 IPW_DEBUG_WX("SET Freq/Channel -> any\n");
@@ -8415,20 +8453,23 @@ static int ipw_wx_set_freq(struct net_device *dev,
8415 } 8453 }
8416 /* if setting by freq convert to channel */ 8454 /* if setting by freq convert to channel */
8417 if (fwrq->e == 1) { 8455 if (fwrq->e == 1) {
8418 channel = ieee80211_freq_to_channel(priv->ieee, fwrq->m); 8456 channel = ipw_freq_to_channel(priv->ieee, fwrq->m);
8419 if (channel == 0) 8457 if (channel == 0)
8420 return -EINVAL; 8458 return -EINVAL;
8421 } else 8459 } else
8422 channel = fwrq->m; 8460 channel = fwrq->m;
8423 8461
8424 if (!ieee80211_is_valid_channel(priv->ieee, channel)) 8462 if (!(band = ipw_is_valid_channel(priv->ieee, channel)))
8425 return -EINVAL; 8463 return -EINVAL;
8426 8464
8427 if (priv->ieee->iw_mode == IW_MODE_ADHOC && priv->ieee->mode & IEEE_A) { 8465 if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
8428 i = ieee80211_channel_to_index(priv->ieee, channel); 8466 i = ipw_channel_to_index(priv->ieee, channel);
8429 if (i == -1) 8467 if (i == -1)
8430 return -EINVAL; 8468 return -EINVAL;
8431 if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { 8469
8470 flags = (band == IEEE80211_24GHZ_BAND) ?
8471 geo->bg[i].flags : geo->a[i].flags;
8472 if (flags & IEEE80211_CH_PASSIVE_ONLY) {
8432 IPW_DEBUG_WX("Invalid Ad-Hoc channel for 802.11a\n"); 8473 IPW_DEBUG_WX("Invalid Ad-Hoc channel for 802.11a\n");
8433 return -EINVAL; 8474 return -EINVAL;
8434 } 8475 }
@@ -8546,7 +8587,7 @@ static int ipw_wx_get_range(struct net_device *dev,
8546{ 8587{
8547 struct ipw_priv *priv = ieee80211_priv(dev); 8588 struct ipw_priv *priv = ieee80211_priv(dev);
8548 struct iw_range *range = (struct iw_range *)extra; 8589 struct iw_range *range = (struct iw_range *)extra;
8549 const struct ieee80211_geo *geo = ieee80211_get_geo(priv->ieee); 8590 const struct ieee80211_geo *geo = ipw_get_geo(priv->ieee);
8550 int i = 0, j; 8591 int i = 0, j;
8551 8592
8552 wrqu->data.length = sizeof(*range); 8593 wrqu->data.length = sizeof(*range);
@@ -9147,7 +9188,7 @@ static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid,
9147 9188
9148 scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = 9189 scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] =
9149 cpu_to_le16(20); 9190 cpu_to_le16(20);
9150 scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(20); 9191 scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120);
9151 scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20); 9192 scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20);
9152 9193
9153 scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee)); 9194 scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee));
@@ -10775,6 +10816,96 @@ static const struct ieee80211_geo ipw_geos[] = {
10775 } 10816 }
10776}; 10817};
10777 10818
10819/* GEO code borrowed from ieee80211_geo.c */
10820static int ipw_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
10821{
10822 int i;
10823
10824 /* Driver needs to initialize the geography map before using
10825 * these helper functions */
10826 BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
10827
10828 if (ieee->freq_band & IEEE80211_24GHZ_BAND)
10829 for (i = 0; i < ieee->geo.bg_channels; i++)
10830 /* NOTE: If G mode is currently supported but
10831 * this is a B only channel, we don't see it
10832 * as valid. */
10833 if ((ieee->geo.bg[i].channel == channel) &&
10834 (!(ieee->mode & IEEE_G) ||
10835 !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY)))
10836 return IEEE80211_24GHZ_BAND;
10837
10838 if (ieee->freq_band & IEEE80211_52GHZ_BAND)
10839 for (i = 0; i < ieee->geo.a_channels; i++)
10840 if (ieee->geo.a[i].channel == channel)
10841 return IEEE80211_52GHZ_BAND;
10842
10843 return 0;
10844}
10845
10846static int ipw_channel_to_index(struct ieee80211_device *ieee, u8 channel)
10847{
10848 int i;
10849
10850 /* Driver needs to initialize the geography map before using
10851 * these helper functions */
10852 BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
10853
10854 if (ieee->freq_band & IEEE80211_24GHZ_BAND)
10855 for (i = 0; i < ieee->geo.bg_channels; i++)
10856 if (ieee->geo.bg[i].channel == channel)
10857 return i;
10858
10859 if (ieee->freq_band & IEEE80211_52GHZ_BAND)
10860 for (i = 0; i < ieee->geo.a_channels; i++)
10861 if (ieee->geo.a[i].channel == channel)
10862 return i;
10863
10864 return -1;
10865}
10866
10867static u8 ipw_freq_to_channel(struct ieee80211_device *ieee, u32 freq)
10868{
10869 int i;
10870
10871 /* Driver needs to initialize the geography map before using
10872 * these helper functions */
10873 BUG_ON(ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0);
10874
10875 freq /= 100000;
10876
10877 if (ieee->freq_band & IEEE80211_24GHZ_BAND)
10878 for (i = 0; i < ieee->geo.bg_channels; i++)
10879 if (ieee->geo.bg[i].freq == freq)
10880 return ieee->geo.bg[i].channel;
10881
10882 if (ieee->freq_band & IEEE80211_52GHZ_BAND)
10883 for (i = 0; i < ieee->geo.a_channels; i++)
10884 if (ieee->geo.a[i].freq == freq)
10885 return ieee->geo.a[i].channel;
10886
10887 return 0;
10888}
10889
10890static int ipw_set_geo(struct ieee80211_device *ieee,
10891 const struct ieee80211_geo *geo)
10892{
10893 memcpy(ieee->geo.name, geo->name, 3);
10894 ieee->geo.name[3] = '\0';
10895 ieee->geo.bg_channels = geo->bg_channels;
10896 ieee->geo.a_channels = geo->a_channels;
10897 memcpy(ieee->geo.bg, geo->bg, geo->bg_channels *
10898 sizeof(struct ieee80211_channel));
10899 memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
10900 sizeof(struct ieee80211_channel));
10901 return 0;
10902}
10903
10904static const struct ieee80211_geo *ipw_get_geo(struct ieee80211_device *ieee)
10905{
10906 return &ieee->geo;
10907}
10908
10778#define MAX_HW_RESTARTS 5 10909#define MAX_HW_RESTARTS 5
10779static int ipw_up(struct ipw_priv *priv) 10910static int ipw_up(struct ipw_priv *priv)
10780{ 10911{
@@ -10816,7 +10947,7 @@ static int ipw_up(struct ipw_priv *priv)
10816 } 10947 }
10817 if (j == ARRAY_SIZE(ipw_geos)) 10948 if (j == ARRAY_SIZE(ipw_geos))
10818 j = 0; 10949 j = 0;
10819 if (ieee80211_set_geo(priv->ieee, &ipw_geos[j])) { 10950 if (ipw_set_geo(priv->ieee, &ipw_geos[j])) {
10820 IPW_WARNING("Could not set geography."); 10951 IPW_WARNING("Could not set geography.");
10821 return 0; 10952 return 0;
10822 } 10953 }