chan.c 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * mac80211 - channel management
  4. * Copyright 2020 - 2024 Intel Corporation
  5. */
  6. #include <linux/nl80211.h>
  7. #include <linux/export.h>
  8. #include <linux/rtnetlink.h>
  9. #include <net/cfg80211.h>
  10. #include "ieee80211_i.h"
  11. #include "driver-ops.h"
  12. #include "rate.h"
  13. static int ieee80211_chanctx_num_assigned(struct ieee80211_local *local,
  14. struct ieee80211_chanctx *ctx)
  15. {
  16. struct ieee80211_link_data *link;
  17. int num = 0;
  18. lockdep_assert_wiphy(local->hw.wiphy);
  19. list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list)
  20. num++;
  21. return num;
  22. }
  23. static int ieee80211_chanctx_num_reserved(struct ieee80211_local *local,
  24. struct ieee80211_chanctx *ctx)
  25. {
  26. struct ieee80211_link_data *link;
  27. int num = 0;
  28. lockdep_assert_wiphy(local->hw.wiphy);
  29. list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list)
  30. num++;
  31. return num;
  32. }
  33. int ieee80211_chanctx_refcount(struct ieee80211_local *local,
  34. struct ieee80211_chanctx *ctx)
  35. {
  36. return ieee80211_chanctx_num_assigned(local, ctx) +
  37. ieee80211_chanctx_num_reserved(local, ctx);
  38. }
  39. static int ieee80211_num_chanctx(struct ieee80211_local *local, int radio_idx)
  40. {
  41. struct ieee80211_chanctx *ctx;
  42. int num = 0;
  43. lockdep_assert_wiphy(local->hw.wiphy);
  44. list_for_each_entry(ctx, &local->chanctx_list, list) {
  45. if (radio_idx >= 0 && ctx->conf.radio_idx != radio_idx)
  46. continue;
  47. num++;
  48. }
  49. return num;
  50. }
  51. static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local,
  52. int radio_idx)
  53. {
  54. lockdep_assert_wiphy(local->hw.wiphy);
  55. return ieee80211_num_chanctx(local, radio_idx) <
  56. ieee80211_max_num_channels(local, radio_idx);
  57. }
  58. static struct ieee80211_chanctx *
  59. ieee80211_link_get_chanctx(struct ieee80211_link_data *link)
  60. {
  61. struct ieee80211_local *local __maybe_unused = link->sdata->local;
  62. struct ieee80211_chanctx_conf *conf;
  63. conf = rcu_dereference_protected(link->conf->chanctx_conf,
  64. lockdep_is_held(&local->hw.wiphy->mtx));
  65. if (!conf)
  66. return NULL;
  67. return container_of(conf, struct ieee80211_chanctx, conf);
  68. }
  69. bool ieee80211_chanreq_identical(const struct ieee80211_chan_req *a,
  70. const struct ieee80211_chan_req *b)
  71. {
  72. if (!cfg80211_chandef_identical(&a->oper, &b->oper))
  73. return false;
  74. if (!a->ap.chan && !b->ap.chan)
  75. return true;
  76. return cfg80211_chandef_identical(&a->ap, &b->ap);
  77. }
  78. static const struct ieee80211_chan_req *
  79. ieee80211_chanreq_compatible(const struct ieee80211_chan_req *a,
  80. const struct ieee80211_chan_req *b,
  81. struct ieee80211_chan_req *tmp)
  82. {
  83. const struct cfg80211_chan_def *compat;
  84. if (a->ap.chan && b->ap.chan &&
  85. !cfg80211_chandef_identical(&a->ap, &b->ap))
  86. return NULL;
  87. compat = cfg80211_chandef_compatible(&a->oper, &b->oper);
  88. if (!compat)
  89. return NULL;
  90. /* Note: later code assumes this always fills & returns tmp if compat */
  91. tmp->oper = *compat;
  92. tmp->ap = a->ap.chan ? a->ap : b->ap;
  93. return tmp;
  94. }
  95. static const struct ieee80211_chan_req *
  96. ieee80211_chanctx_compatible(struct ieee80211_chanctx *ctx,
  97. const struct ieee80211_chan_req *req,
  98. struct ieee80211_chan_req *tmp)
  99. {
  100. const struct ieee80211_chan_req *ret;
  101. struct ieee80211_chan_req tmp2;
  102. *tmp = (struct ieee80211_chan_req){
  103. .oper = ctx->conf.def,
  104. .ap = ctx->conf.ap,
  105. };
  106. ret = ieee80211_chanreq_compatible(tmp, req, &tmp2);
  107. if (!ret)
  108. return NULL;
  109. *tmp = *ret;
  110. return tmp;
  111. }
  112. static const struct ieee80211_chan_req *
  113. ieee80211_chanctx_reserved_chanreq(struct ieee80211_local *local,
  114. struct ieee80211_chanctx *ctx,
  115. const struct ieee80211_chan_req *req,
  116. struct ieee80211_chan_req *tmp)
  117. {
  118. struct ieee80211_link_data *link;
  119. lockdep_assert_wiphy(local->hw.wiphy);
  120. if (WARN_ON(!req))
  121. return NULL;
  122. list_for_each_entry(link, &ctx->reserved_links, reserved_chanctx_list) {
  123. req = ieee80211_chanreq_compatible(&link->reserved, req, tmp);
  124. if (!req)
  125. break;
  126. }
  127. return req;
  128. }
  129. static const struct ieee80211_chan_req *
  130. ieee80211_chanctx_non_reserved_chandef(struct ieee80211_local *local,
  131. struct ieee80211_chanctx *ctx,
  132. const struct ieee80211_chan_req *compat,
  133. struct ieee80211_chan_req *tmp)
  134. {
  135. struct ieee80211_link_data *link;
  136. const struct ieee80211_chan_req *comp_def = compat;
  137. lockdep_assert_wiphy(local->hw.wiphy);
  138. list_for_each_entry(link, &ctx->assigned_links, assigned_chanctx_list) {
  139. struct ieee80211_bss_conf *link_conf = link->conf;
  140. if (link->reserved_chanctx)
  141. continue;
  142. comp_def = ieee80211_chanreq_compatible(&link_conf->chanreq,
  143. comp_def, tmp);
  144. if (!comp_def)
  145. break;
  146. }
  147. return comp_def;
  148. }
  149. static bool
  150. ieee80211_chanctx_can_reserve(struct ieee80211_local *local,
  151. struct ieee80211_chanctx *ctx,
  152. const struct ieee80211_chan_req *req)
  153. {
  154. struct ieee80211_chan_req tmp;
  155. lockdep_assert_wiphy(local->hw.wiphy);
  156. if (!ieee80211_chanctx_reserved_chanreq(local, ctx, req, &tmp))
  157. return false;
  158. if (!ieee80211_chanctx_non_reserved_chandef(local, ctx, req, &tmp))
  159. return false;
  160. if (!list_empty(&ctx->reserved_links) &&
  161. ieee80211_chanctx_reserved_chanreq(local, ctx, req, &tmp))
  162. return true;
  163. return false;
  164. }
  165. static struct ieee80211_chanctx *
  166. ieee80211_find_reservation_chanctx(struct ieee80211_local *local,
  167. const struct ieee80211_chan_req *chanreq,
  168. enum ieee80211_chanctx_mode mode)
  169. {
  170. struct ieee80211_chanctx *ctx;
  171. lockdep_assert_wiphy(local->hw.wiphy);
  172. if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
  173. return NULL;
  174. list_for_each_entry(ctx, &local->chanctx_list, list) {
  175. if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
  176. continue;
  177. if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
  178. continue;
  179. if (!ieee80211_chanctx_can_reserve(local, ctx, chanreq))
  180. continue;
  181. return ctx;
  182. }
  183. return NULL;
  184. }
  185. static enum nl80211_chan_width ieee80211_get_sta_bw(struct sta_info *sta,
  186. unsigned int link_id)
  187. {
  188. enum ieee80211_sta_rx_bandwidth width;
  189. struct link_sta_info *link_sta;
  190. link_sta = wiphy_dereference(sta->local->hw.wiphy, sta->link[link_id]);
  191. /* no effect if this STA has no presence on this link */
  192. if (!link_sta)
  193. return NL80211_CHAN_WIDTH_20_NOHT;
  194. width = ieee80211_sta_cap_rx_bw(link_sta);
  195. switch (width) {
  196. case IEEE80211_STA_RX_BW_20:
  197. if (link_sta->pub->ht_cap.ht_supported)
  198. return NL80211_CHAN_WIDTH_20;
  199. else
  200. return NL80211_CHAN_WIDTH_20_NOHT;
  201. case IEEE80211_STA_RX_BW_40:
  202. return NL80211_CHAN_WIDTH_40;
  203. case IEEE80211_STA_RX_BW_80:
  204. return NL80211_CHAN_WIDTH_80;
  205. case IEEE80211_STA_RX_BW_160:
  206. /*
  207. * This applied for both 160 and 80+80. since we use
  208. * the returned value to consider degradation of
  209. * ctx->conf.min_def, we have to make sure to take
  210. * the bigger one (NL80211_CHAN_WIDTH_160).
  211. * Otherwise we might try degrading even when not
  212. * needed, as the max required sta_bw returned (80+80)
  213. * might be smaller than the configured bw (160).
  214. */
  215. return NL80211_CHAN_WIDTH_160;
  216. case IEEE80211_STA_RX_BW_320:
  217. return NL80211_CHAN_WIDTH_320;
  218. default:
  219. WARN_ON(1);
  220. return NL80211_CHAN_WIDTH_20;
  221. }
  222. }
  223. static enum nl80211_chan_width
  224. ieee80211_get_max_required_bw(struct ieee80211_link_data *link)
  225. {
  226. struct ieee80211_sub_if_data *sdata = link->sdata;
  227. unsigned int link_id = link->link_id;
  228. enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
  229. struct sta_info *sta;
  230. lockdep_assert_wiphy(sdata->local->hw.wiphy);
  231. list_for_each_entry(sta, &sdata->local->sta_list, list) {
  232. if (sdata != sta->sdata &&
  233. !(sta->sdata->bss && sta->sdata->bss == sdata->bss))
  234. continue;
  235. max_bw = max(max_bw, ieee80211_get_sta_bw(sta, link_id));
  236. }
  237. return max_bw;
  238. }
  239. static enum nl80211_chan_width
  240. ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
  241. struct ieee80211_chanctx *ctx,
  242. struct ieee80211_link_data *rsvd_for,
  243. bool check_reserved)
  244. {
  245. struct ieee80211_sub_if_data *sdata;
  246. struct ieee80211_link_data *link;
  247. enum nl80211_chan_width max_bw = NL80211_CHAN_WIDTH_20_NOHT;
  248. if (WARN_ON(check_reserved && rsvd_for))
  249. return ctx->conf.def.width;
  250. for_each_sdata_link(local, link) {
  251. enum nl80211_chan_width width = NL80211_CHAN_WIDTH_20_NOHT;
  252. if (check_reserved) {
  253. if (link->reserved_chanctx != ctx)
  254. continue;
  255. } else if (link != rsvd_for &&
  256. rcu_access_pointer(link->conf->chanctx_conf) != &ctx->conf)
  257. continue;
  258. switch (link->sdata->vif.type) {
  259. case NL80211_IFTYPE_AP:
  260. case NL80211_IFTYPE_AP_VLAN:
  261. width = ieee80211_get_max_required_bw(link);
  262. break;
  263. case NL80211_IFTYPE_STATION:
  264. /*
  265. * The ap's sta->bandwidth is not set yet at this
  266. * point, so take the width from the chandef, but
  267. * account also for TDLS peers
  268. */
  269. width = max(link->conf->chanreq.oper.width,
  270. ieee80211_get_max_required_bw(link));
  271. break;
  272. case NL80211_IFTYPE_P2P_DEVICE:
  273. case NL80211_IFTYPE_NAN:
  274. continue;
  275. case NL80211_IFTYPE_ADHOC:
  276. case NL80211_IFTYPE_MESH_POINT:
  277. case NL80211_IFTYPE_OCB:
  278. width = link->conf->chanreq.oper.width;
  279. break;
  280. case NL80211_IFTYPE_WDS:
  281. case NL80211_IFTYPE_UNSPECIFIED:
  282. case NUM_NL80211_IFTYPES:
  283. case NL80211_IFTYPE_MONITOR:
  284. case NL80211_IFTYPE_P2P_CLIENT:
  285. case NL80211_IFTYPE_P2P_GO:
  286. WARN_ON_ONCE(1);
  287. }
  288. max_bw = max(max_bw, width);
  289. }
  290. /* use the configured bandwidth in case of monitor interface */
  291. sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
  292. if (sdata &&
  293. rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &ctx->conf)
  294. max_bw = max(max_bw, ctx->conf.def.width);
  295. return max_bw;
  296. }
  297. /*
  298. * recalc the min required chan width of the channel context, which is
  299. * the max of min required widths of all the interfaces bound to this
  300. * channel context.
  301. */
  302. static u32
  303. _ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
  304. struct ieee80211_chanctx *ctx,
  305. struct ieee80211_link_data *rsvd_for,
  306. bool check_reserved)
  307. {
  308. enum nl80211_chan_width max_bw;
  309. struct cfg80211_chan_def min_def;
  310. lockdep_assert_wiphy(local->hw.wiphy);
  311. /* don't optimize non-20MHz based and radar_enabled confs */
  312. if (ctx->conf.def.width == NL80211_CHAN_WIDTH_5 ||
  313. ctx->conf.def.width == NL80211_CHAN_WIDTH_10 ||
  314. ctx->conf.def.width == NL80211_CHAN_WIDTH_1 ||
  315. ctx->conf.def.width == NL80211_CHAN_WIDTH_2 ||
  316. ctx->conf.def.width == NL80211_CHAN_WIDTH_4 ||
  317. ctx->conf.def.width == NL80211_CHAN_WIDTH_8 ||
  318. ctx->conf.def.width == NL80211_CHAN_WIDTH_16 ||
  319. ctx->conf.radar_enabled) {
  320. ctx->conf.min_def = ctx->conf.def;
  321. return 0;
  322. }
  323. max_bw = ieee80211_get_chanctx_max_required_bw(local, ctx, rsvd_for,
  324. check_reserved);
  325. /* downgrade chandef up to max_bw */
  326. min_def = ctx->conf.def;
  327. while (min_def.width > max_bw)
  328. ieee80211_chandef_downgrade(&min_def, NULL);
  329. if (cfg80211_chandef_identical(&ctx->conf.min_def, &min_def))
  330. return 0;
  331. ctx->conf.min_def = min_def;
  332. if (!ctx->driver_present)
  333. return 0;
  334. return IEEE80211_CHANCTX_CHANGE_MIN_WIDTH;
  335. }
  336. static void ieee80211_chan_bw_change(struct ieee80211_local *local,
  337. struct ieee80211_chanctx *ctx,
  338. bool reserved, bool narrowed)
  339. {
  340. struct sta_info *sta;
  341. struct ieee80211_supported_band *sband =
  342. local->hw.wiphy->bands[ctx->conf.def.chan->band];
  343. rcu_read_lock();
  344. list_for_each_entry_rcu(sta, &local->sta_list,
  345. list) {
  346. struct ieee80211_sub_if_data *sdata = sta->sdata;
  347. enum ieee80211_sta_rx_bandwidth new_sta_bw;
  348. unsigned int link_id;
  349. if (!ieee80211_sdata_running(sta->sdata))
  350. continue;
  351. for (link_id = 0; link_id < ARRAY_SIZE(sta->sdata->link); link_id++) {
  352. struct ieee80211_link_data *link =
  353. rcu_dereference(sdata->link[link_id]);
  354. struct ieee80211_bss_conf *link_conf;
  355. struct cfg80211_chan_def *new_chandef;
  356. struct link_sta_info *link_sta;
  357. if (!link)
  358. continue;
  359. link_conf = link->conf;
  360. if (rcu_access_pointer(link_conf->chanctx_conf) != &ctx->conf)
  361. continue;
  362. link_sta = rcu_dereference(sta->link[link_id]);
  363. if (!link_sta)
  364. continue;
  365. if (reserved)
  366. new_chandef = &link->reserved.oper;
  367. else
  368. new_chandef = &link_conf->chanreq.oper;
  369. new_sta_bw = _ieee80211_sta_cur_vht_bw(link_sta,
  370. new_chandef);
  371. /* nothing change */
  372. if (new_sta_bw == link_sta->pub->bandwidth)
  373. continue;
  374. /* vif changed to narrow BW and narrow BW for station wasn't
  375. * requested or vise versa */
  376. if ((new_sta_bw < link_sta->pub->bandwidth) == !narrowed)
  377. continue;
  378. link_sta->pub->bandwidth = new_sta_bw;
  379. rate_control_rate_update(local, sband, sta, link_id,
  380. IEEE80211_RC_BW_CHANGED);
  381. }
  382. }
  383. rcu_read_unlock();
  384. }
  385. /*
  386. * recalc the min required chan width of the channel context, which is
  387. * the max of min required widths of all the interfaces bound to this
  388. * channel context.
  389. */
  390. void ieee80211_recalc_chanctx_min_def(struct ieee80211_local *local,
  391. struct ieee80211_chanctx *ctx,
  392. struct ieee80211_link_data *rsvd_for,
  393. bool check_reserved)
  394. {
  395. u32 changed = _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for,
  396. check_reserved);
  397. if (!changed)
  398. return;
  399. /* check is BW narrowed */
  400. ieee80211_chan_bw_change(local, ctx, false, true);
  401. drv_change_chanctx(local, ctx, changed);
  402. /* check is BW wider */
  403. ieee80211_chan_bw_change(local, ctx, false, false);
  404. }
  405. static void _ieee80211_change_chanctx(struct ieee80211_local *local,
  406. struct ieee80211_chanctx *ctx,
  407. struct ieee80211_chanctx *old_ctx,
  408. const struct ieee80211_chan_req *chanreq,
  409. struct ieee80211_link_data *rsvd_for)
  410. {
  411. const struct cfg80211_chan_def *chandef = &chanreq->oper;
  412. struct ieee80211_chan_req ctx_req = {
  413. .oper = ctx->conf.def,
  414. .ap = ctx->conf.ap,
  415. };
  416. u32 changed = 0;
  417. /* expected to handle only 20/40/80/160/320 channel widths */
  418. switch (chandef->width) {
  419. case NL80211_CHAN_WIDTH_20_NOHT:
  420. case NL80211_CHAN_WIDTH_20:
  421. case NL80211_CHAN_WIDTH_40:
  422. case NL80211_CHAN_WIDTH_80:
  423. case NL80211_CHAN_WIDTH_80P80:
  424. case NL80211_CHAN_WIDTH_160:
  425. case NL80211_CHAN_WIDTH_320:
  426. break;
  427. default:
  428. WARN_ON(1);
  429. }
  430. /* Check maybe BW narrowed - we do this _before_ calling recalc_chanctx_min_def
  431. * due to maybe not returning from it, e.g in case new context was added
  432. * first time with all parameters up to date.
  433. */
  434. ieee80211_chan_bw_change(local, old_ctx, false, true);
  435. if (ieee80211_chanreq_identical(&ctx_req, chanreq)) {
  436. ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, false);
  437. return;
  438. }
  439. WARN_ON(ieee80211_chanctx_refcount(local, ctx) > 1 &&
  440. !cfg80211_chandef_compatible(&ctx->conf.def, &chanreq->oper));
  441. ieee80211_remove_wbrf(local, &ctx->conf.def);
  442. if (!cfg80211_chandef_identical(&ctx->conf.def, &chanreq->oper)) {
  443. if (ctx->conf.def.width != chanreq->oper.width)
  444. changed |= IEEE80211_CHANCTX_CHANGE_WIDTH;
  445. if (ctx->conf.def.punctured != chanreq->oper.punctured)
  446. changed |= IEEE80211_CHANCTX_CHANGE_PUNCTURING;
  447. }
  448. if (!cfg80211_chandef_identical(&ctx->conf.ap, &chanreq->ap))
  449. changed |= IEEE80211_CHANCTX_CHANGE_AP;
  450. ctx->conf.def = *chandef;
  451. ctx->conf.ap = chanreq->ap;
  452. /* check if min chanctx also changed */
  453. changed |= _ieee80211_recalc_chanctx_min_def(local, ctx, rsvd_for, false);
  454. ieee80211_add_wbrf(local, &ctx->conf.def);
  455. drv_change_chanctx(local, ctx, changed);
  456. /* check if BW is wider */
  457. ieee80211_chan_bw_change(local, old_ctx, false, false);
  458. }
  459. static void ieee80211_change_chanctx(struct ieee80211_local *local,
  460. struct ieee80211_chanctx *ctx,
  461. struct ieee80211_chanctx *old_ctx,
  462. const struct ieee80211_chan_req *chanreq)
  463. {
  464. _ieee80211_change_chanctx(local, ctx, old_ctx, chanreq, NULL);
  465. }
  466. /* Note: if successful, the returned chanctx is reserved for the link */
  467. static struct ieee80211_chanctx *
  468. ieee80211_find_chanctx(struct ieee80211_local *local,
  469. struct ieee80211_link_data *link,
  470. const struct ieee80211_chan_req *chanreq,
  471. enum ieee80211_chanctx_mode mode)
  472. {
  473. struct ieee80211_chan_req tmp;
  474. struct ieee80211_chanctx *ctx;
  475. lockdep_assert_wiphy(local->hw.wiphy);
  476. if (mode == IEEE80211_CHANCTX_EXCLUSIVE)
  477. return NULL;
  478. if (WARN_ON(link->reserved_chanctx))
  479. return NULL;
  480. list_for_each_entry(ctx, &local->chanctx_list, list) {
  481. const struct ieee80211_chan_req *compat;
  482. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACE_NONE)
  483. continue;
  484. if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE)
  485. continue;
  486. compat = ieee80211_chanctx_compatible(ctx, chanreq, &tmp);
  487. if (!compat)
  488. continue;
  489. compat = ieee80211_chanctx_reserved_chanreq(local, ctx,
  490. compat, &tmp);
  491. if (!compat)
  492. continue;
  493. /*
  494. * Reserve the chanctx temporarily, as the driver might change
  495. * active links during callbacks we make into it below and/or
  496. * later during assignment, which could (otherwise) cause the
  497. * context to actually be removed.
  498. */
  499. link->reserved_chanctx = ctx;
  500. list_add(&link->reserved_chanctx_list,
  501. &ctx->reserved_links);
  502. ieee80211_change_chanctx(local, ctx, ctx, compat);
  503. return ctx;
  504. }
  505. return NULL;
  506. }
  507. bool ieee80211_is_radar_required(struct ieee80211_local *local)
  508. {
  509. struct ieee80211_link_data *link;
  510. lockdep_assert_wiphy(local->hw.wiphy);
  511. for_each_sdata_link(local, link) {
  512. if (link->radar_required)
  513. return true;
  514. }
  515. return false;
  516. }
  517. static bool
  518. ieee80211_chanctx_radar_required(struct ieee80211_local *local,
  519. struct ieee80211_chanctx *ctx)
  520. {
  521. struct ieee80211_chanctx_conf *conf = &ctx->conf;
  522. struct ieee80211_link_data *link;
  523. lockdep_assert_wiphy(local->hw.wiphy);
  524. for_each_sdata_link(local, link) {
  525. if (rcu_access_pointer(link->conf->chanctx_conf) != conf)
  526. continue;
  527. if (!link->radar_required)
  528. continue;
  529. return true;
  530. }
  531. return false;
  532. }
  533. static struct ieee80211_chanctx *
  534. ieee80211_alloc_chanctx(struct ieee80211_local *local,
  535. const struct ieee80211_chan_req *chanreq,
  536. enum ieee80211_chanctx_mode mode,
  537. int radio_idx)
  538. {
  539. struct ieee80211_chanctx *ctx;
  540. lockdep_assert_wiphy(local->hw.wiphy);
  541. ctx = kzalloc(sizeof(*ctx) + local->hw.chanctx_data_size, GFP_KERNEL);
  542. if (!ctx)
  543. return NULL;
  544. INIT_LIST_HEAD(&ctx->assigned_links);
  545. INIT_LIST_HEAD(&ctx->reserved_links);
  546. ctx->conf.def = chanreq->oper;
  547. ctx->conf.ap = chanreq->ap;
  548. ctx->conf.rx_chains_static = 1;
  549. ctx->conf.rx_chains_dynamic = 1;
  550. ctx->mode = mode;
  551. ctx->conf.radar_enabled = false;
  552. ctx->conf.radio_idx = radio_idx;
  553. ctx->radar_detected = false;
  554. _ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false);
  555. return ctx;
  556. }
  557. static int ieee80211_add_chanctx(struct ieee80211_local *local,
  558. struct ieee80211_chanctx *ctx)
  559. {
  560. u32 changed;
  561. int err;
  562. lockdep_assert_wiphy(local->hw.wiphy);
  563. ieee80211_add_wbrf(local, &ctx->conf.def);
  564. /* turn idle off *before* setting channel -- some drivers need that */
  565. changed = ieee80211_idle_off(local);
  566. if (changed)
  567. ieee80211_hw_config(local, changed);
  568. err = drv_add_chanctx(local, ctx);
  569. if (err) {
  570. ieee80211_recalc_idle(local);
  571. return err;
  572. }
  573. return 0;
  574. }
  575. static struct ieee80211_chanctx *
  576. ieee80211_new_chanctx(struct ieee80211_local *local,
  577. const struct ieee80211_chan_req *chanreq,
  578. enum ieee80211_chanctx_mode mode,
  579. bool assign_on_failure,
  580. int radio_idx)
  581. {
  582. struct ieee80211_chanctx *ctx;
  583. int err;
  584. lockdep_assert_wiphy(local->hw.wiphy);
  585. ctx = ieee80211_alloc_chanctx(local, chanreq, mode, radio_idx);
  586. if (!ctx)
  587. return ERR_PTR(-ENOMEM);
  588. err = ieee80211_add_chanctx(local, ctx);
  589. if (!assign_on_failure && err) {
  590. kfree(ctx);
  591. return ERR_PTR(err);
  592. }
  593. /* We ignored a driver error, see _ieee80211_set_active_links */
  594. WARN_ON_ONCE(err && !local->in_reconfig);
  595. list_add_rcu(&ctx->list, &local->chanctx_list);
  596. return ctx;
  597. }
  598. static void ieee80211_del_chanctx(struct ieee80211_local *local,
  599. struct ieee80211_chanctx *ctx,
  600. bool skip_idle_recalc)
  601. {
  602. lockdep_assert_wiphy(local->hw.wiphy);
  603. drv_remove_chanctx(local, ctx);
  604. if (!skip_idle_recalc)
  605. ieee80211_recalc_idle(local);
  606. ieee80211_remove_wbrf(local, &ctx->conf.def);
  607. }
  608. static void ieee80211_free_chanctx(struct ieee80211_local *local,
  609. struct ieee80211_chanctx *ctx,
  610. bool skip_idle_recalc)
  611. {
  612. lockdep_assert_wiphy(local->hw.wiphy);
  613. WARN_ON_ONCE(ieee80211_chanctx_refcount(local, ctx) != 0);
  614. list_del_rcu(&ctx->list);
  615. ieee80211_del_chanctx(local, ctx, skip_idle_recalc);
  616. kfree_rcu(ctx, rcu_head);
  617. }
  618. void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
  619. struct ieee80211_chanctx *ctx)
  620. {
  621. struct ieee80211_chanctx_conf *conf = &ctx->conf;
  622. const struct ieee80211_chan_req *compat = NULL;
  623. struct ieee80211_link_data *link;
  624. struct ieee80211_chan_req tmp;
  625. struct sta_info *sta;
  626. lockdep_assert_wiphy(local->hw.wiphy);
  627. for_each_sdata_link(local, link) {
  628. struct ieee80211_bss_conf *link_conf;
  629. if (link->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
  630. continue;
  631. link_conf = link->conf;
  632. if (rcu_access_pointer(link_conf->chanctx_conf) != conf)
  633. continue;
  634. if (!compat)
  635. compat = &link_conf->chanreq;
  636. compat = ieee80211_chanreq_compatible(&link_conf->chanreq,
  637. compat, &tmp);
  638. if (WARN_ON_ONCE(!compat))
  639. return;
  640. }
  641. if (WARN_ON_ONCE(!compat))
  642. return;
  643. /* TDLS peers can sometimes affect the chandef width */
  644. list_for_each_entry(sta, &local->sta_list, list) {
  645. struct ieee80211_sub_if_data *sdata = sta->sdata;
  646. struct ieee80211_chan_req tdls_chanreq = {};
  647. int tdls_link_id;
  648. if (!sta->uploaded ||
  649. !test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW) ||
  650. !test_sta_flag(sta, WLAN_STA_AUTHORIZED) ||
  651. !sta->tdls_chandef.chan)
  652. continue;
  653. tdls_link_id = ieee80211_tdls_sta_link_id(sta);
  654. link = sdata_dereference(sdata->link[tdls_link_id], sdata);
  655. if (!link)
  656. continue;
  657. if (rcu_access_pointer(link->conf->chanctx_conf) != conf)
  658. continue;
  659. tdls_chanreq.oper = sta->tdls_chandef;
  660. /* note this always fills and returns &tmp if compat */
  661. compat = ieee80211_chanreq_compatible(&tdls_chanreq,
  662. compat, &tmp);
  663. if (WARN_ON_ONCE(!compat))
  664. return;
  665. }
  666. ieee80211_change_chanctx(local, ctx, ctx, compat);
  667. }
  668. static void ieee80211_recalc_radar_chanctx(struct ieee80211_local *local,
  669. struct ieee80211_chanctx *chanctx)
  670. {
  671. bool radar_enabled;
  672. lockdep_assert_wiphy(local->hw.wiphy);
  673. radar_enabled = ieee80211_chanctx_radar_required(local, chanctx);
  674. if (radar_enabled == chanctx->conf.radar_enabled)
  675. return;
  676. chanctx->conf.radar_enabled = radar_enabled;
  677. drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RADAR);
  678. }
  679. static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
  680. struct ieee80211_chanctx *new_ctx,
  681. bool assign_on_failure)
  682. {
  683. struct ieee80211_sub_if_data *sdata = link->sdata;
  684. struct ieee80211_local *local = sdata->local;
  685. struct ieee80211_chanctx_conf *conf;
  686. struct ieee80211_chanctx *curr_ctx = NULL;
  687. bool new_idle;
  688. int ret;
  689. if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN))
  690. return -EOPNOTSUPP;
  691. conf = rcu_dereference_protected(link->conf->chanctx_conf,
  692. lockdep_is_held(&local->hw.wiphy->mtx));
  693. if (conf) {
  694. curr_ctx = container_of(conf, struct ieee80211_chanctx, conf);
  695. drv_unassign_vif_chanctx(local, sdata, link->conf, curr_ctx);
  696. conf = NULL;
  697. list_del(&link->assigned_chanctx_list);
  698. }
  699. if (new_ctx) {
  700. /* recalc considering the link we'll use it for now */
  701. ieee80211_recalc_chanctx_min_def(local, new_ctx, link, false);
  702. ret = drv_assign_vif_chanctx(local, sdata, link->conf, new_ctx);
  703. if (assign_on_failure || !ret) {
  704. /* Need to continue, see _ieee80211_set_active_links */
  705. WARN_ON_ONCE(ret && !local->in_reconfig);
  706. ret = 0;
  707. /* succeeded, so commit it to the data structures */
  708. conf = &new_ctx->conf;
  709. list_add(&link->assigned_chanctx_list,
  710. &new_ctx->assigned_links);
  711. }
  712. } else {
  713. ret = 0;
  714. }
  715. rcu_assign_pointer(link->conf->chanctx_conf, conf);
  716. if (curr_ctx && ieee80211_chanctx_num_assigned(local, curr_ctx) > 0) {
  717. ieee80211_recalc_chanctx_chantype(local, curr_ctx);
  718. ieee80211_recalc_smps_chanctx(local, curr_ctx);
  719. ieee80211_recalc_radar_chanctx(local, curr_ctx);
  720. ieee80211_recalc_chanctx_min_def(local, curr_ctx, NULL, false);
  721. }
  722. if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) {
  723. ieee80211_recalc_txpower(sdata, false);
  724. ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL, false);
  725. }
  726. if (conf) {
  727. new_idle = false;
  728. } else {
  729. struct ieee80211_link_data *tmp;
  730. new_idle = true;
  731. for_each_sdata_link(local, tmp) {
  732. if (rcu_access_pointer(tmp->conf->chanctx_conf)) {
  733. new_idle = false;
  734. break;
  735. }
  736. }
  737. }
  738. if (new_idle != sdata->vif.cfg.idle) {
  739. sdata->vif.cfg.idle = new_idle;
  740. if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
  741. sdata->vif.type != NL80211_IFTYPE_MONITOR)
  742. ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE);
  743. }
  744. ieee80211_check_fast_xmit_iface(sdata);
  745. return ret;
  746. }
  747. void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
  748. struct ieee80211_chanctx *chanctx)
  749. {
  750. struct ieee80211_sub_if_data *sdata;
  751. u8 rx_chains_static, rx_chains_dynamic;
  752. struct ieee80211_link_data *link;
  753. lockdep_assert_wiphy(local->hw.wiphy);
  754. rx_chains_static = 1;
  755. rx_chains_dynamic = 1;
  756. for_each_sdata_link(local, link) {
  757. u8 needed_static, needed_dynamic;
  758. switch (link->sdata->vif.type) {
  759. case NL80211_IFTYPE_STATION:
  760. if (!link->sdata->u.mgd.associated)
  761. continue;
  762. break;
  763. case NL80211_IFTYPE_AP:
  764. case NL80211_IFTYPE_ADHOC:
  765. case NL80211_IFTYPE_MESH_POINT:
  766. case NL80211_IFTYPE_OCB:
  767. break;
  768. default:
  769. continue;
  770. }
  771. if (rcu_access_pointer(link->conf->chanctx_conf) != &chanctx->conf)
  772. continue;
  773. switch (link->smps_mode) {
  774. default:
  775. WARN_ONCE(1, "Invalid SMPS mode %d\n",
  776. link->smps_mode);
  777. fallthrough;
  778. case IEEE80211_SMPS_OFF:
  779. needed_static = link->needed_rx_chains;
  780. needed_dynamic = link->needed_rx_chains;
  781. break;
  782. case IEEE80211_SMPS_DYNAMIC:
  783. needed_static = 1;
  784. needed_dynamic = link->needed_rx_chains;
  785. break;
  786. case IEEE80211_SMPS_STATIC:
  787. needed_static = 1;
  788. needed_dynamic = 1;
  789. break;
  790. }
  791. rx_chains_static = max(rx_chains_static, needed_static);
  792. rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
  793. }
  794. /* Disable SMPS for the monitor interface */
  795. sdata = wiphy_dereference(local->hw.wiphy, local->monitor_sdata);
  796. if (sdata &&
  797. rcu_access_pointer(sdata->vif.bss_conf.chanctx_conf) == &chanctx->conf)
  798. rx_chains_dynamic = rx_chains_static = local->rx_chains;
  799. if (rx_chains_static == chanctx->conf.rx_chains_static &&
  800. rx_chains_dynamic == chanctx->conf.rx_chains_dynamic)
  801. return;
  802. chanctx->conf.rx_chains_static = rx_chains_static;
  803. chanctx->conf.rx_chains_dynamic = rx_chains_dynamic;
  804. drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
  805. }
  806. static void
  807. __ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
  808. bool clear)
  809. {
  810. struct ieee80211_sub_if_data *sdata = link->sdata;
  811. unsigned int link_id = link->link_id;
  812. struct ieee80211_bss_conf *link_conf = link->conf;
  813. struct ieee80211_local *local __maybe_unused = sdata->local;
  814. struct ieee80211_sub_if_data *vlan;
  815. struct ieee80211_chanctx_conf *conf;
  816. if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
  817. return;
  818. lockdep_assert_wiphy(local->hw.wiphy);
  819. /* Check that conf exists, even when clearing this function
  820. * must be called with the AP's channel context still there
  821. * as it would otherwise cause VLANs to have an invalid
  822. * channel context pointer for a while, possibly pointing
  823. * to a channel context that has already been freed.
  824. */
  825. conf = rcu_dereference_protected(link_conf->chanctx_conf,
  826. lockdep_is_held(&local->hw.wiphy->mtx));
  827. WARN_ON(!conf);
  828. if (clear)
  829. conf = NULL;
  830. list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
  831. struct ieee80211_bss_conf *vlan_conf;
  832. vlan_conf = wiphy_dereference(local->hw.wiphy,
  833. vlan->vif.link_conf[link_id]);
  834. if (WARN_ON(!vlan_conf))
  835. continue;
  836. rcu_assign_pointer(vlan_conf->chanctx_conf, conf);
  837. }
  838. }
  839. void ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
  840. bool clear)
  841. {
  842. struct ieee80211_local *local = link->sdata->local;
  843. lockdep_assert_wiphy(local->hw.wiphy);
  844. __ieee80211_link_copy_chanctx_to_vlans(link, clear);
  845. }
  846. int ieee80211_link_unreserve_chanctx(struct ieee80211_link_data *link)
  847. {
  848. struct ieee80211_sub_if_data *sdata = link->sdata;
  849. struct ieee80211_chanctx *ctx = link->reserved_chanctx;
  850. lockdep_assert_wiphy(sdata->local->hw.wiphy);
  851. if (WARN_ON(!ctx))
  852. return -EINVAL;
  853. list_del(&link->reserved_chanctx_list);
  854. link->reserved_chanctx = NULL;
  855. if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) {
  856. if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
  857. if (WARN_ON(!ctx->replace_ctx))
  858. return -EINVAL;
  859. WARN_ON(ctx->replace_ctx->replace_state !=
  860. IEEE80211_CHANCTX_WILL_BE_REPLACED);
  861. WARN_ON(ctx->replace_ctx->replace_ctx != ctx);
  862. ctx->replace_ctx->replace_ctx = NULL;
  863. ctx->replace_ctx->replace_state =
  864. IEEE80211_CHANCTX_REPLACE_NONE;
  865. list_del_rcu(&ctx->list);
  866. kfree_rcu(ctx, rcu_head);
  867. } else {
  868. ieee80211_free_chanctx(sdata->local, ctx, false);
  869. }
  870. }
  871. return 0;
  872. }
  873. static struct ieee80211_chanctx *
  874. ieee80211_replace_chanctx(struct ieee80211_local *local,
  875. const struct ieee80211_chan_req *chanreq,
  876. enum ieee80211_chanctx_mode mode,
  877. struct ieee80211_chanctx *curr_ctx)
  878. {
  879. struct ieee80211_chanctx *new_ctx, *ctx;
  880. struct wiphy *wiphy = local->hw.wiphy;
  881. const struct wiphy_radio *radio;
  882. if (!curr_ctx || (curr_ctx->replace_state ==
  883. IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
  884. !list_empty(&curr_ctx->reserved_links)) {
  885. /*
  886. * Another link already requested this context for a
  887. * reservation. Find another one hoping all links assigned
  888. * to it will also switch soon enough.
  889. *
  890. * TODO: This needs a little more work as some cases
  891. * (more than 2 chanctx capable devices) may fail which could
  892. * otherwise succeed provided some channel context juggling was
  893. * performed.
  894. *
  895. * Consider ctx1..3, link1..6, each ctx has 2 links. link1 and
  896. * link2 from ctx1 request new different chandefs starting 2
  897. * in-place reserations with ctx4 and ctx5 replacing ctx1 and
  898. * ctx2 respectively. Next link5 and link6 from ctx3 reserve
  899. * ctx4. If link3 and link4 remain on ctx2 as they are then this
  900. * fails unless `replace_ctx` from ctx5 is replaced with ctx3.
  901. */
  902. list_for_each_entry(ctx, &local->chanctx_list, list) {
  903. if (ctx->replace_state !=
  904. IEEE80211_CHANCTX_REPLACE_NONE)
  905. continue;
  906. if (!list_empty(&ctx->reserved_links))
  907. continue;
  908. if (ctx->conf.radio_idx >= 0) {
  909. radio = &wiphy->radio[ctx->conf.radio_idx];
  910. if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
  911. continue;
  912. }
  913. curr_ctx = ctx;
  914. break;
  915. }
  916. }
  917. /*
  918. * If that's true then all available contexts already have reservations
  919. * and cannot be used.
  920. */
  921. if (!curr_ctx || (curr_ctx->replace_state ==
  922. IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
  923. !list_empty(&curr_ctx->reserved_links))
  924. return ERR_PTR(-EBUSY);
  925. new_ctx = ieee80211_alloc_chanctx(local, chanreq, mode, -1);
  926. if (!new_ctx)
  927. return ERR_PTR(-ENOMEM);
  928. new_ctx->replace_ctx = curr_ctx;
  929. new_ctx->replace_state = IEEE80211_CHANCTX_REPLACES_OTHER;
  930. curr_ctx->replace_ctx = new_ctx;
  931. curr_ctx->replace_state = IEEE80211_CHANCTX_WILL_BE_REPLACED;
  932. list_add_rcu(&new_ctx->list, &local->chanctx_list);
  933. return new_ctx;
  934. }
  935. static bool
  936. ieee80211_find_available_radio(struct ieee80211_local *local,
  937. const struct ieee80211_chan_req *chanreq,
  938. int *radio_idx)
  939. {
  940. struct wiphy *wiphy = local->hw.wiphy;
  941. const struct wiphy_radio *radio;
  942. int i;
  943. *radio_idx = -1;
  944. if (!wiphy->n_radio)
  945. return true;
  946. for (i = 0; i < wiphy->n_radio; i++) {
  947. radio = &wiphy->radio[i];
  948. if (!cfg80211_radio_chandef_valid(radio, &chanreq->oper))
  949. continue;
  950. if (!ieee80211_can_create_new_chanctx(local, i))
  951. continue;
  952. *radio_idx = i;
  953. return true;
  954. }
  955. return false;
  956. }
  957. int ieee80211_link_reserve_chanctx(struct ieee80211_link_data *link,
  958. const struct ieee80211_chan_req *chanreq,
  959. enum ieee80211_chanctx_mode mode,
  960. bool radar_required)
  961. {
  962. struct ieee80211_sub_if_data *sdata = link->sdata;
  963. struct ieee80211_local *local = sdata->local;
  964. struct ieee80211_chanctx *new_ctx, *curr_ctx;
  965. int radio_idx;
  966. lockdep_assert_wiphy(local->hw.wiphy);
  967. curr_ctx = ieee80211_link_get_chanctx(link);
  968. if (curr_ctx && !local->ops->switch_vif_chanctx)
  969. return -EOPNOTSUPP;
  970. new_ctx = ieee80211_find_reservation_chanctx(local, chanreq, mode);
  971. if (!new_ctx) {
  972. if (ieee80211_can_create_new_chanctx(local, -1) &&
  973. ieee80211_find_available_radio(local, chanreq, &radio_idx))
  974. new_ctx = ieee80211_new_chanctx(local, chanreq, mode,
  975. false, radio_idx);
  976. else
  977. new_ctx = ieee80211_replace_chanctx(local, chanreq,
  978. mode, curr_ctx);
  979. if (IS_ERR(new_ctx))
  980. return PTR_ERR(new_ctx);
  981. }
  982. list_add(&link->reserved_chanctx_list, &new_ctx->reserved_links);
  983. link->reserved_chanctx = new_ctx;
  984. link->reserved = *chanreq;
  985. link->reserved_radar_required = radar_required;
  986. link->reserved_ready = false;
  987. return 0;
  988. }
  989. static void
  990. ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
  991. {
  992. struct ieee80211_sub_if_data *sdata = link->sdata;
  993. switch (sdata->vif.type) {
  994. case NL80211_IFTYPE_ADHOC:
  995. case NL80211_IFTYPE_AP:
  996. case NL80211_IFTYPE_MESH_POINT:
  997. case NL80211_IFTYPE_OCB:
  998. wiphy_work_queue(sdata->local->hw.wiphy,
  999. &link->csa.finalize_work);
  1000. break;
  1001. case NL80211_IFTYPE_STATION:
  1002. wiphy_delayed_work_queue(sdata->local->hw.wiphy,
  1003. &link->u.mgd.csa.switch_work, 0);
  1004. break;
  1005. case NL80211_IFTYPE_UNSPECIFIED:
  1006. case NL80211_IFTYPE_AP_VLAN:
  1007. case NL80211_IFTYPE_WDS:
  1008. case NL80211_IFTYPE_MONITOR:
  1009. case NL80211_IFTYPE_P2P_CLIENT:
  1010. case NL80211_IFTYPE_P2P_GO:
  1011. case NL80211_IFTYPE_P2P_DEVICE:
  1012. case NL80211_IFTYPE_NAN:
  1013. case NUM_NL80211_IFTYPES:
  1014. WARN_ON(1);
  1015. break;
  1016. }
  1017. }
  1018. static void
  1019. ieee80211_link_update_chanreq(struct ieee80211_link_data *link,
  1020. const struct ieee80211_chan_req *chanreq)
  1021. {
  1022. struct ieee80211_sub_if_data *sdata = link->sdata;
  1023. unsigned int link_id = link->link_id;
  1024. struct ieee80211_sub_if_data *vlan;
  1025. link->conf->chanreq = *chanreq;
  1026. if (sdata->vif.type != NL80211_IFTYPE_AP)
  1027. return;
  1028. list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
  1029. struct ieee80211_bss_conf *vlan_conf;
  1030. vlan_conf = wiphy_dereference(sdata->local->hw.wiphy,
  1031. vlan->vif.link_conf[link_id]);
  1032. if (WARN_ON(!vlan_conf))
  1033. continue;
  1034. vlan_conf->chanreq = *chanreq;
  1035. }
  1036. }
  1037. static int
  1038. ieee80211_link_use_reserved_reassign(struct ieee80211_link_data *link)
  1039. {
  1040. struct ieee80211_sub_if_data *sdata = link->sdata;
  1041. struct ieee80211_bss_conf *link_conf = link->conf;
  1042. struct ieee80211_local *local = sdata->local;
  1043. struct ieee80211_vif_chanctx_switch vif_chsw[1] = {};
  1044. struct ieee80211_chanctx *old_ctx, *new_ctx;
  1045. const struct ieee80211_chan_req *chanreq;
  1046. struct ieee80211_chan_req tmp;
  1047. u64 changed = 0;
  1048. int err;
  1049. lockdep_assert_wiphy(local->hw.wiphy);
  1050. new_ctx = link->reserved_chanctx;
  1051. old_ctx = ieee80211_link_get_chanctx(link);
  1052. if (WARN_ON(!link->reserved_ready))
  1053. return -EBUSY;
  1054. if (WARN_ON(!new_ctx))
  1055. return -EINVAL;
  1056. if (WARN_ON(!old_ctx))
  1057. return -EINVAL;
  1058. if (WARN_ON(new_ctx->replace_state ==
  1059. IEEE80211_CHANCTX_REPLACES_OTHER))
  1060. return -EINVAL;
  1061. chanreq = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
  1062. &link->reserved,
  1063. &tmp);
  1064. if (WARN_ON(!chanreq))
  1065. return -EINVAL;
  1066. if (link_conf->chanreq.oper.width != link->reserved.oper.width)
  1067. changed = BSS_CHANGED_BANDWIDTH;
  1068. ieee80211_link_update_chanreq(link, &link->reserved);
  1069. _ieee80211_change_chanctx(local, new_ctx, old_ctx, chanreq, link);
  1070. vif_chsw[0].vif = &sdata->vif;
  1071. vif_chsw[0].old_ctx = &old_ctx->conf;
  1072. vif_chsw[0].new_ctx = &new_ctx->conf;
  1073. vif_chsw[0].link_conf = link->conf;
  1074. list_del(&link->reserved_chanctx_list);
  1075. link->reserved_chanctx = NULL;
  1076. err = drv_switch_vif_chanctx(local, vif_chsw, 1,
  1077. CHANCTX_SWMODE_REASSIGN_VIF);
  1078. if (err) {
  1079. if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
  1080. ieee80211_free_chanctx(local, new_ctx, false);
  1081. goto out;
  1082. }
  1083. list_move(&link->assigned_chanctx_list, &new_ctx->assigned_links);
  1084. rcu_assign_pointer(link_conf->chanctx_conf, &new_ctx->conf);
  1085. if (sdata->vif.type == NL80211_IFTYPE_AP)
  1086. __ieee80211_link_copy_chanctx_to_vlans(link, false);
  1087. ieee80211_check_fast_xmit_iface(sdata);
  1088. if (ieee80211_chanctx_refcount(local, old_ctx) == 0)
  1089. ieee80211_free_chanctx(local, old_ctx, false);
  1090. ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL, false);
  1091. ieee80211_recalc_smps_chanctx(local, new_ctx);
  1092. ieee80211_recalc_radar_chanctx(local, new_ctx);
  1093. if (changed)
  1094. ieee80211_link_info_change_notify(sdata, link, changed);
  1095. out:
  1096. ieee80211_link_chanctx_reservation_complete(link);
  1097. return err;
  1098. }
  1099. static int
  1100. ieee80211_link_use_reserved_assign(struct ieee80211_link_data *link)
  1101. {
  1102. struct ieee80211_sub_if_data *sdata = link->sdata;
  1103. struct ieee80211_local *local = sdata->local;
  1104. struct ieee80211_chanctx *old_ctx, *new_ctx;
  1105. const struct ieee80211_chan_req *chanreq;
  1106. struct ieee80211_chan_req tmp;
  1107. int err;
  1108. old_ctx = ieee80211_link_get_chanctx(link);
  1109. new_ctx = link->reserved_chanctx;
  1110. if (WARN_ON(!link->reserved_ready))
  1111. return -EINVAL;
  1112. if (WARN_ON(old_ctx))
  1113. return -EINVAL;
  1114. if (WARN_ON(!new_ctx))
  1115. return -EINVAL;
  1116. if (WARN_ON(new_ctx->replace_state ==
  1117. IEEE80211_CHANCTX_REPLACES_OTHER))
  1118. return -EINVAL;
  1119. chanreq = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
  1120. &link->reserved,
  1121. &tmp);
  1122. if (WARN_ON(!chanreq))
  1123. return -EINVAL;
  1124. ieee80211_change_chanctx(local, new_ctx, new_ctx, chanreq);
  1125. list_del(&link->reserved_chanctx_list);
  1126. link->reserved_chanctx = NULL;
  1127. err = ieee80211_assign_link_chanctx(link, new_ctx, false);
  1128. if (err) {
  1129. if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
  1130. ieee80211_free_chanctx(local, new_ctx, false);
  1131. goto out;
  1132. }
  1133. out:
  1134. ieee80211_link_chanctx_reservation_complete(link);
  1135. return err;
  1136. }
  1137. static bool
  1138. ieee80211_link_has_in_place_reservation(struct ieee80211_link_data *link)
  1139. {
  1140. struct ieee80211_sub_if_data *sdata = link->sdata;
  1141. struct ieee80211_chanctx *old_ctx, *new_ctx;
  1142. lockdep_assert_wiphy(sdata->local->hw.wiphy);
  1143. new_ctx = link->reserved_chanctx;
  1144. old_ctx = ieee80211_link_get_chanctx(link);
  1145. if (!old_ctx)
  1146. return false;
  1147. if (WARN_ON(!new_ctx))
  1148. return false;
  1149. if (old_ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
  1150. return false;
  1151. if (new_ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1152. return false;
  1153. return true;
  1154. }
  1155. static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
  1156. int n_vifs)
  1157. {
  1158. struct ieee80211_vif_chanctx_switch *vif_chsw;
  1159. struct ieee80211_link_data *link;
  1160. struct ieee80211_chanctx *ctx, *old_ctx;
  1161. int i, err;
  1162. lockdep_assert_wiphy(local->hw.wiphy);
  1163. vif_chsw = kcalloc(n_vifs, sizeof(vif_chsw[0]), GFP_KERNEL);
  1164. if (!vif_chsw)
  1165. return -ENOMEM;
  1166. i = 0;
  1167. list_for_each_entry(ctx, &local->chanctx_list, list) {
  1168. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1169. continue;
  1170. if (WARN_ON(!ctx->replace_ctx)) {
  1171. err = -EINVAL;
  1172. goto out;
  1173. }
  1174. list_for_each_entry(link, &ctx->reserved_links,
  1175. reserved_chanctx_list) {
  1176. if (!ieee80211_link_has_in_place_reservation(link))
  1177. continue;
  1178. old_ctx = ieee80211_link_get_chanctx(link);
  1179. vif_chsw[i].vif = &link->sdata->vif;
  1180. vif_chsw[i].old_ctx = &old_ctx->conf;
  1181. vif_chsw[i].new_ctx = &ctx->conf;
  1182. vif_chsw[i].link_conf = link->conf;
  1183. i++;
  1184. }
  1185. }
  1186. err = drv_switch_vif_chanctx(local, vif_chsw, n_vifs,
  1187. CHANCTX_SWMODE_SWAP_CONTEXTS);
  1188. out:
  1189. kfree(vif_chsw);
  1190. return err;
  1191. }
  1192. static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local)
  1193. {
  1194. struct ieee80211_chanctx *ctx;
  1195. int err;
  1196. lockdep_assert_wiphy(local->hw.wiphy);
  1197. list_for_each_entry(ctx, &local->chanctx_list, list) {
  1198. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1199. continue;
  1200. if (!list_empty(&ctx->replace_ctx->assigned_links))
  1201. continue;
  1202. ieee80211_del_chanctx(local, ctx->replace_ctx, false);
  1203. err = ieee80211_add_chanctx(local, ctx);
  1204. if (err)
  1205. goto err;
  1206. }
  1207. return 0;
  1208. err:
  1209. WARN_ON(ieee80211_add_chanctx(local, ctx));
  1210. list_for_each_entry_continue_reverse(ctx, &local->chanctx_list, list) {
  1211. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1212. continue;
  1213. if (!list_empty(&ctx->replace_ctx->assigned_links))
  1214. continue;
  1215. ieee80211_del_chanctx(local, ctx, false);
  1216. WARN_ON(ieee80211_add_chanctx(local, ctx->replace_ctx));
  1217. }
  1218. return err;
  1219. }
  1220. static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
  1221. {
  1222. struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx;
  1223. int err, n_assigned, n_reserved, n_ready;
  1224. int n_ctx = 0, n_vifs_switch = 0, n_vifs_assign = 0, n_vifs_ctxless = 0;
  1225. lockdep_assert_wiphy(local->hw.wiphy);
  1226. /*
  1227. * If there are 2 independent pairs of channel contexts performing
  1228. * cross-switch of their vifs this code will still wait until both are
  1229. * ready even though it could be possible to switch one before the
  1230. * other is ready.
  1231. *
  1232. * For practical reasons and code simplicity just do a single huge
  1233. * switch.
  1234. */
  1235. /*
  1236. * Verify if the reservation is still feasible.
  1237. * - if it's not then disconnect
  1238. * - if it is but not all vifs necessary are ready then defer
  1239. */
  1240. list_for_each_entry(ctx, &local->chanctx_list, list) {
  1241. struct ieee80211_link_data *link;
  1242. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1243. continue;
  1244. if (WARN_ON(!ctx->replace_ctx)) {
  1245. err = -EINVAL;
  1246. goto err;
  1247. }
  1248. n_ctx++;
  1249. n_assigned = 0;
  1250. n_reserved = 0;
  1251. n_ready = 0;
  1252. list_for_each_entry(link, &ctx->replace_ctx->assigned_links,
  1253. assigned_chanctx_list) {
  1254. n_assigned++;
  1255. if (link->reserved_chanctx) {
  1256. n_reserved++;
  1257. if (link->reserved_ready)
  1258. n_ready++;
  1259. }
  1260. }
  1261. if (n_assigned != n_reserved) {
  1262. if (n_ready == n_reserved) {
  1263. wiphy_info(local->hw.wiphy,
  1264. "channel context reservation cannot be finalized because some interfaces aren't switching\n");
  1265. err = -EBUSY;
  1266. goto err;
  1267. }
  1268. return -EAGAIN;
  1269. }
  1270. ctx->conf.radar_enabled = false;
  1271. list_for_each_entry(link, &ctx->reserved_links,
  1272. reserved_chanctx_list) {
  1273. if (ieee80211_link_has_in_place_reservation(link) &&
  1274. !link->reserved_ready)
  1275. return -EAGAIN;
  1276. old_ctx = ieee80211_link_get_chanctx(link);
  1277. if (old_ctx) {
  1278. if (old_ctx->replace_state ==
  1279. IEEE80211_CHANCTX_WILL_BE_REPLACED)
  1280. n_vifs_switch++;
  1281. else
  1282. n_vifs_assign++;
  1283. } else {
  1284. n_vifs_ctxless++;
  1285. }
  1286. if (link->reserved_radar_required)
  1287. ctx->conf.radar_enabled = true;
  1288. }
  1289. }
  1290. if (WARN_ON(n_ctx == 0) ||
  1291. WARN_ON(n_vifs_switch == 0 &&
  1292. n_vifs_assign == 0 &&
  1293. n_vifs_ctxless == 0)) {
  1294. err = -EINVAL;
  1295. goto err;
  1296. }
  1297. /* update station rate control and min width before switch */
  1298. list_for_each_entry(ctx, &local->chanctx_list, list) {
  1299. struct ieee80211_link_data *link;
  1300. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1301. continue;
  1302. if (WARN_ON(!ctx->replace_ctx)) {
  1303. err = -EINVAL;
  1304. goto err;
  1305. }
  1306. list_for_each_entry(link, &ctx->reserved_links,
  1307. reserved_chanctx_list) {
  1308. if (!ieee80211_link_has_in_place_reservation(link))
  1309. continue;
  1310. ieee80211_chan_bw_change(local,
  1311. ieee80211_link_get_chanctx(link),
  1312. true, true);
  1313. }
  1314. ieee80211_recalc_chanctx_min_def(local, ctx, NULL, true);
  1315. }
  1316. /*
  1317. * All necessary vifs are ready. Perform the switch now depending on
  1318. * reservations and driver capabilities.
  1319. */
  1320. if (n_vifs_switch > 0) {
  1321. err = ieee80211_chsw_switch_vifs(local, n_vifs_switch);
  1322. if (err)
  1323. goto err;
  1324. }
  1325. if (n_vifs_assign > 0 || n_vifs_ctxless > 0) {
  1326. err = ieee80211_chsw_switch_ctxs(local);
  1327. if (err)
  1328. goto err;
  1329. }
  1330. /*
  1331. * Update all structures, values and pointers to point to new channel
  1332. * context(s).
  1333. */
  1334. list_for_each_entry(ctx, &local->chanctx_list, list) {
  1335. struct ieee80211_link_data *link, *link_tmp;
  1336. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1337. continue;
  1338. if (WARN_ON(!ctx->replace_ctx)) {
  1339. err = -EINVAL;
  1340. goto err;
  1341. }
  1342. list_for_each_entry(link, &ctx->reserved_links,
  1343. reserved_chanctx_list) {
  1344. struct ieee80211_sub_if_data *sdata = link->sdata;
  1345. struct ieee80211_bss_conf *link_conf = link->conf;
  1346. u64 changed = 0;
  1347. if (!ieee80211_link_has_in_place_reservation(link))
  1348. continue;
  1349. rcu_assign_pointer(link_conf->chanctx_conf,
  1350. &ctx->conf);
  1351. if (sdata->vif.type == NL80211_IFTYPE_AP)
  1352. __ieee80211_link_copy_chanctx_to_vlans(link,
  1353. false);
  1354. ieee80211_check_fast_xmit_iface(sdata);
  1355. link->radar_required = link->reserved_radar_required;
  1356. if (link_conf->chanreq.oper.width != link->reserved.oper.width)
  1357. changed = BSS_CHANGED_BANDWIDTH;
  1358. ieee80211_link_update_chanreq(link, &link->reserved);
  1359. if (changed)
  1360. ieee80211_link_info_change_notify(sdata,
  1361. link,
  1362. changed);
  1363. ieee80211_recalc_txpower(sdata, false);
  1364. }
  1365. ieee80211_recalc_chanctx_chantype(local, ctx);
  1366. ieee80211_recalc_smps_chanctx(local, ctx);
  1367. ieee80211_recalc_radar_chanctx(local, ctx);
  1368. ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false);
  1369. list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
  1370. reserved_chanctx_list) {
  1371. if (ieee80211_link_get_chanctx(link) != ctx)
  1372. continue;
  1373. list_del(&link->reserved_chanctx_list);
  1374. list_move(&link->assigned_chanctx_list,
  1375. &ctx->assigned_links);
  1376. link->reserved_chanctx = NULL;
  1377. ieee80211_link_chanctx_reservation_complete(link);
  1378. ieee80211_chan_bw_change(local, ctx, false, false);
  1379. }
  1380. /*
  1381. * This context might have been a dependency for an already
  1382. * ready re-assign reservation interface that was deferred. Do
  1383. * not propagate error to the caller though. The in-place
  1384. * reservation for originally requested interface has already
  1385. * succeeded at this point.
  1386. */
  1387. list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
  1388. reserved_chanctx_list) {
  1389. if (WARN_ON(ieee80211_link_has_in_place_reservation(link)))
  1390. continue;
  1391. if (WARN_ON(link->reserved_chanctx != ctx))
  1392. continue;
  1393. if (!link->reserved_ready)
  1394. continue;
  1395. if (ieee80211_link_get_chanctx(link))
  1396. err = ieee80211_link_use_reserved_reassign(link);
  1397. else
  1398. err = ieee80211_link_use_reserved_assign(link);
  1399. if (err) {
  1400. link_info(link,
  1401. "failed to finalize (re-)assign reservation (err=%d)\n",
  1402. err);
  1403. ieee80211_link_unreserve_chanctx(link);
  1404. cfg80211_stop_iface(local->hw.wiphy,
  1405. &link->sdata->wdev,
  1406. GFP_KERNEL);
  1407. }
  1408. }
  1409. }
  1410. /*
  1411. * Finally free old contexts
  1412. */
  1413. list_for_each_entry_safe(ctx, ctx_tmp, &local->chanctx_list, list) {
  1414. if (ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
  1415. continue;
  1416. ctx->replace_ctx->replace_ctx = NULL;
  1417. ctx->replace_ctx->replace_state =
  1418. IEEE80211_CHANCTX_REPLACE_NONE;
  1419. list_del_rcu(&ctx->list);
  1420. kfree_rcu(ctx, rcu_head);
  1421. }
  1422. return 0;
  1423. err:
  1424. list_for_each_entry(ctx, &local->chanctx_list, list) {
  1425. struct ieee80211_link_data *link, *link_tmp;
  1426. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1427. continue;
  1428. list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
  1429. reserved_chanctx_list) {
  1430. ieee80211_link_unreserve_chanctx(link);
  1431. ieee80211_link_chanctx_reservation_complete(link);
  1432. }
  1433. }
  1434. return err;
  1435. }
  1436. void __ieee80211_link_release_channel(struct ieee80211_link_data *link,
  1437. bool skip_idle_recalc)
  1438. {
  1439. struct ieee80211_sub_if_data *sdata = link->sdata;
  1440. struct ieee80211_bss_conf *link_conf = link->conf;
  1441. struct ieee80211_local *local = sdata->local;
  1442. struct ieee80211_chanctx_conf *conf;
  1443. struct ieee80211_chanctx *ctx;
  1444. bool use_reserved_switch = false;
  1445. lockdep_assert_wiphy(local->hw.wiphy);
  1446. conf = rcu_dereference_protected(link_conf->chanctx_conf,
  1447. lockdep_is_held(&local->hw.wiphy->mtx));
  1448. if (!conf)
  1449. return;
  1450. ctx = container_of(conf, struct ieee80211_chanctx, conf);
  1451. if (link->reserved_chanctx) {
  1452. if (link->reserved_chanctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER &&
  1453. ieee80211_chanctx_num_reserved(local, link->reserved_chanctx) > 1)
  1454. use_reserved_switch = true;
  1455. ieee80211_link_unreserve_chanctx(link);
  1456. }
  1457. ieee80211_assign_link_chanctx(link, NULL, false);
  1458. if (ieee80211_chanctx_refcount(local, ctx) == 0)
  1459. ieee80211_free_chanctx(local, ctx, skip_idle_recalc);
  1460. link->radar_required = false;
  1461. /* Unreserving may ready an in-place reservation. */
  1462. if (use_reserved_switch)
  1463. ieee80211_vif_use_reserved_switch(local);
  1464. }
  1465. int _ieee80211_link_use_channel(struct ieee80211_link_data *link,
  1466. const struct ieee80211_chan_req *chanreq,
  1467. enum ieee80211_chanctx_mode mode,
  1468. bool assign_on_failure)
  1469. {
  1470. struct ieee80211_sub_if_data *sdata = link->sdata;
  1471. struct ieee80211_local *local = sdata->local;
  1472. struct ieee80211_chanctx *ctx;
  1473. u8 radar_detect_width = 0;
  1474. bool reserved = false;
  1475. int radio_idx;
  1476. int ret;
  1477. lockdep_assert_wiphy(local->hw.wiphy);
  1478. if (!ieee80211_vif_link_active(&sdata->vif, link->link_id)) {
  1479. ieee80211_link_update_chanreq(link, chanreq);
  1480. return 0;
  1481. }
  1482. ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
  1483. &chanreq->oper,
  1484. sdata->wdev.iftype);
  1485. if (ret < 0)
  1486. goto out;
  1487. if (ret > 0)
  1488. radar_detect_width = BIT(chanreq->oper.width);
  1489. link->radar_required = ret;
  1490. ret = ieee80211_check_combinations(sdata, &chanreq->oper, mode,
  1491. radar_detect_width, -1);
  1492. if (ret < 0)
  1493. goto out;
  1494. __ieee80211_link_release_channel(link, false);
  1495. ctx = ieee80211_find_chanctx(local, link, chanreq, mode);
  1496. /* Note: context is now reserved */
  1497. if (ctx)
  1498. reserved = true;
  1499. else if (!ieee80211_find_available_radio(local, chanreq, &radio_idx))
  1500. ctx = ERR_PTR(-EBUSY);
  1501. else
  1502. ctx = ieee80211_new_chanctx(local, chanreq, mode,
  1503. assign_on_failure, radio_idx);
  1504. if (IS_ERR(ctx)) {
  1505. ret = PTR_ERR(ctx);
  1506. goto out;
  1507. }
  1508. ieee80211_link_update_chanreq(link, chanreq);
  1509. ret = ieee80211_assign_link_chanctx(link, ctx, assign_on_failure);
  1510. if (reserved) {
  1511. /* remove reservation */
  1512. WARN_ON(link->reserved_chanctx != ctx);
  1513. link->reserved_chanctx = NULL;
  1514. list_del(&link->reserved_chanctx_list);
  1515. }
  1516. if (ret) {
  1517. /* if assign fails refcount stays the same */
  1518. if (ieee80211_chanctx_refcount(local, ctx) == 0)
  1519. ieee80211_free_chanctx(local, ctx, false);
  1520. goto out;
  1521. }
  1522. ieee80211_recalc_smps_chanctx(local, ctx);
  1523. ieee80211_recalc_radar_chanctx(local, ctx);
  1524. out:
  1525. if (ret)
  1526. link->radar_required = false;
  1527. return ret;
  1528. }
  1529. int ieee80211_link_use_reserved_context(struct ieee80211_link_data *link)
  1530. {
  1531. struct ieee80211_sub_if_data *sdata = link->sdata;
  1532. struct ieee80211_local *local = sdata->local;
  1533. struct ieee80211_chanctx *new_ctx;
  1534. struct ieee80211_chanctx *old_ctx;
  1535. int err;
  1536. lockdep_assert_wiphy(local->hw.wiphy);
  1537. new_ctx = link->reserved_chanctx;
  1538. old_ctx = ieee80211_link_get_chanctx(link);
  1539. if (WARN_ON(!new_ctx))
  1540. return -EINVAL;
  1541. if (WARN_ON(new_ctx->replace_state ==
  1542. IEEE80211_CHANCTX_WILL_BE_REPLACED))
  1543. return -EINVAL;
  1544. if (WARN_ON(link->reserved_ready))
  1545. return -EINVAL;
  1546. link->reserved_ready = true;
  1547. if (new_ctx->replace_state == IEEE80211_CHANCTX_REPLACE_NONE) {
  1548. if (old_ctx)
  1549. return ieee80211_link_use_reserved_reassign(link);
  1550. return ieee80211_link_use_reserved_assign(link);
  1551. }
  1552. /*
  1553. * In-place reservation may need to be finalized now either if:
  1554. * a) sdata is taking part in the swapping itself and is the last one
  1555. * b) sdata has switched with a re-assign reservation to an existing
  1556. * context readying in-place switching of old_ctx
  1557. *
  1558. * In case of (b) do not propagate the error up because the requested
  1559. * sdata already switched successfully. Just spill an extra warning.
  1560. * The ieee80211_vif_use_reserved_switch() already stops all necessary
  1561. * interfaces upon failure.
  1562. */
  1563. if ((old_ctx &&
  1564. old_ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
  1565. new_ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
  1566. err = ieee80211_vif_use_reserved_switch(local);
  1567. if (err && err != -EAGAIN) {
  1568. if (new_ctx->replace_state ==
  1569. IEEE80211_CHANCTX_REPLACES_OTHER)
  1570. return err;
  1571. wiphy_info(local->hw.wiphy,
  1572. "depending in-place reservation failed (err=%d)\n",
  1573. err);
  1574. }
  1575. }
  1576. return 0;
  1577. }
  1578. /*
  1579. * This is similar to ieee80211_chanctx_compatible(), but rechecks
  1580. * against all the links actually using it (except the one that's
  1581. * passed, since that one is changing).
  1582. * This is done in order to allow changes to the AP's bandwidth for
  1583. * wider bandwidth OFDMA purposes, which wouldn't be treated as
  1584. * compatible by ieee80211_chanctx_recheck() but is OK if the link
  1585. * requesting the update is the only one using it.
  1586. */
  1587. static const struct ieee80211_chan_req *
  1588. ieee80211_chanctx_recheck(struct ieee80211_local *local,
  1589. struct ieee80211_link_data *skip_link,
  1590. struct ieee80211_chanctx *ctx,
  1591. const struct ieee80211_chan_req *req,
  1592. struct ieee80211_chan_req *tmp)
  1593. {
  1594. const struct ieee80211_chan_req *ret = req;
  1595. struct ieee80211_link_data *link;
  1596. lockdep_assert_wiphy(local->hw.wiphy);
  1597. for_each_sdata_link(local, link) {
  1598. if (link == skip_link)
  1599. continue;
  1600. if (rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf) {
  1601. ret = ieee80211_chanreq_compatible(ret,
  1602. &link->conf->chanreq,
  1603. tmp);
  1604. if (!ret)
  1605. return NULL;
  1606. }
  1607. if (link->reserved_chanctx == ctx) {
  1608. ret = ieee80211_chanreq_compatible(ret,
  1609. &link->reserved,
  1610. tmp);
  1611. if (!ret)
  1612. return NULL;
  1613. }
  1614. }
  1615. *tmp = *ret;
  1616. return tmp;
  1617. }
  1618. int ieee80211_link_change_chanreq(struct ieee80211_link_data *link,
  1619. const struct ieee80211_chan_req *chanreq,
  1620. u64 *changed)
  1621. {
  1622. struct ieee80211_sub_if_data *sdata = link->sdata;
  1623. struct ieee80211_bss_conf *link_conf = link->conf;
  1624. struct ieee80211_local *local = sdata->local;
  1625. struct ieee80211_chanctx_conf *conf;
  1626. struct ieee80211_chanctx *ctx;
  1627. const struct ieee80211_chan_req *compat;
  1628. struct ieee80211_chan_req tmp;
  1629. lockdep_assert_wiphy(local->hw.wiphy);
  1630. if (!cfg80211_chandef_usable(sdata->local->hw.wiphy,
  1631. &chanreq->oper,
  1632. IEEE80211_CHAN_DISABLED))
  1633. return -EINVAL;
  1634. /* for non-HT 20 MHz the rest doesn't matter */
  1635. if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT &&
  1636. cfg80211_chandef_identical(&chanreq->oper, &link_conf->chanreq.oper))
  1637. return 0;
  1638. /* but you cannot switch to/from it */
  1639. if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT ||
  1640. link_conf->chanreq.oper.width == NL80211_CHAN_WIDTH_20_NOHT)
  1641. return -EINVAL;
  1642. conf = rcu_dereference_protected(link_conf->chanctx_conf,
  1643. lockdep_is_held(&local->hw.wiphy->mtx));
  1644. if (!conf)
  1645. return -EINVAL;
  1646. ctx = container_of(conf, struct ieee80211_chanctx, conf);
  1647. compat = ieee80211_chanctx_recheck(local, link, ctx, chanreq, &tmp);
  1648. if (!compat)
  1649. return -EINVAL;
  1650. switch (ctx->replace_state) {
  1651. case IEEE80211_CHANCTX_REPLACE_NONE:
  1652. if (!ieee80211_chanctx_reserved_chanreq(local, ctx, compat,
  1653. &tmp))
  1654. return -EBUSY;
  1655. break;
  1656. case IEEE80211_CHANCTX_WILL_BE_REPLACED:
  1657. /* TODO: Perhaps the bandwidth change could be treated as a
  1658. * reservation itself? */
  1659. return -EBUSY;
  1660. case IEEE80211_CHANCTX_REPLACES_OTHER:
  1661. /* channel context that is going to replace another channel
  1662. * context doesn't really exist and shouldn't be assigned
  1663. * anywhere yet */
  1664. WARN_ON(1);
  1665. break;
  1666. }
  1667. ieee80211_link_update_chanreq(link, chanreq);
  1668. ieee80211_recalc_chanctx_chantype(local, ctx);
  1669. *changed |= BSS_CHANGED_BANDWIDTH;
  1670. return 0;
  1671. }
  1672. void ieee80211_link_release_channel(struct ieee80211_link_data *link)
  1673. {
  1674. struct ieee80211_sub_if_data *sdata = link->sdata;
  1675. lockdep_assert_wiphy(sdata->local->hw.wiphy);
  1676. if (rcu_access_pointer(link->conf->chanctx_conf))
  1677. __ieee80211_link_release_channel(link, false);
  1678. }
  1679. void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data *link)
  1680. {
  1681. struct ieee80211_sub_if_data *sdata = link->sdata;
  1682. unsigned int link_id = link->link_id;
  1683. struct ieee80211_bss_conf *link_conf = link->conf;
  1684. struct ieee80211_bss_conf *ap_conf;
  1685. struct ieee80211_local *local = sdata->local;
  1686. struct ieee80211_sub_if_data *ap;
  1687. struct ieee80211_chanctx_conf *conf;
  1688. lockdep_assert_wiphy(local->hw.wiphy);
  1689. if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
  1690. return;
  1691. ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
  1692. ap_conf = wiphy_dereference(local->hw.wiphy,
  1693. ap->vif.link_conf[link_id]);
  1694. conf = wiphy_dereference(local->hw.wiphy,
  1695. ap_conf->chanctx_conf);
  1696. rcu_assign_pointer(link_conf->chanctx_conf, conf);
  1697. }
  1698. void ieee80211_iter_chan_contexts_atomic(
  1699. struct ieee80211_hw *hw,
  1700. void (*iter)(struct ieee80211_hw *hw,
  1701. struct ieee80211_chanctx_conf *chanctx_conf,
  1702. void *data),
  1703. void *iter_data)
  1704. {
  1705. struct ieee80211_local *local = hw_to_local(hw);
  1706. struct ieee80211_chanctx *ctx;
  1707. rcu_read_lock();
  1708. list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
  1709. if (ctx->driver_present)
  1710. iter(hw, &ctx->conf, iter_data);
  1711. rcu_read_unlock();
  1712. }
  1713. EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);