chan.c 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150
  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. link->radar_required = link->reserved_radar_required;
  1084. list_move(&link->assigned_chanctx_list, &new_ctx->assigned_links);
  1085. rcu_assign_pointer(link_conf->chanctx_conf, &new_ctx->conf);
  1086. if (sdata->vif.type == NL80211_IFTYPE_AP)
  1087. __ieee80211_link_copy_chanctx_to_vlans(link, false);
  1088. ieee80211_check_fast_xmit_iface(sdata);
  1089. if (ieee80211_chanctx_refcount(local, old_ctx) == 0)
  1090. ieee80211_free_chanctx(local, old_ctx, false);
  1091. ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL, false);
  1092. ieee80211_recalc_smps_chanctx(local, new_ctx);
  1093. ieee80211_recalc_radar_chanctx(local, new_ctx);
  1094. if (changed)
  1095. ieee80211_link_info_change_notify(sdata, link, changed);
  1096. out:
  1097. ieee80211_link_chanctx_reservation_complete(link);
  1098. return err;
  1099. }
  1100. static int
  1101. ieee80211_link_use_reserved_assign(struct ieee80211_link_data *link)
  1102. {
  1103. struct ieee80211_sub_if_data *sdata = link->sdata;
  1104. struct ieee80211_local *local = sdata->local;
  1105. struct ieee80211_chanctx *old_ctx, *new_ctx;
  1106. const struct ieee80211_chan_req *chanreq;
  1107. struct ieee80211_chan_req tmp;
  1108. int err;
  1109. old_ctx = ieee80211_link_get_chanctx(link);
  1110. new_ctx = link->reserved_chanctx;
  1111. if (WARN_ON(!link->reserved_ready))
  1112. return -EINVAL;
  1113. if (WARN_ON(old_ctx))
  1114. return -EINVAL;
  1115. if (WARN_ON(!new_ctx))
  1116. return -EINVAL;
  1117. if (WARN_ON(new_ctx->replace_state ==
  1118. IEEE80211_CHANCTX_REPLACES_OTHER))
  1119. return -EINVAL;
  1120. chanreq = ieee80211_chanctx_non_reserved_chandef(local, new_ctx,
  1121. &link->reserved,
  1122. &tmp);
  1123. if (WARN_ON(!chanreq))
  1124. return -EINVAL;
  1125. ieee80211_change_chanctx(local, new_ctx, new_ctx, chanreq);
  1126. list_del(&link->reserved_chanctx_list);
  1127. link->reserved_chanctx = NULL;
  1128. err = ieee80211_assign_link_chanctx(link, new_ctx, false);
  1129. if (err) {
  1130. if (ieee80211_chanctx_refcount(local, new_ctx) == 0)
  1131. ieee80211_free_chanctx(local, new_ctx, false);
  1132. goto out;
  1133. }
  1134. out:
  1135. ieee80211_link_chanctx_reservation_complete(link);
  1136. return err;
  1137. }
  1138. static bool
  1139. ieee80211_link_has_in_place_reservation(struct ieee80211_link_data *link)
  1140. {
  1141. struct ieee80211_sub_if_data *sdata = link->sdata;
  1142. struct ieee80211_chanctx *old_ctx, *new_ctx;
  1143. lockdep_assert_wiphy(sdata->local->hw.wiphy);
  1144. new_ctx = link->reserved_chanctx;
  1145. old_ctx = ieee80211_link_get_chanctx(link);
  1146. if (!old_ctx)
  1147. return false;
  1148. if (WARN_ON(!new_ctx))
  1149. return false;
  1150. if (old_ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
  1151. return false;
  1152. if (new_ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1153. return false;
  1154. return true;
  1155. }
  1156. static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
  1157. int n_vifs)
  1158. {
  1159. struct ieee80211_vif_chanctx_switch *vif_chsw;
  1160. struct ieee80211_link_data *link;
  1161. struct ieee80211_chanctx *ctx, *old_ctx;
  1162. int i, err;
  1163. lockdep_assert_wiphy(local->hw.wiphy);
  1164. vif_chsw = kcalloc(n_vifs, sizeof(vif_chsw[0]), GFP_KERNEL);
  1165. if (!vif_chsw)
  1166. return -ENOMEM;
  1167. i = 0;
  1168. list_for_each_entry(ctx, &local->chanctx_list, list) {
  1169. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1170. continue;
  1171. if (WARN_ON(!ctx->replace_ctx)) {
  1172. err = -EINVAL;
  1173. goto out;
  1174. }
  1175. list_for_each_entry(link, &ctx->reserved_links,
  1176. reserved_chanctx_list) {
  1177. if (!ieee80211_link_has_in_place_reservation(link))
  1178. continue;
  1179. old_ctx = ieee80211_link_get_chanctx(link);
  1180. vif_chsw[i].vif = &link->sdata->vif;
  1181. vif_chsw[i].old_ctx = &old_ctx->conf;
  1182. vif_chsw[i].new_ctx = &ctx->conf;
  1183. vif_chsw[i].link_conf = link->conf;
  1184. i++;
  1185. }
  1186. }
  1187. err = drv_switch_vif_chanctx(local, vif_chsw, n_vifs,
  1188. CHANCTX_SWMODE_SWAP_CONTEXTS);
  1189. out:
  1190. kfree(vif_chsw);
  1191. return err;
  1192. }
  1193. static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local)
  1194. {
  1195. struct ieee80211_chanctx *ctx;
  1196. int err;
  1197. lockdep_assert_wiphy(local->hw.wiphy);
  1198. list_for_each_entry(ctx, &local->chanctx_list, list) {
  1199. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1200. continue;
  1201. if (!list_empty(&ctx->replace_ctx->assigned_links))
  1202. continue;
  1203. ieee80211_del_chanctx(local, ctx->replace_ctx, false);
  1204. err = ieee80211_add_chanctx(local, ctx);
  1205. if (err)
  1206. goto err;
  1207. }
  1208. return 0;
  1209. err:
  1210. WARN_ON(ieee80211_add_chanctx(local, ctx));
  1211. list_for_each_entry_continue_reverse(ctx, &local->chanctx_list, list) {
  1212. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1213. continue;
  1214. if (!list_empty(&ctx->replace_ctx->assigned_links))
  1215. continue;
  1216. ieee80211_del_chanctx(local, ctx, false);
  1217. WARN_ON(ieee80211_add_chanctx(local, ctx->replace_ctx));
  1218. }
  1219. return err;
  1220. }
  1221. static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
  1222. {
  1223. struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx;
  1224. int err, n_assigned, n_reserved, n_ready;
  1225. int n_ctx = 0, n_vifs_switch = 0, n_vifs_assign = 0, n_vifs_ctxless = 0;
  1226. lockdep_assert_wiphy(local->hw.wiphy);
  1227. /*
  1228. * If there are 2 independent pairs of channel contexts performing
  1229. * cross-switch of their vifs this code will still wait until both are
  1230. * ready even though it could be possible to switch one before the
  1231. * other is ready.
  1232. *
  1233. * For practical reasons and code simplicity just do a single huge
  1234. * switch.
  1235. */
  1236. /*
  1237. * Verify if the reservation is still feasible.
  1238. * - if it's not then disconnect
  1239. * - if it is but not all vifs necessary are ready then defer
  1240. */
  1241. list_for_each_entry(ctx, &local->chanctx_list, list) {
  1242. struct ieee80211_link_data *link;
  1243. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1244. continue;
  1245. if (WARN_ON(!ctx->replace_ctx)) {
  1246. err = -EINVAL;
  1247. goto err;
  1248. }
  1249. n_ctx++;
  1250. n_assigned = 0;
  1251. n_reserved = 0;
  1252. n_ready = 0;
  1253. list_for_each_entry(link, &ctx->replace_ctx->assigned_links,
  1254. assigned_chanctx_list) {
  1255. n_assigned++;
  1256. if (link->reserved_chanctx) {
  1257. n_reserved++;
  1258. if (link->reserved_ready)
  1259. n_ready++;
  1260. }
  1261. }
  1262. if (n_assigned != n_reserved) {
  1263. if (n_ready == n_reserved) {
  1264. wiphy_info(local->hw.wiphy,
  1265. "channel context reservation cannot be finalized because some interfaces aren't switching\n");
  1266. err = -EBUSY;
  1267. goto err;
  1268. }
  1269. return -EAGAIN;
  1270. }
  1271. ctx->conf.radar_enabled = false;
  1272. list_for_each_entry(link, &ctx->reserved_links,
  1273. reserved_chanctx_list) {
  1274. if (ieee80211_link_has_in_place_reservation(link) &&
  1275. !link->reserved_ready)
  1276. return -EAGAIN;
  1277. old_ctx = ieee80211_link_get_chanctx(link);
  1278. if (old_ctx) {
  1279. if (old_ctx->replace_state ==
  1280. IEEE80211_CHANCTX_WILL_BE_REPLACED)
  1281. n_vifs_switch++;
  1282. else
  1283. n_vifs_assign++;
  1284. } else {
  1285. n_vifs_ctxless++;
  1286. }
  1287. if (link->reserved_radar_required)
  1288. ctx->conf.radar_enabled = true;
  1289. }
  1290. }
  1291. if (WARN_ON(n_ctx == 0) ||
  1292. WARN_ON(n_vifs_switch == 0 &&
  1293. n_vifs_assign == 0 &&
  1294. n_vifs_ctxless == 0)) {
  1295. err = -EINVAL;
  1296. goto err;
  1297. }
  1298. /* update station rate control and min width before switch */
  1299. list_for_each_entry(ctx, &local->chanctx_list, list) {
  1300. struct ieee80211_link_data *link;
  1301. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1302. continue;
  1303. if (WARN_ON(!ctx->replace_ctx)) {
  1304. err = -EINVAL;
  1305. goto err;
  1306. }
  1307. list_for_each_entry(link, &ctx->reserved_links,
  1308. reserved_chanctx_list) {
  1309. if (!ieee80211_link_has_in_place_reservation(link))
  1310. continue;
  1311. ieee80211_chan_bw_change(local,
  1312. ieee80211_link_get_chanctx(link),
  1313. true, true);
  1314. }
  1315. ieee80211_recalc_chanctx_min_def(local, ctx, NULL, true);
  1316. }
  1317. /*
  1318. * All necessary vifs are ready. Perform the switch now depending on
  1319. * reservations and driver capabilities.
  1320. */
  1321. if (n_vifs_switch > 0) {
  1322. err = ieee80211_chsw_switch_vifs(local, n_vifs_switch);
  1323. if (err)
  1324. goto err;
  1325. }
  1326. if (n_vifs_assign > 0 || n_vifs_ctxless > 0) {
  1327. err = ieee80211_chsw_switch_ctxs(local);
  1328. if (err)
  1329. goto err;
  1330. }
  1331. /*
  1332. * Update all structures, values and pointers to point to new channel
  1333. * context(s).
  1334. */
  1335. list_for_each_entry(ctx, &local->chanctx_list, list) {
  1336. struct ieee80211_link_data *link, *link_tmp;
  1337. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1338. continue;
  1339. if (WARN_ON(!ctx->replace_ctx)) {
  1340. err = -EINVAL;
  1341. goto err;
  1342. }
  1343. list_for_each_entry(link, &ctx->reserved_links,
  1344. reserved_chanctx_list) {
  1345. struct ieee80211_sub_if_data *sdata = link->sdata;
  1346. struct ieee80211_bss_conf *link_conf = link->conf;
  1347. u64 changed = 0;
  1348. if (!ieee80211_link_has_in_place_reservation(link))
  1349. continue;
  1350. rcu_assign_pointer(link_conf->chanctx_conf,
  1351. &ctx->conf);
  1352. if (sdata->vif.type == NL80211_IFTYPE_AP)
  1353. __ieee80211_link_copy_chanctx_to_vlans(link,
  1354. false);
  1355. ieee80211_check_fast_xmit_iface(sdata);
  1356. link->radar_required = link->reserved_radar_required;
  1357. if (link_conf->chanreq.oper.width != link->reserved.oper.width)
  1358. changed = BSS_CHANGED_BANDWIDTH;
  1359. ieee80211_link_update_chanreq(link, &link->reserved);
  1360. if (changed)
  1361. ieee80211_link_info_change_notify(sdata,
  1362. link,
  1363. changed);
  1364. ieee80211_recalc_txpower(sdata, false);
  1365. }
  1366. ieee80211_recalc_chanctx_chantype(local, ctx);
  1367. ieee80211_recalc_smps_chanctx(local, ctx);
  1368. ieee80211_recalc_radar_chanctx(local, ctx);
  1369. ieee80211_recalc_chanctx_min_def(local, ctx, NULL, false);
  1370. list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
  1371. reserved_chanctx_list) {
  1372. if (ieee80211_link_get_chanctx(link) != ctx)
  1373. continue;
  1374. list_del(&link->reserved_chanctx_list);
  1375. list_move(&link->assigned_chanctx_list,
  1376. &ctx->assigned_links);
  1377. link->reserved_chanctx = NULL;
  1378. ieee80211_link_chanctx_reservation_complete(link);
  1379. ieee80211_chan_bw_change(local, ctx, false, false);
  1380. }
  1381. /*
  1382. * This context might have been a dependency for an already
  1383. * ready re-assign reservation interface that was deferred. Do
  1384. * not propagate error to the caller though. The in-place
  1385. * reservation for originally requested interface has already
  1386. * succeeded at this point.
  1387. */
  1388. list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
  1389. reserved_chanctx_list) {
  1390. if (WARN_ON(ieee80211_link_has_in_place_reservation(link)))
  1391. continue;
  1392. if (WARN_ON(link->reserved_chanctx != ctx))
  1393. continue;
  1394. if (!link->reserved_ready)
  1395. continue;
  1396. if (ieee80211_link_get_chanctx(link))
  1397. err = ieee80211_link_use_reserved_reassign(link);
  1398. else
  1399. err = ieee80211_link_use_reserved_assign(link);
  1400. if (err) {
  1401. link_info(link,
  1402. "failed to finalize (re-)assign reservation (err=%d)\n",
  1403. err);
  1404. ieee80211_link_unreserve_chanctx(link);
  1405. cfg80211_stop_iface(local->hw.wiphy,
  1406. &link->sdata->wdev,
  1407. GFP_KERNEL);
  1408. }
  1409. }
  1410. }
  1411. /*
  1412. * Finally free old contexts
  1413. */
  1414. list_for_each_entry_safe(ctx, ctx_tmp, &local->chanctx_list, list) {
  1415. if (ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED)
  1416. continue;
  1417. ctx->replace_ctx->replace_ctx = NULL;
  1418. ctx->replace_ctx->replace_state =
  1419. IEEE80211_CHANCTX_REPLACE_NONE;
  1420. list_del_rcu(&ctx->list);
  1421. kfree_rcu(ctx, rcu_head);
  1422. }
  1423. return 0;
  1424. err:
  1425. list_for_each_entry(ctx, &local->chanctx_list, list) {
  1426. struct ieee80211_link_data *link, *link_tmp;
  1427. if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER)
  1428. continue;
  1429. list_for_each_entry_safe(link, link_tmp, &ctx->reserved_links,
  1430. reserved_chanctx_list) {
  1431. ieee80211_link_unreserve_chanctx(link);
  1432. ieee80211_link_chanctx_reservation_complete(link);
  1433. }
  1434. }
  1435. return err;
  1436. }
  1437. void __ieee80211_link_release_channel(struct ieee80211_link_data *link,
  1438. bool skip_idle_recalc)
  1439. {
  1440. struct ieee80211_sub_if_data *sdata = link->sdata;
  1441. struct ieee80211_bss_conf *link_conf = link->conf;
  1442. struct ieee80211_local *local = sdata->local;
  1443. struct ieee80211_chanctx_conf *conf;
  1444. struct ieee80211_chanctx *ctx;
  1445. bool use_reserved_switch = false;
  1446. lockdep_assert_wiphy(local->hw.wiphy);
  1447. conf = rcu_dereference_protected(link_conf->chanctx_conf,
  1448. lockdep_is_held(&local->hw.wiphy->mtx));
  1449. if (!conf)
  1450. return;
  1451. ctx = container_of(conf, struct ieee80211_chanctx, conf);
  1452. if (link->reserved_chanctx) {
  1453. if (link->reserved_chanctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER &&
  1454. ieee80211_chanctx_num_reserved(local, link->reserved_chanctx) > 1)
  1455. use_reserved_switch = true;
  1456. ieee80211_link_unreserve_chanctx(link);
  1457. }
  1458. ieee80211_assign_link_chanctx(link, NULL, false);
  1459. if (ieee80211_chanctx_refcount(local, ctx) == 0)
  1460. ieee80211_free_chanctx(local, ctx, skip_idle_recalc);
  1461. link->radar_required = false;
  1462. /* Unreserving may ready an in-place reservation. */
  1463. if (use_reserved_switch)
  1464. ieee80211_vif_use_reserved_switch(local);
  1465. }
  1466. int _ieee80211_link_use_channel(struct ieee80211_link_data *link,
  1467. const struct ieee80211_chan_req *chanreq,
  1468. enum ieee80211_chanctx_mode mode,
  1469. bool assign_on_failure)
  1470. {
  1471. struct ieee80211_sub_if_data *sdata = link->sdata;
  1472. struct ieee80211_local *local = sdata->local;
  1473. struct ieee80211_chanctx *ctx;
  1474. u8 radar_detect_width = 0;
  1475. bool reserved = false;
  1476. int radio_idx;
  1477. int ret;
  1478. lockdep_assert_wiphy(local->hw.wiphy);
  1479. if (!ieee80211_vif_link_active(&sdata->vif, link->link_id)) {
  1480. ieee80211_link_update_chanreq(link, chanreq);
  1481. return 0;
  1482. }
  1483. ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
  1484. &chanreq->oper,
  1485. sdata->wdev.iftype);
  1486. if (ret < 0)
  1487. goto out;
  1488. if (ret > 0)
  1489. radar_detect_width = BIT(chanreq->oper.width);
  1490. link->radar_required = ret;
  1491. ret = ieee80211_check_combinations(sdata, &chanreq->oper, mode,
  1492. radar_detect_width, -1);
  1493. if (ret < 0)
  1494. goto out;
  1495. __ieee80211_link_release_channel(link, false);
  1496. ctx = ieee80211_find_chanctx(local, link, chanreq, mode);
  1497. /* Note: context is now reserved */
  1498. if (ctx)
  1499. reserved = true;
  1500. else if (!ieee80211_find_available_radio(local, chanreq, &radio_idx))
  1501. ctx = ERR_PTR(-EBUSY);
  1502. else
  1503. ctx = ieee80211_new_chanctx(local, chanreq, mode,
  1504. assign_on_failure, radio_idx);
  1505. if (IS_ERR(ctx)) {
  1506. ret = PTR_ERR(ctx);
  1507. goto out;
  1508. }
  1509. ieee80211_link_update_chanreq(link, chanreq);
  1510. ret = ieee80211_assign_link_chanctx(link, ctx, assign_on_failure);
  1511. if (reserved) {
  1512. /* remove reservation */
  1513. WARN_ON(link->reserved_chanctx != ctx);
  1514. link->reserved_chanctx = NULL;
  1515. list_del(&link->reserved_chanctx_list);
  1516. }
  1517. if (ret) {
  1518. /* if assign fails refcount stays the same */
  1519. if (ieee80211_chanctx_refcount(local, ctx) == 0)
  1520. ieee80211_free_chanctx(local, ctx, false);
  1521. goto out;
  1522. }
  1523. ieee80211_recalc_smps_chanctx(local, ctx);
  1524. ieee80211_recalc_radar_chanctx(local, ctx);
  1525. out:
  1526. if (ret)
  1527. link->radar_required = false;
  1528. return ret;
  1529. }
  1530. int ieee80211_link_use_reserved_context(struct ieee80211_link_data *link)
  1531. {
  1532. struct ieee80211_sub_if_data *sdata = link->sdata;
  1533. struct ieee80211_local *local = sdata->local;
  1534. struct ieee80211_chanctx *new_ctx;
  1535. struct ieee80211_chanctx *old_ctx;
  1536. int err;
  1537. lockdep_assert_wiphy(local->hw.wiphy);
  1538. new_ctx = link->reserved_chanctx;
  1539. old_ctx = ieee80211_link_get_chanctx(link);
  1540. if (WARN_ON(!new_ctx))
  1541. return -EINVAL;
  1542. if (WARN_ON(new_ctx->replace_state ==
  1543. IEEE80211_CHANCTX_WILL_BE_REPLACED))
  1544. return -EINVAL;
  1545. if (WARN_ON(link->reserved_ready))
  1546. return -EINVAL;
  1547. link->reserved_ready = true;
  1548. if (new_ctx->replace_state == IEEE80211_CHANCTX_REPLACE_NONE) {
  1549. if (old_ctx)
  1550. return ieee80211_link_use_reserved_reassign(link);
  1551. return ieee80211_link_use_reserved_assign(link);
  1552. }
  1553. /*
  1554. * In-place reservation may need to be finalized now either if:
  1555. * a) sdata is taking part in the swapping itself and is the last one
  1556. * b) sdata has switched with a re-assign reservation to an existing
  1557. * context readying in-place switching of old_ctx
  1558. *
  1559. * In case of (b) do not propagate the error up because the requested
  1560. * sdata already switched successfully. Just spill an extra warning.
  1561. * The ieee80211_vif_use_reserved_switch() already stops all necessary
  1562. * interfaces upon failure.
  1563. */
  1564. if ((old_ctx &&
  1565. old_ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) ||
  1566. new_ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) {
  1567. err = ieee80211_vif_use_reserved_switch(local);
  1568. if (err && err != -EAGAIN) {
  1569. if (new_ctx->replace_state ==
  1570. IEEE80211_CHANCTX_REPLACES_OTHER)
  1571. return err;
  1572. wiphy_info(local->hw.wiphy,
  1573. "depending in-place reservation failed (err=%d)\n",
  1574. err);
  1575. }
  1576. }
  1577. return 0;
  1578. }
  1579. /*
  1580. * This is similar to ieee80211_chanctx_compatible(), but rechecks
  1581. * against all the links actually using it (except the one that's
  1582. * passed, since that one is changing).
  1583. * This is done in order to allow changes to the AP's bandwidth for
  1584. * wider bandwidth OFDMA purposes, which wouldn't be treated as
  1585. * compatible by ieee80211_chanctx_recheck() but is OK if the link
  1586. * requesting the update is the only one using it.
  1587. */
  1588. static const struct ieee80211_chan_req *
  1589. ieee80211_chanctx_recheck(struct ieee80211_local *local,
  1590. struct ieee80211_link_data *skip_link,
  1591. struct ieee80211_chanctx *ctx,
  1592. const struct ieee80211_chan_req *req,
  1593. struct ieee80211_chan_req *tmp)
  1594. {
  1595. const struct ieee80211_chan_req *ret = req;
  1596. struct ieee80211_link_data *link;
  1597. lockdep_assert_wiphy(local->hw.wiphy);
  1598. for_each_sdata_link(local, link) {
  1599. if (link == skip_link)
  1600. continue;
  1601. if (rcu_access_pointer(link->conf->chanctx_conf) == &ctx->conf) {
  1602. ret = ieee80211_chanreq_compatible(ret,
  1603. &link->conf->chanreq,
  1604. tmp);
  1605. if (!ret)
  1606. return NULL;
  1607. }
  1608. if (link->reserved_chanctx == ctx) {
  1609. ret = ieee80211_chanreq_compatible(ret,
  1610. &link->reserved,
  1611. tmp);
  1612. if (!ret)
  1613. return NULL;
  1614. }
  1615. }
  1616. *tmp = *ret;
  1617. return tmp;
  1618. }
  1619. int ieee80211_link_change_chanreq(struct ieee80211_link_data *link,
  1620. const struct ieee80211_chan_req *chanreq,
  1621. u64 *changed)
  1622. {
  1623. struct ieee80211_sub_if_data *sdata = link->sdata;
  1624. struct ieee80211_bss_conf *link_conf = link->conf;
  1625. struct ieee80211_local *local = sdata->local;
  1626. struct ieee80211_chanctx_conf *conf;
  1627. struct ieee80211_chanctx *ctx;
  1628. const struct ieee80211_chan_req *compat;
  1629. struct ieee80211_chan_req tmp;
  1630. lockdep_assert_wiphy(local->hw.wiphy);
  1631. if (!cfg80211_chandef_usable(sdata->local->hw.wiphy,
  1632. &chanreq->oper,
  1633. IEEE80211_CHAN_DISABLED))
  1634. return -EINVAL;
  1635. /* for non-HT 20 MHz the rest doesn't matter */
  1636. if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT &&
  1637. cfg80211_chandef_identical(&chanreq->oper, &link_conf->chanreq.oper))
  1638. return 0;
  1639. /* but you cannot switch to/from it */
  1640. if (chanreq->oper.width == NL80211_CHAN_WIDTH_20_NOHT ||
  1641. link_conf->chanreq.oper.width == NL80211_CHAN_WIDTH_20_NOHT)
  1642. return -EINVAL;
  1643. conf = rcu_dereference_protected(link_conf->chanctx_conf,
  1644. lockdep_is_held(&local->hw.wiphy->mtx));
  1645. if (!conf)
  1646. return -EINVAL;
  1647. ctx = container_of(conf, struct ieee80211_chanctx, conf);
  1648. compat = ieee80211_chanctx_recheck(local, link, ctx, chanreq, &tmp);
  1649. if (!compat)
  1650. return -EINVAL;
  1651. switch (ctx->replace_state) {
  1652. case IEEE80211_CHANCTX_REPLACE_NONE:
  1653. if (!ieee80211_chanctx_reserved_chanreq(local, ctx, compat,
  1654. &tmp))
  1655. return -EBUSY;
  1656. break;
  1657. case IEEE80211_CHANCTX_WILL_BE_REPLACED:
  1658. /* TODO: Perhaps the bandwidth change could be treated as a
  1659. * reservation itself? */
  1660. return -EBUSY;
  1661. case IEEE80211_CHANCTX_REPLACES_OTHER:
  1662. /* channel context that is going to replace another channel
  1663. * context doesn't really exist and shouldn't be assigned
  1664. * anywhere yet */
  1665. WARN_ON(1);
  1666. break;
  1667. }
  1668. ieee80211_link_update_chanreq(link, chanreq);
  1669. ieee80211_recalc_chanctx_chantype(local, ctx);
  1670. *changed |= BSS_CHANGED_BANDWIDTH;
  1671. return 0;
  1672. }
  1673. void ieee80211_link_release_channel(struct ieee80211_link_data *link)
  1674. {
  1675. struct ieee80211_sub_if_data *sdata = link->sdata;
  1676. if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
  1677. return;
  1678. lockdep_assert_wiphy(sdata->local->hw.wiphy);
  1679. if (rcu_access_pointer(link->conf->chanctx_conf))
  1680. __ieee80211_link_release_channel(link, false);
  1681. }
  1682. void ieee80211_link_vlan_copy_chanctx(struct ieee80211_link_data *link)
  1683. {
  1684. struct ieee80211_sub_if_data *sdata = link->sdata;
  1685. unsigned int link_id = link->link_id;
  1686. struct ieee80211_bss_conf *link_conf = link->conf;
  1687. struct ieee80211_bss_conf *ap_conf;
  1688. struct ieee80211_local *local = sdata->local;
  1689. struct ieee80211_sub_if_data *ap;
  1690. struct ieee80211_chanctx_conf *conf;
  1691. lockdep_assert_wiphy(local->hw.wiphy);
  1692. if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
  1693. return;
  1694. ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
  1695. ap_conf = wiphy_dereference(local->hw.wiphy,
  1696. ap->vif.link_conf[link_id]);
  1697. conf = wiphy_dereference(local->hw.wiphy,
  1698. ap_conf->chanctx_conf);
  1699. rcu_assign_pointer(link_conf->chanctx_conf, conf);
  1700. }
  1701. void ieee80211_iter_chan_contexts_atomic(
  1702. struct ieee80211_hw *hw,
  1703. void (*iter)(struct ieee80211_hw *hw,
  1704. struct ieee80211_chanctx_conf *chanctx_conf,
  1705. void *data),
  1706. void *iter_data)
  1707. {
  1708. struct ieee80211_local *local = hw_to_local(hw);
  1709. struct ieee80211_chanctx *ctx;
  1710. rcu_read_lock();
  1711. list_for_each_entry_rcu(ctx, &local->chanctx_list, list)
  1712. if (ctx->driver_present)
  1713. iter(hw, &ctx->conf, iter_data);
  1714. rcu_read_unlock();
  1715. }
  1716. EXPORT_SYMBOL_GPL(ieee80211_iter_chan_contexts_atomic);