aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211_ioctl.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-01-24 13:38:38 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-02-29 15:19:32 -0500
commit8318d78a44d49ac1edf2bdec7299de3617c4232e (patch)
treed434634418edd7399737801615d247be06616fdd /net/mac80211/ieee80211_ioctl.c
parent10b6b80145cc93887dd8aab99bfffa375e9add31 (diff)
cfg80211 API for channels/bitrates, mac80211 and driver conversion
This patch creates new cfg80211 wiphy API for channel and bitrate registration and converts mac80211 and drivers to the new API. The old mac80211 API is completely ripped out. All drivers (except ath5k) are updated to the new API, in many cases I expect that optimisations can be done. Along with the regulatory code I've also ripped out the IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED flag, I believe it to be unnecessary if the hardware simply gives us whatever channels it wants to support and we then enable/disable them as required, which is pretty much required for travelling. Additionally, the patch adds proper "basic" rate handling for STA mode interface, AP mode interface will have to have new API added to allow userspace to set the basic rate set, currently it'll be empty... However, the basic rate handling will need to be moved to the BSS conf stuff. I do expect there to be bugs in this, especially wrt. transmit power handling where I'm basically clueless about how it should work. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/ieee80211_ioctl.c')
-rw-r--r--net/mac80211/ieee80211_ioctl.c127
1 files changed, 66 insertions, 61 deletions
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c
index 5024d3733834..54ad07aafe2d 100644
--- a/net/mac80211/ieee80211_ioctl.c
+++ b/net/mac80211/ieee80211_ioctl.c
@@ -129,22 +129,7 @@ static int ieee80211_ioctl_giwname(struct net_device *dev,
129 struct iw_request_info *info, 129 struct iw_request_info *info,
130 char *name, char *extra) 130 char *name, char *extra)
131{ 131{
132 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 132 strcpy(name, "IEEE 802.11");
133
134 switch (local->hw.conf.phymode) {
135 case MODE_IEEE80211A:
136 strcpy(name, "IEEE 802.11a");
137 break;
138 case MODE_IEEE80211B:
139 strcpy(name, "IEEE 802.11b");
140 break;
141 case MODE_IEEE80211G:
142 strcpy(name, "IEEE 802.11g");
143 break;
144 default:
145 strcpy(name, "IEEE 802.11");
146 break;
147 }
148 133
149 return 0; 134 return 0;
150} 135}
@@ -156,7 +141,7 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev,
156{ 141{
157 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 142 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
158 struct iw_range *range = (struct iw_range *) extra; 143 struct iw_range *range = (struct iw_range *) extra;
159 struct ieee80211_hw_mode *mode = NULL; 144 enum ieee80211_band band;
160 int c = 0; 145 int c = 0;
161 146
162 data->length = sizeof(struct iw_range); 147 data->length = sizeof(struct iw_range);
@@ -191,24 +176,27 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev,
191 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | 176 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
192 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; 177 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
193 178
194 list_for_each_entry(mode, &local->modes_list, list) {
195 int i = 0;
196 179
197 if (!(local->enabled_modes & (1 << mode->mode)) || 180 for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
198 (local->hw_modes & local->enabled_modes & 181 int i;
199 (1 << MODE_IEEE80211G) && mode->mode == MODE_IEEE80211B)) 182 struct ieee80211_supported_band *sband;
183
184 sband = local->hw.wiphy->bands[band];
185
186 if (!sband)
200 continue; 187 continue;
201 188
202 while (i < mode->num_channels && c < IW_MAX_FREQUENCIES) { 189 for (i = 0; i < sband->n_channels && c < IW_MAX_FREQUENCIES; i++) {
203 struct ieee80211_channel *chan = &mode->channels[i]; 190 struct ieee80211_channel *chan = &sband->channels[i];
204 191
205 if (chan->flag & IEEE80211_CHAN_W_SCAN) { 192 if (!(chan->flags & IEEE80211_CHAN_DISABLED)) {
206 range->freq[c].i = chan->chan; 193 range->freq[c].i =
207 range->freq[c].m = chan->freq * 100000; 194 ieee80211_frequency_to_channel(
208 range->freq[c].e = 1; 195 chan->center_freq);
196 range->freq[c].m = chan->center_freq;
197 range->freq[c].e = 6;
209 c++; 198 c++;
210 } 199 }
211 i++;
212 } 200 }
213 } 201 }
214 range->num_channels = c; 202 range->num_channels = c;
@@ -294,22 +282,29 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev,
294 return 0; 282 return 0;
295} 283}
296 284
297int ieee80211_set_channel(struct ieee80211_local *local, int channel, int freq) 285int ieee80211_set_freq(struct ieee80211_local *local, int freqMHz)
298{ 286{
299 struct ieee80211_hw_mode *mode; 287 int set = 0;
300 int c, set = 0;
301 int ret = -EINVAL; 288 int ret = -EINVAL;
289 enum ieee80211_band band;
290 struct ieee80211_supported_band *sband;
291 int i;
292
293 for (band = 0; band < IEEE80211_NUM_BANDS; band ++) {
294 sband = local->hw.wiphy->bands[band];
302 295
303 list_for_each_entry(mode, &local->modes_list, list) { 296 if (!sband)
304 if (!(local->enabled_modes & (1 << mode->mode)))
305 continue; 297 continue;
306 for (c = 0; c < mode->num_channels; c++) { 298
307 struct ieee80211_channel *chan = &mode->channels[c]; 299 for (i = 0; i < sband->n_channels; i++) {
308 if (chan->flag & IEEE80211_CHAN_W_SCAN && 300 struct ieee80211_channel *chan = &sband->channels[i];
309 ((chan->chan == channel) || (chan->freq == freq))) { 301
310 local->oper_channel = chan; 302 if (chan->flags & IEEE80211_CHAN_DISABLED)
311 local->oper_hw_mode = mode; 303 continue;
304
305 if (chan->center_freq == freqMHz) {
312 set = 1; 306 set = 1;
307 local->oper_channel = chan;
313 break; 308 break;
314 } 309 }
315 } 310 }
@@ -347,13 +342,14 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev,
347 IEEE80211_STA_AUTO_CHANNEL_SEL; 342 IEEE80211_STA_AUTO_CHANNEL_SEL;
348 return 0; 343 return 0;
349 } else 344 } else
350 return ieee80211_set_channel(local, freq->m, -1); 345 return ieee80211_set_freq(local,
346 ieee80211_channel_to_frequency(freq->m));
351 } else { 347 } else {
352 int i, div = 1000000; 348 int i, div = 1000000;
353 for (i = 0; i < freq->e; i++) 349 for (i = 0; i < freq->e; i++)
354 div /= 10; 350 div /= 10;
355 if (div > 0) 351 if (div > 0)
356 return ieee80211_set_channel(local, -1, freq->m / div); 352 return ieee80211_set_freq(local, freq->m / div);
357 else 353 else
358 return -EINVAL; 354 return -EINVAL;
359 } 355 }
@@ -366,10 +362,7 @@ static int ieee80211_ioctl_giwfreq(struct net_device *dev,
366{ 362{
367 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 363 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
368 364
369 /* TODO: in station mode (Managed/Ad-hoc) might need to poll low-level 365 freq->m = local->hw.conf.channel->center_freq;
370 * driver for the current channel with firmware-based management */
371
372 freq->m = local->hw.conf.freq;
373 freq->e = 6; 366 freq->e = 6;
374 367
375 return 0; 368 return 0;
@@ -566,15 +559,17 @@ static int ieee80211_ioctl_siwrate(struct net_device *dev,
566 struct iw_param *rate, char *extra) 559 struct iw_param *rate, char *extra)
567{ 560{
568 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 561 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
569 struct ieee80211_hw_mode *mode; 562 int i, err = -EINVAL;
570 int i;
571 u32 target_rate = rate->value / 100000; 563 u32 target_rate = rate->value / 100000;
572 struct ieee80211_sub_if_data *sdata; 564 struct ieee80211_sub_if_data *sdata;
565 struct ieee80211_supported_band *sband;
573 566
574 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 567 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
575 if (!sdata->bss) 568 if (!sdata->bss)
576 return -ENODEV; 569 return -ENODEV;
577 mode = local->oper_hw_mode; 570
571 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
572
578 /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates 573 /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
579 * target_rate = X, rate->fixed = 1 means only rate X 574 * target_rate = X, rate->fixed = 1 means only rate X
580 * target_rate = X, rate->fixed = 0 means all rates <= X */ 575 * target_rate = X, rate->fixed = 0 means all rates <= X */
@@ -582,18 +577,20 @@ static int ieee80211_ioctl_siwrate(struct net_device *dev,
582 sdata->bss->force_unicast_rateidx = -1; 577 sdata->bss->force_unicast_rateidx = -1;
583 if (rate->value < 0) 578 if (rate->value < 0)
584 return 0; 579 return 0;
585 for (i=0; i < mode->num_rates; i++) { 580
586 struct ieee80211_rate *rates = &mode->rates[i]; 581 for (i=0; i< sband->n_bitrates; i++) {
587 int this_rate = rates->rate; 582 struct ieee80211_rate *brate = &sband->bitrates[i];
583 int this_rate = brate->bitrate;
588 584
589 if (target_rate == this_rate) { 585 if (target_rate == this_rate) {
590 sdata->bss->max_ratectrl_rateidx = i; 586 sdata->bss->max_ratectrl_rateidx = i;
591 if (rate->fixed) 587 if (rate->fixed)
592 sdata->bss->force_unicast_rateidx = i; 588 sdata->bss->force_unicast_rateidx = i;
593 return 0; 589 err = 0;
590 break;
594 } 591 }
595 } 592 }
596 return -EINVAL; 593 return err;
597} 594}
598 595
599static int ieee80211_ioctl_giwrate(struct net_device *dev, 596static int ieee80211_ioctl_giwrate(struct net_device *dev,
@@ -603,18 +600,24 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev,
603 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 600 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
604 struct sta_info *sta; 601 struct sta_info *sta;
605 struct ieee80211_sub_if_data *sdata; 602 struct ieee80211_sub_if_data *sdata;
603 struct ieee80211_supported_band *sband;
606 604
607 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 605 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
606
608 if (sdata->vif.type == IEEE80211_IF_TYPE_STA) 607 if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
609 sta = sta_info_get(local, sdata->u.sta.bssid); 608 sta = sta_info_get(local, sdata->u.sta.bssid);
610 else 609 else
611 return -EOPNOTSUPP; 610 return -EOPNOTSUPP;
612 if (!sta) 611 if (!sta)
613 return -ENODEV; 612 return -ENODEV;
614 if (sta->txrate < local->oper_hw_mode->num_rates) 613
615 rate->value = local->oper_hw_mode->rates[sta->txrate].rate * 100000; 614 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
615
616 if (sta->txrate_idx < sband->n_bitrates)
617 rate->value = sband->bitrates[sta->txrate_idx].bitrate;
616 else 618 else
617 rate->value = 0; 619 rate->value = 0;
620 rate->value *= 100000;
618 sta_info_put(sta); 621 sta_info_put(sta);
619 return 0; 622 return 0;
620} 623}
@@ -625,7 +628,7 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
625{ 628{
626 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 629 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
627 bool need_reconfig = 0; 630 bool need_reconfig = 0;
628 u8 new_power_level; 631 int new_power_level;
629 632
630 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) 633 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
631 return -EINVAL; 634 return -EINVAL;
@@ -635,13 +638,15 @@ static int ieee80211_ioctl_siwtxpower(struct net_device *dev,
635 if (data->txpower.fixed) { 638 if (data->txpower.fixed) {
636 new_power_level = data->txpower.value; 639 new_power_level = data->txpower.value;
637 } else { 640 } else {
638 /* Automatic power level. Get the px power from the current 641 /*
639 * channel. */ 642 * Automatic power level. Use maximum power for the current
640 struct ieee80211_channel* chan = local->oper_channel; 643 * channel. Should be part of rate control.
644 */
645 struct ieee80211_channel* chan = local->hw.conf.channel;
641 if (!chan) 646 if (!chan)
642 return -EINVAL; 647 return -EINVAL;
643 648
644 new_power_level = chan->power_level; 649 new_power_level = chan->max_power;
645 } 650 }
646 651
647 if (local->hw.conf.power_level != new_power_level) { 652 if (local->hw.conf.power_level != new_power_level) {