cfg80211: Extend channel to frequency mapping for 802.11j

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>
This commit is contained in:
Bruno Randolf 2011-01-17 13:37:28 +09:00 committed by John W. Linville
parent 60f2d1d506
commit 59eb21a650
18 changed files with 71 additions and 40 deletions

View File

@ -594,10 +594,11 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
rx_status.flag = 0; rx_status.flag = 0;
rx_status.mactime = le64_to_cpu(rx_end->timestamp); 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) ? rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; 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); rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
if (rx_status.band == IEEE80211_BAND_5GHZ) if (rx_status.band == IEEE80211_BAND_5GHZ)

View 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 carries information about the packet to mac80211 */
rx_status.mactime = le64_to_cpu(phy_res->timestamp); 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) ? rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; 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 = rx_status.rate_idx =
iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
rx_status.flag = 0; rx_status.flag = 0;

View File

@ -227,7 +227,8 @@ int iwlcore_init_geos(struct iwl_priv *priv)
geo_ch = &sband->channels[sband->n_channels++]; geo_ch = &sband->channels[sband->n_channels++];
geo_ch->center_freq = 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_power = ch->max_power_avg;
geo_ch->max_antenna_gain = 0xff; geo_ch->max_antenna_gain = 0xff;
geo_ch->hw_value = ch->channel; geo_ch->hw_value = ch->channel;

View File

@ -287,7 +287,8 @@ int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
return -EINVAL; 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); channel = ieee80211_get_channel(wiphy, freq);
signal = umac_bss->rssi * 100; signal = umac_bss->rssi * 100;

View File

@ -543,7 +543,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
switch (le32_to_cpu(complete->status)) { switch (le32_to_cpu(complete->status)) {
case UMAC_ASSOC_COMPLETE_SUCCESS: case UMAC_ASSOC_COMPLETE_SUCCESS:
chan = ieee80211_get_channel(wiphy, 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) { if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
/* Associated to a unallowed channel, disassociate. */ /* Associated to a unallowed channel, disassociate. */
__iwm_invalidate_mlme_profile(iwm); __iwm_invalidate_mlme_profile(iwm);
@ -841,7 +844,7 @@ static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf,
goto err; 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); channel = ieee80211_get_channel(wiphy, freq);
signal = umac_bss->rssi * 100; signal = umac_bss->rssi * 100;

View File

@ -607,7 +607,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
/* No channel, no luck */ /* No channel, no luck */
if (chan_no != -1) { if (chan_no != -1) {
struct wiphy *wiphy = priv->wdev->wiphy; 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 = struct ieee80211_channel *channel =
ieee80211_get_channel(wiphy, freq); 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); lbs_deb_enter(LBS_DEB_CFG80211);
survey->channel = ieee80211_get_channel(wiphy, 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); ret = lbs_get_rssi(priv, &signal, &noise);
if (ret == 0) { if (ret == 0) {

View File

@ -906,7 +906,8 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
} else { } else {
status->band = IEEE80211_BAND_2GHZ; 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; *qos = rxd->qos_control;
@ -1013,7 +1014,8 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
} else { } else {
status->band = IEEE80211_BAND_2GHZ; 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; *qos = rxd->qos_control;
if ((rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DECRYPT_ERROR) && if ((rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DECRYPT_ERROR) &&

View File

@ -649,7 +649,10 @@ static void rt2x00lib_channel(struct ieee80211_channel *entry,
const int channel, const int tx_power, const int channel, const int tx_power,
const int value) 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->hw_value = value;
entry->max_power = tx_power; entry->max_power = tx_power;
entry->max_antenna_gain = 0xff; entry->max_antenna_gain = 0xff;

View File

@ -78,7 +78,8 @@ static void wl1251_rx_status(struct wl1251 *wl,
*/ */
wl->noise = desc->rssi - desc->snr / 2; 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; status->flag |= RX_FLAG_TSFT;

View File

@ -76,7 +76,7 @@ static void wl1271_rx_status(struct wl1271 *wl,
*/ */
wl->noise = desc->rssi - (desc->snr >> 1); 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) { if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;

View File

@ -1790,8 +1790,9 @@ static inline void *wdev_priv(struct wireless_dev *wdev)
/** /**
* ieee80211_channel_to_frequency - convert channel number to frequency * ieee80211_channel_to_frequency - convert channel number to frequency
* @chan: channel number * @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 * ieee80211_frequency_to_channel - convert frequency to channel number

View File

@ -270,7 +270,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
enum ieee80211_band band = rx_status->band; enum ieee80211_band band = rx_status->band;
if (elems->ds_params && elems->ds_params_len == 1) 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 else
freq = rx_status->freq; freq = rx_status->freq;

View File

@ -574,7 +574,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
&elems); &elems);
if (elems.ds_params && elems.ds_params_len == 1) 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 else
freq = rx_status->freq; freq = rx_status->freq;

View File

@ -176,7 +176,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
/* check that channel matches the right operating channel */ /* check that channel matches the right operating channel */
if (local->hw.conf.channel->center_freq != 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; enable_ht = false;
if (enable_ht) { 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); container_of((void *)bss, struct cfg80211_bss, priv);
struct ieee80211_channel *new_ch; struct ieee80211_channel *new_ch;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 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); 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) 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 else
freq = rx_status->freq; freq = rx_status->freq;

View 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); ieee802_11_parse_elems(elements, skb->len - baselen, &elems);
if (elems.ds_params && elems.ds_params_len == 1) 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 else
freq = rx_status->freq; freq = rx_status->freq;

View File

@ -1801,9 +1801,9 @@ void regulatory_hint_disconnect(void)
static bool freq_is_chan_12_13_14(u16 freq) static bool freq_is_chan_12_13_14(u16 freq)
{ {
if (freq == ieee80211_channel_to_frequency(12) || if (freq == ieee80211_channel_to_frequency(12, IEEE80211_BAND_2GHZ) ||
freq == ieee80211_channel_to_frequency(13) || freq == ieee80211_channel_to_frequency(13, IEEE80211_BAND_2GHZ) ||
freq == ieee80211_channel_to_frequency(14)) freq == ieee80211_channel_to_frequency(14, IEEE80211_BAND_2GHZ))
return true; return true;
return false; return false;
} }

View File

@ -29,29 +29,37 @@ ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
} }
EXPORT_SYMBOL(ieee80211_get_response_rate); 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) /* see 802.11 17.3.8.3.2 and Annex J
return 2407 + chan * 5; * there are overlapping channel numbers in 5GHz and 2GHz bands */
if (band == IEEE80211_BAND_5GHZ) {
if (chan == 14) if (chan >= 182 && chan <= 196)
return 2484; return 4000 + chan * 5;
else
/* FIXME: 802.11j 17.3.8.3.2 */ return 5000 + chan * 5;
return (chan + 1000) * 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); EXPORT_SYMBOL(ieee80211_channel_to_frequency);
int ieee80211_frequency_to_channel(int freq) int ieee80211_frequency_to_channel(int freq)
{ {
/* see 802.11 17.3.8.3.2 and Annex J */
if (freq == 2484) if (freq == 2484)
return 14; return 14;
else if (freq < 2484)
if (freq < 2484)
return (freq - 2407) / 5; return (freq - 2407) / 5;
else if (freq >= 4910 && freq <= 4980)
/* FIXME: 802.11j 17.3.8.3.2 */ return (freq - 4000) / 5;
return freq/5 - 1000; else
return (freq - 5000) / 5;
} }
EXPORT_SYMBOL(ieee80211_frequency_to_channel); EXPORT_SYMBOL(ieee80211_frequency_to_channel);

View File

@ -267,9 +267,12 @@ int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq)
* -EINVAL for impossible things. * -EINVAL for impossible things.
*/ */
if (freq->e == 0) { if (freq->e == 0) {
enum ieee80211_band band = IEEE80211_BAND_2GHZ;
if (freq->m < 0) if (freq->m < 0)
return 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 { } else {
int i, div = 1000000; int i, div = 1000000;
for (i = 0; i < freq->e; i++) for (i = 0; i < freq->e; i++)