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