aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211_ioctl.c
diff options
context:
space:
mode:
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) {