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