cfg80211: Extend channel to frequency mapping for 802.11j
authorBruno Randolf <br1@einfach.org>
Mon, 17 Jan 2011 04:37:28 +0000 (13:37 +0900)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 21 Jan 2011 20:34:17 +0000 (15:34 -0500)
Extend channel to frequency mapping for 802.11j Japan 4.9GHz band, according to
IEEE802.11 section 17.3.8.3.2 and Annex J. Because there are now overlapping
channel numbers in the 2GHz and 5GHz band we can't map from channel to
frequency without knowing the band. This is no problem as in most contexts we
know the band. In places where we don't know the band (and WEXT compatibility)
we assume the 2GHz band for channels below 14.

This patch does not implement all channel to frequency mappings defined in
802.11, it's just an extension for 802.11j 20MHz channels. 5MHz and 10MHz
channels as well as 802.11y channels have been omitted.

The following drivers have been updated to reflect the API changes:
iwl-3945, iwl-agn, iwmc3200wifi, libertas, mwl8k, rt2x00, wl1251, wl12xx.
The drivers have been compile-tested only.

Signed-off-by: Bruno Randolf <br1@einfach.org>
Signed-off-by: Brian Prodoehl <bprodoehl@gmail.com>
Acked-by: Luciano Coelho <coelho@ti.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
18 files changed:
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwmc3200wifi/cfg80211.c
drivers/net/wireless/iwmc3200wifi/rx.c
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/mwl8k.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/wl1251/rx.c
drivers/net/wireless/wl12xx/rx.c
include/net/cfg80211.h
net/mac80211/ibss.c
net/mac80211/mesh.c
net/mac80211/mlme.c
net/mac80211/scan.c
net/wireless/reg.c
net/wireless/util.c
net/wireless/wext-compat.c

index a9b852be450980249597039ae2adad299ac1b67c..1d9dcd7e3b829f499dbb14c7e93a01263d19e37d 100644 (file)
@@ -594,10 +594,11 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
 
        rx_status.flag = 0;
        rx_status.mactime = le64_to_cpu(rx_end->timestamp);
-       rx_status.freq =
-               ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel));
        rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
                                IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+       rx_status.freq =
+               ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel),
+                                              rx_status.band);
 
        rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
        if (rx_status.band == IEEE80211_BAND_5GHZ)
index 29dcda0bde658b4cec43a284c22f0c77c62a6aab..c7d03874b38091cf8bf4a6356ca02d6d87e49e6a 100644 (file)
@@ -1162,10 +1162,11 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv,
 
        /* rx_status carries information about the packet to mac80211 */
        rx_status.mactime = le64_to_cpu(phy_res->timestamp);
-       rx_status.freq =
-               ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel));
        rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
                                IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+       rx_status.freq =
+               ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel),
+                                              rx_status.band);
        rx_status.rate_idx =
                iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
        rx_status.flag = 0;
index efbde1f1a8bfca29924465c0c56ba57cf4c74e17..a8d4a936a2e7367770a93ad2ebb6b2b77d308cd3 100644 (file)
@@ -227,7 +227,8 @@ int iwlcore_init_geos(struct iwl_priv *priv)
                geo_ch = &sband->channels[sband->n_channels++];
 
                geo_ch->center_freq =
-                               ieee80211_channel_to_frequency(ch->channel);
+                               ieee80211_channel_to_frequency(ch->channel,
+                                                              sband->band);
                geo_ch->max_power = ch->max_power_avg;
                geo_ch->max_antenna_gain = 0xff;
                geo_ch->hw_value = ch->channel;
index 5a4982271e96a8f9cb57fb6c22610549b1dbcb0b..ed57e44028009e0b6dd515169416caa4d213029b 100644 (file)
@@ -287,7 +287,8 @@ int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
                        return -EINVAL;
                }
 
-               freq = ieee80211_channel_to_frequency(umac_bss->channel);
+               freq = ieee80211_channel_to_frequency(umac_bss->channel,
+                                                     band->band);
                channel = ieee80211_get_channel(wiphy, freq);
                signal = umac_bss->rssi * 100;
 
index a944893ae3ca78d9b3371102ffc85ad9b5cea65e..9a57cf6a488fabba03d00c1f3d8d57970f1fd233 100644 (file)
@@ -543,7 +543,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
        switch (le32_to_cpu(complete->status)) {
        case UMAC_ASSOC_COMPLETE_SUCCESS:
                chan = ieee80211_get_channel(wiphy,
-                       ieee80211_channel_to_frequency(complete->channel));
+                       ieee80211_channel_to_frequency(complete->channel,
+                               complete->band == UMAC_BAND_2GHZ ?
+                                       IEEE80211_BAND_2GHZ :
+                                       IEEE80211_BAND_5GHZ));
                if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
                        /* Associated to a unallowed channel, disassociate. */
                        __iwm_invalidate_mlme_profile(iwm);
@@ -841,7 +844,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf,
                goto err;
        }
 
-       freq = ieee80211_channel_to_frequency(umac_bss->channel);
+       freq = ieee80211_channel_to_frequency(umac_bss->channel, band->band);
        channel = ieee80211_get_channel(wiphy, freq);
        signal = umac_bss->rssi * 100;
 
index 698a1f7694ed9eac019b580a9fe534a169661955..30ef0351bfc443fd889505d5c7421ce55b6ddadc 100644 (file)
@@ -607,7 +607,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
                /* No channel, no luck */
                if (chan_no != -1) {
                        struct wiphy *wiphy = priv->wdev->wiphy;
-                       int freq = ieee80211_channel_to_frequency(chan_no);
+                       int freq = ieee80211_channel_to_frequency(chan_no,
+                                                       IEEE80211_BAND_2GHZ);
                        struct ieee80211_channel *channel =
                                ieee80211_get_channel(wiphy, freq);
 
@@ -1597,7 +1598,8 @@ static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev,
        lbs_deb_enter(LBS_DEB_CFG80211);
 
        survey->channel = ieee80211_get_channel(wiphy,
-               ieee80211_channel_to_frequency(priv->channel));
+               ieee80211_channel_to_frequency(priv->channel,
+                                              IEEE80211_BAND_2GHZ));
 
        ret = lbs_get_rssi(priv, &signal, &noise);
        if (ret == 0) {
index 106b427d0064424b82f7771f035b9e6cc3ead2d6..af4f2c64f2428b58ff626048a7f93d00c5b82090 100644 (file)
@@ -906,7 +906,8 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
        } else {
                status->band = IEEE80211_BAND_2GHZ;
        }
-       status->freq = ieee80211_channel_to_frequency(rxd->channel);
+       status->freq = ieee80211_channel_to_frequency(rxd->channel,
+                                                     status->band);
 
        *qos = rxd->qos_control;
 
@@ -1013,7 +1014,8 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
        } else {
                status->band = IEEE80211_BAND_2GHZ;
        }
-       status->freq = ieee80211_channel_to_frequency(rxd->channel);
+       status->freq = ieee80211_channel_to_frequency(rxd->channel,
+                                                     status->band);
 
        *qos = rxd->qos_control;
        if ((rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DECRYPT_ERROR) &&
index 9597a03242cceb7bbed7fd8b0d847741c2450097..31b7db05abd913d7e5a46e79e3ecc7f610bf6197 100644 (file)
@@ -649,7 +649,10 @@ static void rt2x00lib_channel(struct ieee80211_channel *entry,
                              const int channel, const int tx_power,
                              const int value)
 {
-       entry->center_freq = ieee80211_channel_to_frequency(channel);
+       /* XXX: this assumption about the band is wrong for 802.11j */
+       entry->band = channel <= 14 ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+       entry->center_freq = ieee80211_channel_to_frequency(channel,
+                                                           entry->band);
        entry->hw_value = value;
        entry->max_power = tx_power;
        entry->max_antenna_gain = 0xff;
index efa53607d5c9ac9e5ef2f572739f46b562334117..86eef456d7b2b5299265312cbe4364051a9488b4 100644 (file)
@@ -78,7 +78,8 @@ static void wl1251_rx_status(struct wl1251 *wl,
         */
        wl->noise = desc->rssi - desc->snr / 2;
 
-       status->freq = ieee80211_channel_to_frequency(desc->channel);
+       status->freq = ieee80211_channel_to_frequency(desc->channel,
+                                                     status->band);
 
        status->flag |= RX_FLAG_TSFT;
 
index 682304c30b81e208b15cc3dda2b6b8f43cf4a4c8..ec8d843d41cfd4198f3dd4c7fe25f43d244a2e02 100644 (file)
@@ -76,7 +76,7 @@ static void wl1271_rx_status(struct wl1271 *wl,
         */
        wl->noise = desc->rssi - (desc->snr >> 1);
 
-       status->freq = ieee80211_channel_to_frequency(desc->channel);
+       status->freq = ieee80211_channel_to_frequency(desc->channel, desc_band);
 
        if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
                status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
index 1322695beb52980e741b17473ed9906ba159895e..679a0494b5f205c99e679f30a5e4b1b6244a0149 100644 (file)
@@ -1790,8 +1790,9 @@ static inline void *wdev_priv(struct wireless_dev *wdev)
 /**
  * ieee80211_channel_to_frequency - convert channel number to frequency
  * @chan: channel number
+ * @band: band, necessary due to channel number overlap
  */
-extern int ieee80211_channel_to_frequency(int chan);
+extern int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band);
 
 /**
  * ieee80211_frequency_to_channel - convert frequency to channel number
index 53c7077ffd4f2ff36e5ddcbdcc3f33bd378cb1c7..775fb63471c457a68bef8439f59e9335a2392b5b 100644 (file)
@@ -270,7 +270,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
        enum ieee80211_band band = rx_status->band;
 
        if (elems->ds_params && elems->ds_params_len == 1)
-               freq = ieee80211_channel_to_frequency(elems->ds_params[0]);
+               freq = ieee80211_channel_to_frequency(elems->ds_params[0],
+                                                     band);
        else
                freq = rx_status->freq;
 
index 2563fd1ea9986b6385b67ecf877da494522c38e7..2a57cc02c6189415387cbba01585778a7ab1674a 100644 (file)
@@ -574,7 +574,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
                               &elems);
 
        if (elems.ds_params && elems.ds_params_len == 1)
-               freq = ieee80211_channel_to_frequency(elems.ds_params[0]);
+               freq = ieee80211_channel_to_frequency(elems.ds_params[0], band);
        else
                freq = rx_status->freq;
 
index eecbb1fcd2abbca0163403d9b968cf3606ee9d9d..32210695b8b6caf04c8affbebf9cc592c0997ce1 100644 (file)
@@ -176,7 +176,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
 
        /* check that channel matches the right operating channel */
        if (local->hw.conf.channel->center_freq !=
-           ieee80211_channel_to_frequency(hti->control_chan))
+           ieee80211_channel_to_frequency(hti->control_chan, sband->band))
                enable_ht = false;
 
        if (enable_ht) {
@@ -429,7 +429,8 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
                container_of((void *)bss, struct cfg80211_bss, priv);
        struct ieee80211_channel *new_ch;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-       int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num);
+       int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num,
+                                                     cbss->channel->band);
 
        ASSERT_MGD_MTX(ifmgd);
 
@@ -1519,7 +1520,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
        }
 
        if (elems->ds_params && elems->ds_params_len == 1)
-               freq = ieee80211_channel_to_frequency(elems->ds_params[0]);
+               freq = ieee80211_channel_to_frequency(elems->ds_params[0],
+                                                     rx_status->band);
        else
                freq = rx_status->freq;
 
index fb274db77e3cc73a1b1d9f537966ffc0a8a0cd14..1ef73be76b25eab0678b0b7d83d7b3a87a1ba996 100644 (file)
@@ -196,7 +196,8 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
        ieee802_11_parse_elems(elements, skb->len - baselen, &elems);
 
        if (elems.ds_params && elems.ds_params_len == 1)
-               freq = ieee80211_channel_to_frequency(elems.ds_params[0]);
+               freq = ieee80211_channel_to_frequency(elems.ds_params[0],
+                                                     rx_status->band);
        else
                freq = rx_status->freq;
 
index 37693b6ef23a68c21f9684b6083f1371dc7c5921..c565689f0b9f2069d3d3a7515773ac7a1ae0d0ca 100644 (file)
@@ -1801,9 +1801,9 @@ void regulatory_hint_disconnect(void)
 
 static bool freq_is_chan_12_13_14(u16 freq)
 {
-       if (freq == ieee80211_channel_to_frequency(12) ||
-           freq == ieee80211_channel_to_frequency(13) ||
-           freq == ieee80211_channel_to_frequency(14))
+       if (freq == ieee80211_channel_to_frequency(12, IEEE80211_BAND_2GHZ) ||
+           freq == ieee80211_channel_to_frequency(13, IEEE80211_BAND_2GHZ) ||
+           freq == ieee80211_channel_to_frequency(14, IEEE80211_BAND_2GHZ))
                return true;
        return false;
 }
index 7620ae2fcf18e391c18ee6cfea6f4ec95c73b074..4ed065d8bb515ae2594b113c9be34daa58895197 100644 (file)
@@ -29,29 +29,37 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
 }
 EXPORT_SYMBOL(ieee80211_get_response_rate);
 
-int ieee80211_channel_to_frequency(int chan)
+int ieee80211_channel_to_frequency(int chan, enum ieee80211_band band)
 {
-       if (chan < 14)
-               return 2407 + chan * 5;
-
-       if (chan == 14)
-               return 2484;
-
-       /* FIXME: 802.11j 17.3.8.3.2 */
-       return (chan + 1000) * 5;
+       /* see 802.11 17.3.8.3.2 and Annex J
+        * there are overlapping channel numbers in 5GHz and 2GHz bands */
+       if (band == IEEE80211_BAND_5GHZ) {
+               if (chan >= 182 && chan <= 196)
+                       return 4000 + chan * 5;
+               else
+                       return 5000 + chan * 5;
+       } else { /* IEEE80211_BAND_2GHZ */
+               if (chan == 14)
+                       return 2484;
+               else if (chan < 14)
+                       return 2407 + chan * 5;
+               else
+                       return 0; /* not supported */
+       }
 }
 EXPORT_SYMBOL(ieee80211_channel_to_frequency);
 
 int ieee80211_frequency_to_channel(int freq)
 {
+       /* see 802.11 17.3.8.3.2 and Annex J */
        if (freq == 2484)
                return 14;
-
-       if (freq < 2484)
+       else if (freq < 2484)
                return (freq - 2407) / 5;
-
-       /* FIXME: 802.11j 17.3.8.3.2 */
-       return freq/5 - 1000;
+       else if (freq >= 4910 && freq <= 4980)
+               return (freq - 4000) / 5;
+       else
+               return (freq - 5000) / 5;
 }
 EXPORT_SYMBOL(ieee80211_frequency_to_channel);
 
index 3e5dbd4e4cd5e470f016aaff5c8cff997f60b678..7f1f4ec49041765e5f7c8d5f7be0d6bdb3b2d4cb 100644 (file)
@@ -267,9 +267,12 @@ int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq)
         * -EINVAL for impossible things.
         */
        if (freq->e == 0) {
+               enum ieee80211_band band = IEEE80211_BAND_2GHZ;
                if (freq->m < 0)
                        return 0;
-               return ieee80211_channel_to_frequency(freq->m);
+               if (freq->m > 14)
+                       band = IEEE80211_BAND_5GHZ;
+               return ieee80211_channel_to_frequency(freq->m, band);
        } else {
                int i, div = 1000000;
                for (i = 0; i < freq->e; i++)