[PATCH 2] cfg80211: Extend channel to frequency mapping for 802.11j
Brian Prodoehl
bprodoehl at gmail.com
Mon Jan 17 15:17:31 EST 2011
On Sun, Jan 16, 2011 at 11:37 PM, Bruno Randolf <br1 at einfach.org> wrote:
> 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 at einfach.org>
>
> ---
>
> v2: Added necessary driver changes first posted by Brian Prodoehl.
> Brian, do you want to add your Signed-off-by?
> ---
> drivers/net/wireless/iwlwifi/iwl-3945.c | 5 ++--
> drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 5 ++--
> drivers/net/wireless/iwlwifi/iwl-core.c | 3 +-
> drivers/net/wireless/iwmc3200wifi/cfg80211.c | 3 +-
> drivers/net/wireless/iwmc3200wifi/rx.c | 7 ++++-
> drivers/net/wireless/libertas/cfg.c | 6 +++-
> drivers/net/wireless/mwl8k.c | 6 +++-
> drivers/net/wireless/rt2x00/rt2x00dev.c | 5 +++-
> drivers/net/wireless/wl1251/rx.c | 3 +-
> drivers/net/wireless/wl12xx/rx.c | 2 +
> include/net/cfg80211.h | 3 +-
> net/mac80211/ibss.c | 3 +-
> net/mac80211/mesh.c | 2 +
> net/mac80211/mlme.c | 8 ++++--
> net/mac80211/scan.c | 3 +-
> net/wireless/reg.c | 6 ++--
> net/wireless/util.c | 36 ++++++++++++++++----------
> net/wireless/wext-compat.c | 5 +++-
> 18 files changed, 71 insertions(+), 40 deletions(-)
>
> diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
> index a9b852b..1d9dcd7 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-3945.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
> @@ -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)
> diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
> index 3dee87e..a800318 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
> @@ -1157,10 +1157,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;
> diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
> index efbde1f..a8d4a93 100644
> --- a/drivers/net/wireless/iwlwifi/iwl-core.c
> +++ b/drivers/net/wireless/iwlwifi/iwl-core.c
> @@ -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;
> diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
> index 5a49822..ed57e44 100644
> --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c
> +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
> @@ -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;
>
> diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
> index a944893..9a57cf6 100644
> --- a/drivers/net/wireless/iwmc3200wifi/rx.c
> +++ b/drivers/net/wireless/iwmc3200wifi/rx.c
> @@ -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;
>
> diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
> index 698a1f7..30ef035 100644
> --- a/drivers/net/wireless/libertas/cfg.c
> +++ b/drivers/net/wireless/libertas/cfg.c
> @@ -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) {
> diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
> index 809f2bf..b62f7ef 100644
> --- a/drivers/net/wireless/mwl8k.c
> +++ b/drivers/net/wireless/mwl8k.c
> @@ -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) &&
> diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
> index 9597a03..31b7db0 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
> @@ -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;
> diff --git a/drivers/net/wireless/wl1251/rx.c b/drivers/net/wireless/wl1251/rx.c
> index efa5360..86eef45 100644
> --- a/drivers/net/wireless/wl1251/rx.c
> +++ b/drivers/net/wireless/wl1251/rx.c
> @@ -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;
>
> diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
> index 682304c..ec8d843 100644
> --- a/drivers/net/wireless/wl12xx/rx.c
> +++ b/drivers/net/wireless/wl12xx/rx.c
> @@ -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;
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index 1322695..679a049 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -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
> diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
> index 53c7077..775fb63 100644
> --- a/net/mac80211/ibss.c
> +++ b/net/mac80211/ibss.c
> @@ -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;
>
> diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
> index 2563fd1..2a57cc0 100644
> --- a/net/mac80211/mesh.c
> +++ b/net/mac80211/mesh.c
> @@ -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;
>
> diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
> index 45fbb9e..33bd6d4 100644
> --- a/net/mac80211/mlme.c
> +++ b/net/mac80211/mlme.c
> @@ -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;
>
> diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
> index fb274db..1ef73be 100644
> --- a/net/mac80211/scan.c
> +++ b/net/mac80211/scan.c
> @@ -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;
>
> diff --git a/net/wireless/reg.c b/net/wireless/reg.c
> index 37693b6..c565689 100644
> --- a/net/wireless/reg.c
> +++ b/net/wireless/reg.c
> @@ -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;
> }
> diff --git a/net/wireless/util.c b/net/wireless/util.c
> index 7620ae2..4ed065d 100644
> --- a/net/wireless/util.c
> +++ b/net/wireless/util.c
> @@ -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);
>
> diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
> index 3e5dbd4..7f1f4ec 100644
> --- a/net/wireless/wext-compat.c
> +++ b/net/wireless/wext-compat.c
> @@ -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++)
Yeah, looks good. Is it worth noting that none of the drivers
actually support the 802.11j channels yet? Not sure of the format of
follow-up s-o-b's, so here goes...
Signed-off-by: Brian Prodoehl <bprodoehl at gmail.com>
More information about the libertas-dev
mailing list