diff options
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 365 |
1 files changed, 294 insertions, 71 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0d463c80c404..cee4884b9d06 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -43,7 +43,7 @@ const unsigned char bridge_tunnel_header[] __aligned(2) = | |||
43 | 43 | ||
44 | 44 | ||
45 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 45 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
46 | enum ieee80211_if_types type) | 46 | enum nl80211_iftype type) |
47 | { | 47 | { |
48 | __le16 fc = hdr->frame_control; | 48 | __le16 fc = hdr->frame_control; |
49 | 49 | ||
@@ -77,10 +77,10 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | |||
77 | 77 | ||
78 | if (ieee80211_is_back_req(fc)) { | 78 | if (ieee80211_is_back_req(fc)) { |
79 | switch (type) { | 79 | switch (type) { |
80 | case IEEE80211_IF_TYPE_STA: | 80 | case NL80211_IFTYPE_STATION: |
81 | return hdr->addr2; | 81 | return hdr->addr2; |
82 | case IEEE80211_IF_TYPE_AP: | 82 | case NL80211_IFTYPE_AP: |
83 | case IEEE80211_IF_TYPE_VLAN: | 83 | case NL80211_IFTYPE_AP_VLAN: |
84 | return hdr->addr1; | 84 | return hdr->addr1; |
85 | default: | 85 | default: |
86 | break; /* fall through to the return */ | 86 | break; /* fall through to the return */ |
@@ -91,45 +91,6 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | |||
91 | return NULL; | 91 | return NULL; |
92 | } | 92 | } |
93 | 93 | ||
94 | int ieee80211_get_hdrlen(u16 fc) | ||
95 | { | ||
96 | int hdrlen = 24; | ||
97 | |||
98 | switch (fc & IEEE80211_FCTL_FTYPE) { | ||
99 | case IEEE80211_FTYPE_DATA: | ||
100 | if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) | ||
101 | hdrlen = 30; /* Addr4 */ | ||
102 | /* | ||
103 | * The QoS Control field is two bytes and its presence is | ||
104 | * indicated by the IEEE80211_STYPE_QOS_DATA bit. Add 2 to | ||
105 | * hdrlen if that bit is set. | ||
106 | * This works by masking out the bit and shifting it to | ||
107 | * bit position 1 so the result has the value 0 or 2. | ||
108 | */ | ||
109 | hdrlen += (fc & IEEE80211_STYPE_QOS_DATA) | ||
110 | >> (ilog2(IEEE80211_STYPE_QOS_DATA)-1); | ||
111 | break; | ||
112 | case IEEE80211_FTYPE_CTL: | ||
113 | /* | ||
114 | * ACK and CTS are 10 bytes, all others 16. To see how | ||
115 | * to get this condition consider | ||
116 | * subtype mask: 0b0000000011110000 (0x00F0) | ||
117 | * ACK subtype: 0b0000000011010000 (0x00D0) | ||
118 | * CTS subtype: 0b0000000011000000 (0x00C0) | ||
119 | * bits that matter: ^^^ (0x00E0) | ||
120 | * value of those: 0b0000000011000000 (0x00C0) | ||
121 | */ | ||
122 | if ((fc & 0xE0) == 0xC0) | ||
123 | hdrlen = 10; | ||
124 | else | ||
125 | hdrlen = 16; | ||
126 | break; | ||
127 | } | ||
128 | |||
129 | return hdrlen; | ||
130 | } | ||
131 | EXPORT_SYMBOL(ieee80211_get_hdrlen); | ||
132 | |||
133 | unsigned int ieee80211_hdrlen(__le16 fc) | 94 | unsigned int ieee80211_hdrlen(__le16 fc) |
134 | { | 95 | { |
135 | unsigned int hdrlen = 24; | 96 | unsigned int hdrlen = 24; |
@@ -270,16 +231,21 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | |||
270 | struct ieee80211_rate *rate) | 231 | struct ieee80211_rate *rate) |
271 | { | 232 | { |
272 | struct ieee80211_local *local = hw_to_local(hw); | 233 | struct ieee80211_local *local = hw_to_local(hw); |
273 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 234 | struct ieee80211_sub_if_data *sdata; |
274 | u16 dur; | 235 | u16 dur; |
275 | int erp; | 236 | int erp; |
237 | bool short_preamble = false; | ||
276 | 238 | ||
277 | erp = 0; | 239 | erp = 0; |
278 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 240 | if (vif) { |
279 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 241 | sdata = vif_to_sdata(vif); |
242 | short_preamble = sdata->bss_conf.use_short_preamble; | ||
243 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | ||
244 | erp = rate->flags & IEEE80211_RATE_ERP_G; | ||
245 | } | ||
280 | 246 | ||
281 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, | 247 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, |
282 | sdata->bss_conf.use_short_preamble); | 248 | short_preamble); |
283 | 249 | ||
284 | return cpu_to_le16(dur); | 250 | return cpu_to_le16(dur); |
285 | } | 251 | } |
@@ -291,7 +257,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
291 | { | 257 | { |
292 | struct ieee80211_local *local = hw_to_local(hw); | 258 | struct ieee80211_local *local = hw_to_local(hw); |
293 | struct ieee80211_rate *rate; | 259 | struct ieee80211_rate *rate; |
294 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 260 | struct ieee80211_sub_if_data *sdata; |
295 | bool short_preamble; | 261 | bool short_preamble; |
296 | int erp; | 262 | int erp; |
297 | u16 dur; | 263 | u16 dur; |
@@ -299,13 +265,17 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
299 | 265 | ||
300 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 266 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
301 | 267 | ||
302 | short_preamble = sdata->bss_conf.use_short_preamble; | 268 | short_preamble = false; |
303 | 269 | ||
304 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; | 270 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; |
305 | 271 | ||
306 | erp = 0; | 272 | erp = 0; |
307 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 273 | if (vif) { |
308 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 274 | sdata = vif_to_sdata(vif); |
275 | short_preamble = sdata->bss_conf.use_short_preamble; | ||
276 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | ||
277 | erp = rate->flags & IEEE80211_RATE_ERP_G; | ||
278 | } | ||
309 | 279 | ||
310 | /* CTS duration */ | 280 | /* CTS duration */ |
311 | dur = ieee80211_frame_duration(local, 10, rate->bitrate, | 281 | dur = ieee80211_frame_duration(local, 10, rate->bitrate, |
@@ -328,7 +298,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
328 | { | 298 | { |
329 | struct ieee80211_local *local = hw_to_local(hw); | 299 | struct ieee80211_local *local = hw_to_local(hw); |
330 | struct ieee80211_rate *rate; | 300 | struct ieee80211_rate *rate; |
331 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 301 | struct ieee80211_sub_if_data *sdata; |
332 | bool short_preamble; | 302 | bool short_preamble; |
333 | int erp; | 303 | int erp; |
334 | u16 dur; | 304 | u16 dur; |
@@ -336,12 +306,16 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
336 | 306 | ||
337 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 307 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
338 | 308 | ||
339 | short_preamble = sdata->bss_conf.use_short_preamble; | 309 | short_preamble = false; |
340 | 310 | ||
341 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; | 311 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; |
342 | erp = 0; | 312 | erp = 0; |
343 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 313 | if (vif) { |
344 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 314 | sdata = vif_to_sdata(vif); |
315 | short_preamble = sdata->bss_conf.use_short_preamble; | ||
316 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | ||
317 | erp = rate->flags & IEEE80211_RATE_ERP_G; | ||
318 | } | ||
345 | 319 | ||
346 | /* Data frame duration */ | 320 | /* Data frame duration */ |
347 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, | 321 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, |
@@ -386,6 +360,13 @@ void ieee80211_stop_queues(struct ieee80211_hw *hw) | |||
386 | } | 360 | } |
387 | EXPORT_SYMBOL(ieee80211_stop_queues); | 361 | EXPORT_SYMBOL(ieee80211_stop_queues); |
388 | 362 | ||
363 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) | ||
364 | { | ||
365 | struct ieee80211_local *local = hw_to_local(hw); | ||
366 | return __netif_subqueue_stopped(local->mdev, queue); | ||
367 | } | ||
368 | EXPORT_SYMBOL(ieee80211_queue_stopped); | ||
369 | |||
389 | void ieee80211_wake_queues(struct ieee80211_hw *hw) | 370 | void ieee80211_wake_queues(struct ieee80211_hw *hw) |
390 | { | 371 | { |
391 | int i; | 372 | int i; |
@@ -408,15 +389,16 @@ void ieee80211_iterate_active_interfaces( | |||
408 | 389 | ||
409 | list_for_each_entry(sdata, &local->interfaces, list) { | 390 | list_for_each_entry(sdata, &local->interfaces, list) { |
410 | switch (sdata->vif.type) { | 391 | switch (sdata->vif.type) { |
411 | case IEEE80211_IF_TYPE_INVALID: | 392 | case __NL80211_IFTYPE_AFTER_LAST: |
412 | case IEEE80211_IF_TYPE_MNTR: | 393 | case NL80211_IFTYPE_UNSPECIFIED: |
413 | case IEEE80211_IF_TYPE_VLAN: | 394 | case NL80211_IFTYPE_MONITOR: |
395 | case NL80211_IFTYPE_AP_VLAN: | ||
414 | continue; | 396 | continue; |
415 | case IEEE80211_IF_TYPE_AP: | 397 | case NL80211_IFTYPE_AP: |
416 | case IEEE80211_IF_TYPE_STA: | 398 | case NL80211_IFTYPE_STATION: |
417 | case IEEE80211_IF_TYPE_IBSS: | 399 | case NL80211_IFTYPE_ADHOC: |
418 | case IEEE80211_IF_TYPE_WDS: | 400 | case NL80211_IFTYPE_WDS: |
419 | case IEEE80211_IF_TYPE_MESH_POINT: | 401 | case NL80211_IFTYPE_MESH_POINT: |
420 | break; | 402 | break; |
421 | } | 403 | } |
422 | if (netif_running(sdata->dev)) | 404 | if (netif_running(sdata->dev)) |
@@ -441,15 +423,16 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
441 | 423 | ||
442 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 424 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
443 | switch (sdata->vif.type) { | 425 | switch (sdata->vif.type) { |
444 | case IEEE80211_IF_TYPE_INVALID: | 426 | case __NL80211_IFTYPE_AFTER_LAST: |
445 | case IEEE80211_IF_TYPE_MNTR: | 427 | case NL80211_IFTYPE_UNSPECIFIED: |
446 | case IEEE80211_IF_TYPE_VLAN: | 428 | case NL80211_IFTYPE_MONITOR: |
429 | case NL80211_IFTYPE_AP_VLAN: | ||
447 | continue; | 430 | continue; |
448 | case IEEE80211_IF_TYPE_AP: | 431 | case NL80211_IFTYPE_AP: |
449 | case IEEE80211_IF_TYPE_STA: | 432 | case NL80211_IFTYPE_STATION: |
450 | case IEEE80211_IF_TYPE_IBSS: | 433 | case NL80211_IFTYPE_ADHOC: |
451 | case IEEE80211_IF_TYPE_WDS: | 434 | case NL80211_IFTYPE_WDS: |
452 | case IEEE80211_IF_TYPE_MESH_POINT: | 435 | case NL80211_IFTYPE_MESH_POINT: |
453 | break; | 436 | break; |
454 | } | 437 | } |
455 | if (netif_running(sdata->dev)) | 438 | if (netif_running(sdata->dev)) |
@@ -460,3 +443,243 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
460 | rcu_read_unlock(); | 443 | rcu_read_unlock(); |
461 | } | 444 | } |
462 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); | 445 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); |
446 | |||
447 | void ieee802_11_parse_elems(u8 *start, size_t len, | ||
448 | struct ieee802_11_elems *elems) | ||
449 | { | ||
450 | size_t left = len; | ||
451 | u8 *pos = start; | ||
452 | |||
453 | memset(elems, 0, sizeof(*elems)); | ||
454 | elems->ie_start = start; | ||
455 | elems->total_len = len; | ||
456 | |||
457 | while (left >= 2) { | ||
458 | u8 id, elen; | ||
459 | |||
460 | id = *pos++; | ||
461 | elen = *pos++; | ||
462 | left -= 2; | ||
463 | |||
464 | if (elen > left) | ||
465 | return; | ||
466 | |||
467 | switch (id) { | ||
468 | case WLAN_EID_SSID: | ||
469 | elems->ssid = pos; | ||
470 | elems->ssid_len = elen; | ||
471 | break; | ||
472 | case WLAN_EID_SUPP_RATES: | ||
473 | elems->supp_rates = pos; | ||
474 | elems->supp_rates_len = elen; | ||
475 | break; | ||
476 | case WLAN_EID_FH_PARAMS: | ||
477 | elems->fh_params = pos; | ||
478 | elems->fh_params_len = elen; | ||
479 | break; | ||
480 | case WLAN_EID_DS_PARAMS: | ||
481 | elems->ds_params = pos; | ||
482 | elems->ds_params_len = elen; | ||
483 | break; | ||
484 | case WLAN_EID_CF_PARAMS: | ||
485 | elems->cf_params = pos; | ||
486 | elems->cf_params_len = elen; | ||
487 | break; | ||
488 | case WLAN_EID_TIM: | ||
489 | elems->tim = pos; | ||
490 | elems->tim_len = elen; | ||
491 | break; | ||
492 | case WLAN_EID_IBSS_PARAMS: | ||
493 | elems->ibss_params = pos; | ||
494 | elems->ibss_params_len = elen; | ||
495 | break; | ||
496 | case WLAN_EID_CHALLENGE: | ||
497 | elems->challenge = pos; | ||
498 | elems->challenge_len = elen; | ||
499 | break; | ||
500 | case WLAN_EID_WPA: | ||
501 | if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && | ||
502 | pos[2] == 0xf2) { | ||
503 | /* Microsoft OUI (00:50:F2) */ | ||
504 | if (pos[3] == 1) { | ||
505 | /* OUI Type 1 - WPA IE */ | ||
506 | elems->wpa = pos; | ||
507 | elems->wpa_len = elen; | ||
508 | } else if (elen >= 5 && pos[3] == 2) { | ||
509 | if (pos[4] == 0) { | ||
510 | elems->wmm_info = pos; | ||
511 | elems->wmm_info_len = elen; | ||
512 | } else if (pos[4] == 1) { | ||
513 | elems->wmm_param = pos; | ||
514 | elems->wmm_param_len = elen; | ||
515 | } | ||
516 | } | ||
517 | } | ||
518 | break; | ||
519 | case WLAN_EID_RSN: | ||
520 | elems->rsn = pos; | ||
521 | elems->rsn_len = elen; | ||
522 | break; | ||
523 | case WLAN_EID_ERP_INFO: | ||
524 | elems->erp_info = pos; | ||
525 | elems->erp_info_len = elen; | ||
526 | break; | ||
527 | case WLAN_EID_EXT_SUPP_RATES: | ||
528 | elems->ext_supp_rates = pos; | ||
529 | elems->ext_supp_rates_len = elen; | ||
530 | break; | ||
531 | case WLAN_EID_HT_CAPABILITY: | ||
532 | if (elen >= sizeof(struct ieee80211_ht_cap)) | ||
533 | elems->ht_cap_elem = (void *)pos; | ||
534 | break; | ||
535 | case WLAN_EID_HT_EXTRA_INFO: | ||
536 | if (elen >= sizeof(struct ieee80211_ht_addt_info)) | ||
537 | elems->ht_info_elem = (void *)pos; | ||
538 | break; | ||
539 | case WLAN_EID_MESH_ID: | ||
540 | elems->mesh_id = pos; | ||
541 | elems->mesh_id_len = elen; | ||
542 | break; | ||
543 | case WLAN_EID_MESH_CONFIG: | ||
544 | elems->mesh_config = pos; | ||
545 | elems->mesh_config_len = elen; | ||
546 | break; | ||
547 | case WLAN_EID_PEER_LINK: | ||
548 | elems->peer_link = pos; | ||
549 | elems->peer_link_len = elen; | ||
550 | break; | ||
551 | case WLAN_EID_PREQ: | ||
552 | elems->preq = pos; | ||
553 | elems->preq_len = elen; | ||
554 | break; | ||
555 | case WLAN_EID_PREP: | ||
556 | elems->prep = pos; | ||
557 | elems->prep_len = elen; | ||
558 | break; | ||
559 | case WLAN_EID_PERR: | ||
560 | elems->perr = pos; | ||
561 | elems->perr_len = elen; | ||
562 | break; | ||
563 | case WLAN_EID_CHANNEL_SWITCH: | ||
564 | elems->ch_switch_elem = pos; | ||
565 | elems->ch_switch_elem_len = elen; | ||
566 | break; | ||
567 | case WLAN_EID_QUIET: | ||
568 | if (!elems->quiet_elem) { | ||
569 | elems->quiet_elem = pos; | ||
570 | elems->quiet_elem_len = elen; | ||
571 | } | ||
572 | elems->num_of_quiet_elem++; | ||
573 | break; | ||
574 | case WLAN_EID_COUNTRY: | ||
575 | elems->country_elem = pos; | ||
576 | elems->country_elem_len = elen; | ||
577 | break; | ||
578 | case WLAN_EID_PWR_CONSTRAINT: | ||
579 | elems->pwr_constr_elem = pos; | ||
580 | elems->pwr_constr_elem_len = elen; | ||
581 | break; | ||
582 | default: | ||
583 | break; | ||
584 | } | ||
585 | |||
586 | left -= elen; | ||
587 | pos += elen; | ||
588 | } | ||
589 | } | ||
590 | |||
591 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | ||
592 | { | ||
593 | struct ieee80211_local *local = sdata->local; | ||
594 | struct ieee80211_tx_queue_params qparam; | ||
595 | int i; | ||
596 | |||
597 | if (!local->ops->conf_tx) | ||
598 | return; | ||
599 | |||
600 | memset(&qparam, 0, sizeof(qparam)); | ||
601 | |||
602 | qparam.aifs = 2; | ||
603 | |||
604 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | ||
605 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) | ||
606 | qparam.cw_min = 31; | ||
607 | else | ||
608 | qparam.cw_min = 15; | ||
609 | |||
610 | qparam.cw_max = 1023; | ||
611 | qparam.txop = 0; | ||
612 | |||
613 | for (i = 0; i < local_to_hw(local)->queues; i++) | ||
614 | local->ops->conf_tx(local_to_hw(local), i, &qparam); | ||
615 | } | ||
616 | |||
617 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
618 | int encrypt) | ||
619 | { | ||
620 | skb->dev = sdata->local->mdev; | ||
621 | skb_set_mac_header(skb, 0); | ||
622 | skb_set_network_header(skb, 0); | ||
623 | skb_set_transport_header(skb, 0); | ||
624 | |||
625 | skb->iif = sdata->dev->ifindex; | ||
626 | skb->do_not_encrypt = !encrypt; | ||
627 | |||
628 | dev_queue_xmit(skb); | ||
629 | } | ||
630 | |||
631 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) | ||
632 | { | ||
633 | int ret = -EINVAL; | ||
634 | struct ieee80211_channel *chan; | ||
635 | struct ieee80211_local *local = sdata->local; | ||
636 | |||
637 | chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); | ||
638 | |||
639 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | ||
640 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
641 | chan->flags & IEEE80211_CHAN_NO_IBSS) { | ||
642 | printk(KERN_DEBUG "%s: IBSS not allowed on frequency " | ||
643 | "%d MHz\n", sdata->dev->name, chan->center_freq); | ||
644 | return ret; | ||
645 | } | ||
646 | local->oper_channel = chan; | ||
647 | |||
648 | if (local->sw_scanning || local->hw_scanning) | ||
649 | ret = 0; | ||
650 | else | ||
651 | ret = ieee80211_hw_config(local); | ||
652 | |||
653 | rate_control_clear(local); | ||
654 | } | ||
655 | |||
656 | return ret; | ||
657 | } | ||
658 | |||
659 | u64 ieee80211_mandatory_rates(struct ieee80211_local *local, | ||
660 | enum ieee80211_band band) | ||
661 | { | ||
662 | struct ieee80211_supported_band *sband; | ||
663 | struct ieee80211_rate *bitrates; | ||
664 | u64 mandatory_rates; | ||
665 | enum ieee80211_rate_flags mandatory_flag; | ||
666 | int i; | ||
667 | |||
668 | sband = local->hw.wiphy->bands[band]; | ||
669 | if (!sband) { | ||
670 | WARN_ON(1); | ||
671 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
672 | } | ||
673 | |||
674 | if (band == IEEE80211_BAND_2GHZ) | ||
675 | mandatory_flag = IEEE80211_RATE_MANDATORY_B; | ||
676 | else | ||
677 | mandatory_flag = IEEE80211_RATE_MANDATORY_A; | ||
678 | |||
679 | bitrates = sband->bitrates; | ||
680 | mandatory_rates = 0; | ||
681 | for (i = 0; i < sband->n_bitrates; i++) | ||
682 | if (bitrates[i].flags & mandatory_flag) | ||
683 | mandatory_rates |= BIT(i); | ||
684 | return mandatory_rates; | ||
685 | } | ||