chan.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. /*
  2. * mac80211 - channel management
  3. */
  4. #include <linux/nl80211.h>
  5. #include <linux/export.h>
  6. #include <linux/rtnetlink.h>
  7. #include <net/cfg80211.h>
  8. #include "ieee80211_i.h"
  9. #include "driver-ops.h"
  10. static void ieee80211_change_chanctx(struct ieee80211_local *local,
  11. struct ieee80211_chanctx *ctx,
  12. const struct cfg80211_chan_def *chandef)
  13. {
  14. if (cfg80211_chandef_identical(&ctx->conf.def, chandef))
  15. return;
  16. WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef));
  17. ctx->conf.def = *chandef;
  18. drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH);
  19. if (!local->use_chanctx) {
  20. local->_oper_chandef = *chandef;
  21. ieee80211_hw_config(local, 0);
  22. }
  23. }
  24. static struct ieee80211_chanctx *
  25. ieee80211_find_chanctx(struct ieee80211_local *local,
  26. const struct cfg80211_chan_def *chandef,
  27. enum ieee80211_chanctx_mode mode)
  28. {
  29. struct ieee80211_chanctx *ctx;
  30. lockdep_assert_held(&local->chanctx_mtx);
  31. if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
  32. return NULL;
  33. list_for_each_entry(ctx, &local->chanctx_list, list) {
  34. const struct cfg80211_chan_def *compat;
  35. if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
  36. continue;
  37. compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef);
  38. if (!compat)
  39. continue;
  40. ieee80211_change_chanctx(local, ctx, compat);
  41. return ctx;
  42. }
  43. return NULL;
  44. }
  45. static bool ieee80211_is_radar_required(struct ieee80211_local *local)
  46. {
  47. struct ieee80211_sub_if_data *sdata;
  48. rcu_read_lock();
  49. list_for_each_entry_rcu(sdata, &local->interfaces, list) {
  50. if (sdata->radar_required) {
  51. rcu_read_unlock();
  52. return true;
  53. }
  54. }
  55. rcu_read_unlock();
  56. return false;
  57. }
  58. static struct ieee80211_chanctx *
  59. ieee80211_new_chanctx(struct ieee80211_local *local,
  60. const struct cfg80211_chan_def *chandef,
  61. enum ieee80211_chanctx_mode mode)
  62. {
  63. struct ieee80211_chanctx *ctx;
  64. int err;
  65. lockdep_assert_held(&local->chanctx_mtx);
  66. ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
  67. if (!ctx)
  68. return ERR_PTR(-ENOMEM);
  69. ctx->conf.def = *chandef;
  70. ctx->conf.rx_chains_static = 1;
  71. ctx->conf.rx_chains_dynamic = 1;
  72. ctx->mode = mode;
  73. ctx->conf.radar_enabled = ieee80211_is_radar_required(local);
  74. if (!local->use_chanctx)
  75. local->hw.conf.radar_enabled = ctx->conf.radar_enabled;
  76. if (!local->use_chanctx) {
  77. local->_oper_chandef = *chandef;
  78. ieee80211_hw_config(local, 0);
  79. } else {
  80. err = drv_add_chanctx(local, ctx);
  81. if (err) {
  82. kfree(ctx);
  83. return ERR_PTR(err);
  84. }
  85. }
  86. list_add_rcu(&ctx->list, &local->chanctx_list);
  87. mutex_lock(&local->mtx);
  88. ieee80211_recalc_idle(local);
  89. mutex_unlock(&local->mtx);
  90. return ctx;
  91. }
  92. static void ieee80211_free_chanctx(struct ieee80211_local *local,
  93. struct ieee80211_chanctx *ctx)
  94. {
  95. bool check_single_channel = false;
  96. lockdep_assert_held(&local->chanctx_mtx);
  97. WARN_ON_ONCE(ctx->refcount != 0);
  98. if (!local->use_chanctx) {
  99. struct cfg80211_chan_def *chandef = &local->_oper_chandef;
  100. chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
  101. chandef->center_freq1 = chandef->chan->center_freq;
  102. chandef->center_freq2 = 0;
  103. /* NOTE: Disabling radar is only valid here for
  104. * single channel context. To be sure, check it ...
  105. */
  106. if (local->hw.conf.radar_enabled)
  107. check_single_channel = true;
  108. local->hw.conf.radar_enabled = false;
  109. ieee80211_hw_config(local, 0);
  110. } else {
  111. drv_remove_chanctx(local, ctx);
  112. }
  113. list_del_rcu(&ctx->list);
  114. kfree_rcu(ctx, rcu_head);
  115. /* throw a warning if this wasn't the only channel context. */
  116. WARN_ON(check_single_channel && !list_empty(&local->chanctx_list));
  117. mutex_lock(&local->mtx);
  118. ieee80211_recalc_idle(local);
  119. mutex_unlock(&local->mtx);
  120. }
  121. static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
  122. struct ieee80211_chanctx *ctx)
  123. {
  124. struct ieee80211_local *local = sdata->local;
  125. int ret;
  126. lockdep_assert_held(&local->chanctx_mtx);
  127. ret = drv_assign_vif_chanctx(local, sdata, ctx);
  128. if (ret)
  129. return ret;
  130. rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf);
  131. ctx->refcount++;
  132. ieee80211_recalc_txpower(sdata);
  133. sdata->vif.bss_conf.idle = false;
  134. if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
  135. sdata->vif.type != NL80211_IFTYPE_MONITOR)
  136. ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
  137. return 0;
  138. }
  139. static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
  140. struct ieee80211_chanctx *ctx)
  141. {
  142. struct ieee80211_chanctx_conf *conf = &ctx->conf;
  143. struct ieee80211_sub_if_data *sdata;
  144. const struct cfg80211_chan_def *compat = NULL;
  145. lockdep_assert_held(&local->chanctx_mtx);
  146. rcu_read_lock();
  147. list_for_each_entry_rcu(sdata, &local->interfaces, list) {
  148. if (!ieee80211_sdata_running(sdata))
  149. continue;
  150. if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
  151. continue;
  152. if (!compat)
  153. compat = &sdata->vif.bss_conf.chandef;
  154. compat = cfg80211_chandef_compatible(
  155. &sdata->vif.bss_conf.chandef, compat);
  156. if (!compat)
  157. break;
  158. }
  159. rcu_read_unlock();
  160. if (WARN_ON_ONCE(!compat))
  161. return;
  162. ieee80211_change_chanctx(local, ctx, compat);
  163. }
  164. static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
  165. struct ieee80211_chanctx *ctx)
  166. {
  167. struct ieee80211_local *local = sdata->local;
  168. lockdep_assert_held(&local->chanctx_mtx);
  169. ctx->refcount--;
  170. rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
  171. sdata->vif.bss_conf.idle = true;
  172. if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
  173. sdata->vif.type != NL80211_IFTYPE_MONITOR)
  174. ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
  175. drv_unassign_vif_chanctx(local, sdata, ctx);
  176. if (ctx->refcount > 0) {
  177. ieee80211_recalc_chanctx_chantype(sdata->local, ctx);
  178. ieee80211_recalc_smps_chanctx(local, ctx);
  179. ieee80211_recalc_radar_chanctx(local, ctx);
  180. }
  181. }
  182. static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
  183. {
  184. struct ieee80211_local *local = sdata->local;
  185. struct ieee80211_chanctx_conf *conf;
  186. struct ieee80211_chanctx *ctx;
  187. lockdep_assert_held(&local->chanctx_mtx);
  188. conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
  189. lockdep_is_held(&local->chanctx_mtx));
  190. if (!conf)
  191. return;
  192. ctx = container_of(conf, struct ieee80211_chanctx, conf);
  193. ieee80211_unassign_vif_chanctx(sdata, ctx);
  194. if (ctx->refcount == 0)
  195. ieee80211_free_chanctx(local, ctx);
  196. }
  197. void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
  198. struct ieee80211_chanctx *chanctx)
  199. {
  200. bool radar_enabled;
  201. lockdep_assert_held(&local->chanctx_mtx);
  202. radar_enabled = ieee80211_is_radar_required(local);
  203. if (radar_enabled == chanctx->conf.radar_enabled)
  204. return;
  205. chanctx->conf.radar_enabled = radar_enabled;
  206. local->radar_detect_enabled = chanctx->conf.radar_enabled;
  207. if (!local->use_chanctx) {
  208. local->hw.conf.radar_enabled = chanctx->conf.radar_enabled;
  209. ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
  210. }
  211. drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
  212. }
  213. void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
  214. struct ieee80211_chanctx *chanctx)
  215. {
  216. struct ieee80211_sub_if_data *sdata;
  217. u8 rx_chains_static, rx_chains_dynamic;
  218. lockdep_assert_held(&local->chanctx_mtx);
  219. rx_chains_static = 1;
  220. rx_chains_dynamic = 1;
  221. rcu_read_lock();
  222. list_for_each_entry_rcu(sdata, &local->interfaces, list) {
  223. u8 needed_static, needed_dynamic;
  224. if (!ieee80211_sdata_running(sdata))
  225. continue;
  226. if (rcu_access_pointer(sdata->vif.chanctx_conf) !=
  227. &chanctx->conf)
  228. continue;
  229. switch (sdata->vif.type) {
  230. case NL80211_IFTYPE_P2P_DEVICE:
  231. continue;
  232. case NL80211_IFTYPE_STATION:
  233. if (!sdata->u.mgd.associated)
  234. continue;
  235. break;
  236. case NL80211_IFTYPE_AP_VLAN:
  237. continue;
  238. case NL80211_IFTYPE_AP:
  239. case NL80211_IFTYPE_ADHOC:
  240. case NL80211_IFTYPE_WDS:
  241. case NL80211_IFTYPE_MESH_POINT:
  242. break;
  243. default:
  244. WARN_ON_ONCE(1);
  245. }
  246. switch (sdata->smps_mode) {
  247. default:
  248. WARN_ONCE(1, "Invalid SMPS mode %d\n",
  249. sdata->smps_mode);
  250. /* fall through */
  251. case IEEE80211_SMPS_OFF:
  252. needed_static = sdata->needed_rx_chains;
  253. needed_dynamic = sdata->needed_rx_chains;
  254. break;
  255. case IEEE80211_SMPS_DYNAMIC:
  256. needed_static = 1;
  257. needed_dynamic = sdata->needed_rx_chains;
  258. break;
  259. case IEEE80211_SMPS_STATIC:
  260. needed_static = 1;
  261. needed_dynamic = 1;
  262. break;
  263. }
  264. rx_chains_static = max(rx_chains_static, needed_static);
  265. rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
  266. }
  267. rcu_read_unlock();
  268. if (!local->use_chanctx) {
  269. if (rx_chains_static > 1)
  270. local->smps_mode = IEEE80211_SMPS_OFF;
  271. else if (rx_chains_dynamic > 1)
  272. local->smps_mode = IEEE80211_SMPS_DYNAMIC;
  273. else
  274. local->smps_mode = IEEE80211_SMPS_STATIC;
  275. ieee80211_hw_config(local, 0);
  276. }
  277. if (rx_chains_static == chanctx->conf.rx_chains_static &&
  278. rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
  279. return;
  280. chanctx->conf.rx_chains_static = rx_chains_static;
  281. chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
  282. drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
  283. }
  284. int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
  285. const struct cfg80211_chan_def *chandef,
  286. enum ieee80211_chanctx_mode mode)
  287. {
  288. struct ieee80211_local *local = sdata->local;
  289. struct ieee80211_chanctx *ctx;
  290. int ret;
  291. WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
  292. mutex_lock(&local->chanctx_mtx);
  293. __ieee80211_vif_release_channel(sdata);
  294. ctx = ieee80211_find_chanctx(local, chandef, mode);
  295. if (!ctx)
  296. ctx = ieee80211_new_chanctx(local, chandef, mode);
  297. if (IS_ERR(ctx)) {
  298. ret = PTR_ERR(ctx);
  299. goto out;
  300. }
  301. sdata->vif.bss_conf.chandef = *chandef;
  302. ret = ieee80211_assign_vif_chanctx(sdata, ctx);
  303. if (ret) {
  304. /* if assign fails refcount stays the same */
  305. if (ctx->refcount == 0)
  306. ieee80211_free_chanctx(local, ctx);
  307. goto out;
  308. }
  309. ieee80211_recalc_smps_chanctx(local, ctx);
  310. ieee80211_recalc_radar_chanctx(local, ctx);
  311. out:
  312. mutex_unlock(&local->chanctx_mtx);
  313. return ret;
  314. }
  315. int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata,
  316. const struct cfg80211_chan_def *chandef,
  317. u32 *changed)
  318. {
  319. struct ieee80211_local *local = sdata->local;
  320. struct ieee80211_chanctx_conf *conf;
  321. struct ieee80211_chanctx *ctx;
  322. int ret;
  323. if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
  324. IEEE80211_CHAN_DISABLED))
  325. return -EINVAL;
  326. mutex_lock(&local->chanctx_mtx);
  327. if (cfg80211_chandef_identical(chandef, &sdata->vif.bss_conf.chandef)) {
  328. ret = 0;
  329. goto out;
  330. }
  331. if (chandef->width == NL80211_CHAN_WIDTH_20_NOHT ||
  332. sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) {
  333. ret = -EINVAL;
  334. goto out;
  335. }
  336. conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
  337. lockdep_is_held(&local->chanctx_mtx));
  338. if (!conf) {
  339. ret = -EINVAL;
  340. goto out;
  341. }
  342. ctx = container_of(conf, struct ieee80211_chanctx, conf);
  343. if (!cfg80211_chandef_compatible(&conf->def, chandef)) {
  344. ret = -EINVAL;
  345. goto out;
  346. }
  347. sdata->vif.bss_conf.chandef = *chandef;
  348. ieee80211_recalc_chanctx_chantype(local, ctx);
  349. *changed |= BSS_CHANGED_BANDWIDTH;
  350. ret = 0;
  351. out:
  352. mutex_unlock(&local->chanctx_mtx);
  353. return ret;
  354. }
  355. void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
  356. {
  357. WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
  358. mutex_lock(&sdata->local->chanctx_mtx);
  359. __ieee80211_vif_release_channel(sdata);
  360. mutex_unlock(&sdata->local->chanctx_mtx);
  361. }
  362. void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
  363. {
  364. struct ieee80211_local *local = sdata->local;
  365. struct ieee80211_sub_if_data *ap;
  366. struct ieee80211_chanctx_conf *conf;
  367. if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
  368. return;
  369. ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
  370. mutex_lock(&local->chanctx_mtx);
  371. conf = rcu_dereference_protected(ap->vif.chanctx_conf,
  372. lockdep_is_held(&local->chanctx_mtx));
  373. rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
  374. mutex_unlock(&local->chanctx_mtx);
  375. }
  376. void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
  377. bool clear)
  378. {
  379. struct ieee80211_local *local = sdata->local;
  380. struct ieee80211_sub_if_data *vlan;
  381. struct ieee80211_chanctx_conf *conf;
  382. ASSERT_RTNL();
  383. if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
  384. return;
  385. mutex_lock(&local->chanctx_mtx);
  386. /*
  387. * Check that conf exists, even when clearing this function
  388. * must be called with the AP's channel context still there
  389. * as it would otherwise cause VLANs to have an invalid
  390. * channel context pointer for a while, possibly pointing
  391. * to a channel context that has already been freed.
  392. */
  393. conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
  394. lockdep_is_held(&local->chanctx_mtx));
  395. WARN_ON(!conf);
  396. if (clear)
  397. conf = NULL;
  398. list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
  399. rcu_assign_pointer(vlan->vif.chanctx_conf, conf);
  400. mutex_unlock(&local->chanctx_mtx);
  401. }
  402. void ieee80211_iter_chan_contexts_atomic(
  403. struct ieee80211_hw *hw,
  404. void (*iter)(struct ieee80211_hw *hw,
  405. struct ieee80211_chanctx_conf *chanctx_conf,
  406. void *data),
  407. void *iter_data)
  408. {
  409. struct ieee80211_local *local = hw_to_local(hw);
  410. struct ieee80211_chanctx *ctx;
  411. rcu_read_lock();
  412. list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
  413. if (ctx->driver_present)
  414. iter(hw, &ctx->conf, iter_data);
  415. rcu_read_unlock();
  416. }
  417. EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);