linux/net/mac80211/chan.c
<<
>>
Prefs
   1/*
   2 * mac80211 - channel management
   3 */
   4
   5#include <linux/nl80211.h>
   6#include <net/cfg80211.h>
   7#include "ieee80211_i.h"
   8
   9static enum ieee80211_chan_mode
  10__ieee80211_get_channel_mode(struct ieee80211_local *local,
  11                             struct ieee80211_sub_if_data *ignore)
  12{
  13        struct ieee80211_sub_if_data *sdata;
  14
  15        lockdep_assert_held(&local->iflist_mtx);
  16
  17        list_for_each_entry(sdata, &local->interfaces, list) {
  18                if (sdata == ignore)
  19                        continue;
  20
  21                if (!ieee80211_sdata_running(sdata))
  22                        continue;
  23
  24                switch (sdata->vif.type) {
  25                case NL80211_IFTYPE_MONITOR:
  26                        continue;
  27                case NL80211_IFTYPE_STATION:
  28                        if (!sdata->u.mgd.associated)
  29                                continue;
  30                        break;
  31                case NL80211_IFTYPE_ADHOC:
  32                        if (!sdata->u.ibss.ssid_len)
  33                                continue;
  34                        if (!sdata->u.ibss.fixed_channel)
  35                                return CHAN_MODE_HOPPING;
  36                        break;
  37                case NL80211_IFTYPE_AP_VLAN:
  38                        /* will also have _AP interface */
  39                        continue;
  40                case NL80211_IFTYPE_AP:
  41                        if (!sdata->u.ap.beacon)
  42                                continue;
  43                        break;
  44                case NL80211_IFTYPE_MESH_POINT:
  45                        if (!sdata->wdev.mesh_id_len)
  46                                continue;
  47                        break;
  48                default:
  49                        break;
  50                }
  51
  52                return CHAN_MODE_FIXED;
  53        }
  54
  55        return CHAN_MODE_UNDEFINED;
  56}
  57
  58enum ieee80211_chan_mode
  59ieee80211_get_channel_mode(struct ieee80211_local *local,
  60                           struct ieee80211_sub_if_data *ignore)
  61{
  62        enum ieee80211_chan_mode mode;
  63
  64        mutex_lock(&local->iflist_mtx);
  65        mode = __ieee80211_get_channel_mode(local, ignore);
  66        mutex_unlock(&local->iflist_mtx);
  67
  68        return mode;
  69}
  70
  71bool ieee80211_set_channel_type(struct ieee80211_local *local,
  72                                struct ieee80211_sub_if_data *sdata,
  73                                enum nl80211_channel_type chantype)
  74{
  75        struct ieee80211_sub_if_data *tmp;
  76        enum nl80211_channel_type superchan = NL80211_CHAN_NO_HT;
  77        bool result;
  78
  79        mutex_lock(&local->iflist_mtx);
  80
  81        list_for_each_entry(tmp, &local->interfaces, list) {
  82                if (tmp == sdata)
  83                        continue;
  84
  85                if (!ieee80211_sdata_running(tmp))
  86                        continue;
  87
  88                switch (tmp->vif.bss_conf.channel_type) {
  89                case NL80211_CHAN_NO_HT:
  90                case NL80211_CHAN_HT20:
  91                        if (superchan > tmp->vif.bss_conf.channel_type)
  92                                break;
  93
  94                        superchan = tmp->vif.bss_conf.channel_type;
  95                        break;
  96                case NL80211_CHAN_HT40PLUS:
  97                        WARN_ON(superchan == NL80211_CHAN_HT40MINUS);
  98                        superchan = NL80211_CHAN_HT40PLUS;
  99                        break;
 100                case NL80211_CHAN_HT40MINUS:
 101                        WARN_ON(superchan == NL80211_CHAN_HT40PLUS);
 102                        superchan = NL80211_CHAN_HT40MINUS;
 103                        break;
 104                }
 105        }
 106
 107        switch (superchan) {
 108        case NL80211_CHAN_NO_HT:
 109        case NL80211_CHAN_HT20:
 110                /*
 111                 * allow any change that doesn't go to no-HT
 112                 * (if it already is no-HT no change is needed)
 113                 */
 114                if (chantype == NL80211_CHAN_NO_HT)
 115                        break;
 116                superchan = chantype;
 117                break;
 118        case NL80211_CHAN_HT40PLUS:
 119        case NL80211_CHAN_HT40MINUS:
 120                /* allow smaller bandwidth and same */
 121                if (chantype == NL80211_CHAN_NO_HT)
 122                        break;
 123                if (chantype == NL80211_CHAN_HT20)
 124                        break;
 125                if (superchan == chantype)
 126                        break;
 127                result = false;
 128                goto out;
 129        }
 130
 131        local->_oper_channel_type = superchan;
 132
 133        if (sdata)
 134                sdata->vif.bss_conf.channel_type = chantype;
 135
 136        result = true;
 137 out:
 138        mutex_unlock(&local->iflist_mtx);
 139
 140        return result;
 141}
 142
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.