1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* Copyright(c) 2020-2022 Realtek Corporation 3 */ 4 5 #include "chan.h" 6 #include "coex.h" 7 #include "debug.h" 8 #include "fw.h" 9 #include "mac.h" 10 #include "phy.h" 11 #include "ps.h" 12 #include "sar.h" 13 #include "util.h" 14 15 static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev, 16 enum rtw89_chanctx_idx idx1, 17 enum rtw89_chanctx_idx idx2); 18 19 static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band, 20 u8 center_chan) 21 { 22 switch (band) { 23 default: 24 case RTW89_BAND_2G: 25 switch (center_chan) { 26 default: 27 case 1 ... 14: 28 return RTW89_CH_2G; 29 } 30 case RTW89_BAND_5G: 31 switch (center_chan) { 32 default: 33 case 36 ... 64: 34 return RTW89_CH_5G_BAND_1; 35 case 100 ... 144: 36 return RTW89_CH_5G_BAND_3; 37 case 149 ... 177: 38 return RTW89_CH_5G_BAND_4; 39 } 40 case RTW89_BAND_6G: 41 switch (center_chan) { 42 default: 43 case 1 ... 29: 44 return RTW89_CH_6G_BAND_IDX0; 45 case 33 ... 61: 46 return RTW89_CH_6G_BAND_IDX1; 47 case 65 ... 93: 48 return RTW89_CH_6G_BAND_IDX2; 49 case 97 ... 125: 50 return RTW89_CH_6G_BAND_IDX3; 51 case 129 ... 157: 52 return RTW89_CH_6G_BAND_IDX4; 53 case 161 ... 189: 54 return RTW89_CH_6G_BAND_IDX5; 55 case 193 ... 221: 56 return RTW89_CH_6G_BAND_IDX6; 57 case 225 ... 253: 58 return RTW89_CH_6G_BAND_IDX7; 59 } 60 } 61 } 62 63 static enum rtw89_tx_comp_band rtw89_get_tx_comp_band(enum rtw89_band band, 64 u8 center_chan) 65 { 66 switch (band) { 67 default: 68 case RTW89_BAND_2G: 69 return RTW89_TX_COMP_BAND_2GHZ; 70 case RTW89_BAND_5G: 71 if (center_chan < 149) 72 return RTW89_TX_COMP_BAND_5GHZ_L; 73 else 74 return RTW89_TX_COMP_BAND_5GHZ_H; 75 case RTW89_BAND_6G: 76 if (center_chan < 65) 77 return RTW89_TX_COMP_BAND_5GHZ_H; 78 else if (center_chan < 193) 79 return RTW89_TX_COMP_BAND_6GHZ_M; 80 else 81 return RTW89_TX_COMP_BAND_6GHZ_UH; 82 } 83 } 84 85 static enum rtw89_sc_offset rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw, 86 u32 center_freq, 87 u32 primary_freq) 88 { 89 u8 primary_chan_idx; 90 u32 offset; 91 92 switch (bw) { 93 default: 94 case RTW89_CHANNEL_WIDTH_20: 95 primary_chan_idx = RTW89_SC_DONT_CARE; 96 break; 97 case RTW89_CHANNEL_WIDTH_40: 98 if (primary_freq > center_freq) 99 primary_chan_idx = RTW89_SC_20_UPPER; 100 else 101 primary_chan_idx = RTW89_SC_20_LOWER; 102 break; 103 case RTW89_CHANNEL_WIDTH_80: 104 case RTW89_CHANNEL_WIDTH_160: 105 if (primary_freq > center_freq) { 106 offset = (primary_freq - center_freq - 10) / 20; 107 primary_chan_idx = RTW89_SC_20_UPPER + offset * 2; 108 } else { 109 offset = (center_freq - primary_freq - 10) / 20; 110 primary_chan_idx = RTW89_SC_20_LOWER + offset * 2; 111 } 112 break; 113 } 114 115 return primary_chan_idx; 116 } 117 118 static u8 rtw89_get_primary_sb_idx(u8 central_ch, u8 pri_ch, 119 enum rtw89_bandwidth bw) 120 { 121 static const u8 prisb_cal_ofst[RTW89_CHANNEL_WIDTH_ORDINARY_NUM] = { 122 0, 2, 6, 14, 30 123 }; 124 125 if (bw >= RTW89_CHANNEL_WIDTH_ORDINARY_NUM) 126 return 0; 127 128 return (prisb_cal_ofst[bw] + pri_ch - central_ch) / 4; 129 } 130 131 void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan, 132 enum rtw89_band band, enum rtw89_bandwidth bandwidth) 133 { 134 enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band); 135 u32 center_freq, primary_freq; 136 137 memset(chan, 0, sizeof(*chan)); 138 chan->channel = center_chan; 139 chan->primary_channel = primary_chan; 140 chan->band_type = band; 141 chan->band_width = bandwidth; 142 143 center_freq = ieee80211_channel_to_frequency(center_chan, nl_band); 144 primary_freq = ieee80211_channel_to_frequency(primary_chan, nl_band); 145 146 chan->freq = center_freq; 147 chan->subband_type = rtw89_get_subband_type(band, center_chan); 148 chan->tx_comp_band = rtw89_get_tx_comp_band(band, center_chan); 149 chan->pri_ch_idx = rtw89_get_primary_chan_idx(bandwidth, center_freq, 150 primary_freq); 151 chan->pri_sb_idx = rtw89_get_primary_sb_idx(center_chan, primary_chan, 152 bandwidth); 153 } 154 155 static void _rtw89_chan_update_punctured(struct rtw89_dev *rtwdev, 156 struct rtw89_vif_link *rtwvif_link, 157 const struct cfg80211_chan_def *chandef) 158 { 159 struct ieee80211_bss_conf *bss_conf; 160 161 if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION && 162 rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT) 163 return; 164 165 rcu_read_lock(); 166 167 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); 168 if (!bss_conf->eht_support) { 169 rcu_read_unlock(); 170 return; 171 } 172 173 rcu_read_unlock(); 174 175 rtw89_chip_h2c_punctured_cmac_tbl(rtwdev, rtwvif_link, chandef->punctured); 176 } 177 178 static void rtw89_chan_update_punctured(struct rtw89_dev *rtwdev, 179 enum rtw89_chanctx_idx idx, 180 const struct cfg80211_chan_def *chandef) 181 { 182 struct rtw89_vif_link *rtwvif_link; 183 struct rtw89_vif *rtwvif; 184 unsigned int link_id; 185 186 rtw89_for_each_rtwvif(rtwdev, rtwvif) { 187 rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { 188 if (!rtwvif_link->chanctx_assigned || 189 rtwvif_link->chanctx_idx != idx) 190 continue; 191 192 _rtw89_chan_update_punctured(rtwdev, rtwvif_link, chandef); 193 } 194 } 195 } 196 197 bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev, 198 enum rtw89_chanctx_idx idx, 199 const struct rtw89_chan *new) 200 { 201 struct rtw89_hal *hal = &rtwdev->hal; 202 struct rtw89_chan *chan = &hal->chanctx[idx].chan; 203 struct rtw89_chan_rcd *rcd = &hal->chanctx[idx].rcd; 204 bool band_changed; 205 206 rcd->prev_primary_channel = chan->primary_channel; 207 rcd->prev_band_type = chan->band_type; 208 band_changed = new->band_type != chan->band_type; 209 rcd->band_changed = band_changed; 210 211 *chan = *new; 212 return band_changed; 213 } 214 215 int rtw89_iterate_entity_chan(struct rtw89_dev *rtwdev, 216 int (*iterator)(const struct rtw89_chan *chan, 217 void *data), 218 void *data) 219 { 220 struct rtw89_hal *hal = &rtwdev->hal; 221 const struct rtw89_chan *chan; 222 int ret; 223 u8 idx; 224 225 lockdep_assert_wiphy(rtwdev->hw->wiphy); 226 227 for_each_set_bit(idx, hal->entity_map, NUM_OF_RTW89_CHANCTX) { 228 chan = rtw89_chan_get(rtwdev, idx); 229 ret = iterator(chan, data); 230 if (ret) 231 return ret; 232 } 233 234 return 0; 235 } 236 237 static void __rtw89_config_entity_chandef(struct rtw89_dev *rtwdev, 238 enum rtw89_chanctx_idx idx, 239 const struct cfg80211_chan_def *chandef) 240 { 241 struct rtw89_hal *hal = &rtwdev->hal; 242 243 hal->chanctx[idx].chandef = *chandef; 244 } 245 246 void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev, 247 enum rtw89_chanctx_idx idx, 248 const struct cfg80211_chan_def *chandef) 249 { 250 struct rtw89_hal *hal = &rtwdev->hal; 251 252 if (!chandef) { 253 clear_bit(idx, hal->entity_map); 254 return; 255 } 256 257 __rtw89_config_entity_chandef(rtwdev, idx, chandef); 258 set_bit(idx, hal->entity_map); 259 } 260 261 void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev, 262 struct rtw89_vif_link *rtwvif_link, 263 const struct cfg80211_chan_def *chandef) 264 { 265 enum rtw89_chanctx_idx idx = rtwvif_link->chanctx_idx; 266 struct rtw89_hal *hal = &rtwdev->hal; 267 enum rtw89_chanctx_idx cur; 268 269 if (chandef) { 270 cur = atomic_cmpxchg(&hal->roc_chanctx_idx, 271 RTW89_CHANCTX_IDLE, idx); 272 if (cur != RTW89_CHANCTX_IDLE) { 273 rtw89_debug(rtwdev, RTW89_DBG_TXRX, 274 "ROC still processing on entity %d\n", idx); 275 return; 276 } 277 278 hal->roc_chandef = *chandef; 279 hal->roc_link_index = rtw89_vif_link_inst_get_index(rtwvif_link); 280 } else { 281 cur = atomic_cmpxchg(&hal->roc_chanctx_idx, idx, 282 RTW89_CHANCTX_IDLE); 283 if (cur == idx) 284 return; 285 286 if (cur == RTW89_CHANCTX_IDLE) 287 rtw89_debug(rtwdev, RTW89_DBG_TXRX, 288 "ROC already finished on entity %d\n", idx); 289 else 290 rtw89_debug(rtwdev, RTW89_DBG_TXRX, 291 "ROC is processing on entity %d\n", cur); 292 } 293 } 294 295 static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev) 296 { 297 struct cfg80211_chan_def chandef = {0}; 298 299 rtw89_get_default_chandef(&chandef); 300 __rtw89_config_entity_chandef(rtwdev, RTW89_CHANCTX_0, &chandef); 301 } 302 303 void rtw89_entity_init(struct rtw89_dev *rtwdev) 304 { 305 struct rtw89_hal *hal = &rtwdev->hal; 306 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt; 307 int i, j; 308 309 hal->entity_pause = false; 310 bitmap_zero(hal->entity_map, NUM_OF_RTW89_CHANCTX); 311 bitmap_zero(hal->changes, NUM_OF_RTW89_CHANCTX_CHANGES); 312 atomic_set(&hal->roc_chanctx_idx, RTW89_CHANCTX_IDLE); 313 314 INIT_LIST_HEAD(&mgnt->active_list); 315 316 for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++) { 317 for (j = 0; j < __RTW89_MLD_MAX_LINK_NUM; j++) 318 mgnt->chanctx_tbl[i][j] = RTW89_CHANCTX_IDLE; 319 } 320 321 hal->entity_force_hw = RTW89_PHY_NUM; 322 323 rtw89_config_default_chandef(rtwdev); 324 } 325 326 static bool rtw89_vif_is_active_role(struct rtw89_vif *rtwvif) 327 { 328 struct rtw89_vif_link *rtwvif_link; 329 unsigned int link_id; 330 331 rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) 332 if (rtwvif_link->chanctx_assigned) 333 return true; 334 335 return false; 336 } 337 338 static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev, 339 struct rtw89_entity_weight *w) 340 { 341 struct rtw89_hal *hal = &rtwdev->hal; 342 const struct rtw89_chanctx_cfg *cfg; 343 struct rtw89_vif *rtwvif; 344 int idx; 345 346 w->registered_chanctxs = bitmap_weight(hal->entity_map, NUM_OF_RTW89_CHANCTX); 347 348 for_each_set_bit(idx, hal->entity_map, NUM_OF_RTW89_CHANCTX) { 349 cfg = hal->chanctx[idx].cfg; 350 if (!cfg) { 351 /* doesn't run with chanctx ops; one channel at most */ 352 w->active_chanctxs = 1; 353 break; 354 } 355 356 if (cfg->ref_count > 0) 357 w->active_chanctxs++; 358 } 359 360 rtw89_for_each_rtwvif(rtwdev, rtwvif) { 361 if (rtw89_vif_is_active_role(rtwvif)) 362 w->active_roles++; 363 } 364 } 365 366 static void rtw89_normalize_link_chanctx(struct rtw89_dev *rtwdev, 367 struct rtw89_vif_link *rtwvif_link) 368 { 369 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; 370 struct rtw89_vif_link *cur; 371 372 if (unlikely(!rtwvif_link->chanctx_assigned)) 373 return; 374 375 cur = rtw89_get_designated_link(rtwvif); 376 if (unlikely(!cur) || !cur->chanctx_assigned) 377 return; 378 379 if (cur == rtwvif_link) 380 return; 381 382 rtw89_swap_chanctx(rtwdev, rtwvif_link->chanctx_idx, cur->chanctx_idx); 383 } 384 385 const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev, 386 const char *caller_message, 387 u8 link_index, bool nullchk) 388 { 389 struct rtw89_hal *hal = &rtwdev->hal; 390 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt; 391 enum rtw89_chanctx_idx chanctx_idx; 392 enum rtw89_chanctx_idx roc_idx; 393 enum rtw89_entity_mode mode; 394 u8 role_index; 395 396 lockdep_assert_wiphy(rtwdev->hw->wiphy); 397 398 if (unlikely(link_index >= __RTW89_MLD_MAX_LINK_NUM)) { 399 WARN(1, "link index %u is invalid (max link inst num: %d)\n", 400 link_index, __RTW89_MLD_MAX_LINK_NUM); 401 goto dflt; 402 } 403 404 mode = rtw89_get_entity_mode(rtwdev); 405 switch (mode) { 406 case RTW89_ENTITY_MODE_SCC_OR_SMLD: 407 case RTW89_ENTITY_MODE_MCC: 408 role_index = 0; 409 break; 410 case RTW89_ENTITY_MODE_MCC_PREPARE: 411 role_index = 1; 412 break; 413 default: 414 WARN(1, "Invalid ent mode: %d\n", mode); 415 goto dflt; 416 } 417 418 chanctx_idx = mgnt->chanctx_tbl[role_index][link_index]; 419 if (chanctx_idx == RTW89_CHANCTX_IDLE) 420 goto dflt; 421 422 roc_idx = atomic_read(&hal->roc_chanctx_idx); 423 if (roc_idx != RTW89_CHANCTX_IDLE) { 424 /* ROC is ongoing (given ROC runs on @hal->roc_link_index). 425 * If @link_index is the same, get the ongoing ROC chanctx. 426 */ 427 if (link_index == hal->roc_link_index) 428 chanctx_idx = roc_idx; 429 } 430 431 return rtw89_chan_get(rtwdev, chanctx_idx); 432 433 dflt: 434 if (unlikely(nullchk)) 435 return NULL; 436 437 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 438 "%s (%s): prefetch NULL on link index %u\n", 439 __func__, caller_message ?: "", link_index); 440 441 return rtw89_chan_get(rtwdev, RTW89_CHANCTX_0); 442 } 443 EXPORT_SYMBOL(__rtw89_mgnt_chan_get); 444 445 bool rtw89_entity_check_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) 446 { 447 switch (rtwdev->mlo_dbcc_mode) { 448 case MLO_2_PLUS_0_1RF: 449 return phy_idx == RTW89_PHY_0; 450 case MLO_0_PLUS_2_1RF: 451 return phy_idx == RTW89_PHY_1; 452 default: 453 return false; 454 } 455 } 456 457 void rtw89_entity_force_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) 458 { 459 rtwdev->hal.entity_force_hw = phy_idx; 460 461 if (phy_idx != RTW89_PHY_NUM) 462 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "%s: %d\n", __func__, phy_idx); 463 else 464 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "%s: (none)\n", __func__); 465 } 466 467 static enum rtw89_mlo_dbcc_mode 468 rtw89_entity_sel_mlo_dbcc_mode(struct rtw89_dev *rtwdev, u8 active_hws) 469 { 470 if (rtwdev->chip->chip_gen != RTW89_CHIP_BE) 471 return MLO_DBCC_NOT_SUPPORT; 472 473 switch (rtwdev->hal.entity_force_hw) { 474 case RTW89_PHY_0: 475 return MLO_2_PLUS_0_1RF; 476 case RTW89_PHY_1: 477 return MLO_0_PLUS_2_1RF; 478 default: 479 break; 480 } 481 482 switch (active_hws) { 483 case BIT(0): 484 return MLO_2_PLUS_0_1RF; 485 case BIT(1): 486 return MLO_0_PLUS_2_1RF; 487 case BIT(0) | BIT(1): 488 default: 489 return MLO_1_PLUS_1_1RF; 490 } 491 } 492 493 static 494 void rtw89_entity_recalc_mlo_dbcc_mode(struct rtw89_dev *rtwdev, u8 active_hws) 495 { 496 enum rtw89_mlo_dbcc_mode mode; 497 498 mode = rtw89_entity_sel_mlo_dbcc_mode(rtwdev, active_hws); 499 rtwdev->mlo_dbcc_mode = mode; 500 501 rtw89_debug(rtwdev, RTW89_DBG_STATE, "recalc mlo dbcc mode to %d\n", mode); 502 } 503 504 static void rtw89_entity_recalc_mgnt_roles(struct rtw89_dev *rtwdev) 505 { 506 struct rtw89_hal *hal = &rtwdev->hal; 507 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt; 508 struct rtw89_vif_link *link; 509 struct rtw89_vif *role; 510 u8 active_hws = 0; 511 u8 pos = 0; 512 int i, j; 513 514 lockdep_assert_wiphy(rtwdev->hw->wiphy); 515 516 for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++) 517 mgnt->active_roles[i] = NULL; 518 519 for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++) { 520 for (j = 0; j < __RTW89_MLD_MAX_LINK_NUM; j++) 521 mgnt->chanctx_tbl[i][j] = RTW89_CHANCTX_IDLE; 522 } 523 524 /* To be consistent with legacy behavior, expect the first active role 525 * which uses RTW89_CHANCTX_0 to put at position 0 and its designated 526 * link take RTW89_CHANCTX_0. (normalizing) 527 */ 528 list_for_each_entry(role, &mgnt->active_list, mgnt_entry) { 529 for (i = 0; i < role->links_inst_valid_num; i++) { 530 link = rtw89_vif_get_link_inst(role, i); 531 if (!link || !link->chanctx_assigned) 532 continue; 533 534 if (link->chanctx_idx == RTW89_CHANCTX_0) { 535 rtw89_normalize_link_chanctx(rtwdev, link); 536 537 list_del(&role->mgnt_entry); 538 list_add(&role->mgnt_entry, &mgnt->active_list); 539 goto fill; 540 } 541 } 542 } 543 544 fill: 545 list_for_each_entry(role, &mgnt->active_list, mgnt_entry) { 546 if (unlikely(pos >= RTW89_MAX_INTERFACE_NUM)) { 547 rtw89_warn(rtwdev, 548 "%s: active roles are over max iface num\n", 549 __func__); 550 break; 551 } 552 553 for (i = 0; i < role->links_inst_valid_num; i++) { 554 link = rtw89_vif_get_link_inst(role, i); 555 if (!link || !link->chanctx_assigned) 556 continue; 557 558 mgnt->chanctx_tbl[pos][i] = link->chanctx_idx; 559 active_hws |= BIT(i); 560 } 561 562 mgnt->active_roles[pos++] = role; 563 } 564 565 rtw89_entity_recalc_mlo_dbcc_mode(rtwdev, active_hws); 566 } 567 568 enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev) 569 { 570 DECLARE_BITMAP(recalc_map, NUM_OF_RTW89_CHANCTX) = {}; 571 struct rtw89_hal *hal = &rtwdev->hal; 572 const struct cfg80211_chan_def *chandef; 573 struct rtw89_entity_weight w = {}; 574 enum rtw89_entity_mode mode; 575 struct rtw89_chan chan; 576 u8 idx; 577 578 lockdep_assert_wiphy(rtwdev->hw->wiphy); 579 580 bitmap_copy(recalc_map, hal->entity_map, NUM_OF_RTW89_CHANCTX); 581 582 rtw89_entity_calculate_weight(rtwdev, &w); 583 switch (w.active_chanctxs) { 584 default: 585 rtw89_warn(rtwdev, "unknown ent chanctxs weight: %d\n", 586 w.active_chanctxs); 587 bitmap_zero(recalc_map, NUM_OF_RTW89_CHANCTX); 588 fallthrough; 589 case 0: 590 if (!w.registered_chanctxs) 591 rtw89_config_default_chandef(rtwdev); 592 set_bit(RTW89_CHANCTX_0, recalc_map); 593 fallthrough; 594 case 1: 595 mode = RTW89_ENTITY_MODE_SCC_OR_SMLD; 596 break; 597 case 2 ... NUM_OF_RTW89_CHANCTX: 598 if (w.active_roles == 1) { 599 mode = RTW89_ENTITY_MODE_SCC_OR_SMLD; 600 break; 601 } 602 603 if (w.active_roles != NUM_OF_RTW89_MCC_ROLES) { 604 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 605 "unhandled ent: %d chanctxs %d roles\n", 606 w.active_chanctxs, w.active_roles); 607 return RTW89_ENTITY_MODE_UNHANDLED; 608 } 609 610 mode = rtw89_get_entity_mode(rtwdev); 611 if (mode == RTW89_ENTITY_MODE_MCC) 612 break; 613 614 mode = RTW89_ENTITY_MODE_MCC_PREPARE; 615 break; 616 } 617 618 for_each_set_bit(idx, recalc_map, NUM_OF_RTW89_CHANCTX) { 619 chandef = rtw89_chandef_get(rtwdev, idx); 620 rtw89_get_channel_params(chandef, &chan); 621 if (chan.channel == 0) { 622 WARN(1, "Invalid channel on chanctx %d\n", idx); 623 return RTW89_ENTITY_MODE_INVALID; 624 } 625 626 rtw89_assign_entity_chan(rtwdev, idx, &chan); 627 } 628 629 rtw89_entity_recalc_mgnt_roles(rtwdev); 630 631 if (hal->entity_pause) 632 return rtw89_get_entity_mode(rtwdev); 633 634 rtw89_set_entity_mode(rtwdev, mode); 635 return mode; 636 } 637 638 static void rtw89_chanctx_notify(struct rtw89_dev *rtwdev, 639 enum rtw89_chanctx_state state) 640 { 641 const struct rtw89_chip_info *chip = rtwdev->chip; 642 const struct rtw89_chanctx_listener *listener = chip->chanctx_listener; 643 int i; 644 645 if (!listener) 646 return; 647 648 for (i = 0; i < NUM_OF_RTW89_CHANCTX_CALLBACKS; i++) { 649 if (!listener->callbacks[i]) 650 continue; 651 652 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 653 "chanctx notify listener: cb %d, state %d\n", 654 i, state); 655 656 listener->callbacks[i](rtwdev, state); 657 } 658 } 659 660 static bool rtw89_concurrent_via_mrc(struct rtw89_dev *rtwdev) 661 { 662 enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen; 663 664 return chip_gen == RTW89_CHIP_BE; 665 } 666 667 /* This function centrally manages how MCC roles are sorted and iterated. 668 * And, it guarantees that ordered_idx is less than NUM_OF_RTW89_MCC_ROLES. 669 * So, if data needs to pass an array for ordered_idx, the array can declare 670 * with NUM_OF_RTW89_MCC_ROLES. Besides, the entire iteration will stop 671 * immediately as long as iterator returns a non-zero value. 672 */ 673 static 674 int rtw89_iterate_mcc_roles(struct rtw89_dev *rtwdev, 675 int (*iterator)(struct rtw89_dev *rtwdev, 676 struct rtw89_mcc_role *mcc_role, 677 unsigned int ordered_idx, 678 void *data), 679 void *data) 680 { 681 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 682 struct rtw89_mcc_role * const roles[] = { 683 &mcc->role_ref, 684 &mcc->role_aux, 685 }; 686 unsigned int idx; 687 int ret; 688 689 BUILD_BUG_ON(ARRAY_SIZE(roles) != NUM_OF_RTW89_MCC_ROLES); 690 691 for (idx = 0; idx < NUM_OF_RTW89_MCC_ROLES; idx++) { 692 ret = iterator(rtwdev, roles[idx], idx, data); 693 if (ret) 694 return ret; 695 } 696 697 return 0; 698 } 699 700 static u32 rtw89_mcc_get_tbtt_ofst(struct rtw89_dev *rtwdev, 701 struct rtw89_mcc_role *role, u64 tsf) 702 { 703 struct rtw89_vif_link *rtwvif_link = role->rtwvif_link; 704 u32 bcn_intvl_us = ieee80211_tu_to_usec(role->beacon_interval); 705 u64 sync_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf); 706 u32 remainder; 707 708 if (role->is_go) { 709 sync_tsf = 0; 710 } else if (tsf < sync_tsf) { 711 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 712 "MCC get tbtt ofst: tsf might not update yet\n"); 713 sync_tsf = 0; 714 } 715 716 div_u64_rem(tsf - sync_tsf, bcn_intvl_us, &remainder); 717 718 return remainder; 719 } 720 721 static int __mcc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux) 722 { 723 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 724 struct rtw89_mcc_role *ref = &mcc->role_ref; 725 struct rtw89_mcc_role *aux = &mcc->role_aux; 726 struct rtw89_mac_mcc_tsf_rpt rpt = {}; 727 struct rtw89_fw_mcc_tsf_req req = {}; 728 int ret; 729 730 req.group = mcc->group; 731 req.macid_x = ref->rtwvif_link->mac_id; 732 req.macid_y = aux->rtwvif_link->mac_id; 733 ret = rtw89_fw_h2c_mcc_req_tsf(rtwdev, &req, &rpt); 734 if (ret) { 735 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 736 "MCC h2c failed to request tsf: %d\n", ret); 737 return ret; 738 } 739 740 *tsf_ref = (u64)rpt.tsf_x_high << 32 | rpt.tsf_x_low; 741 *tsf_aux = (u64)rpt.tsf_y_high << 32 | rpt.tsf_y_low; 742 743 return 0; 744 } 745 746 static int __mrc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux) 747 { 748 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 749 struct rtw89_mcc_role *ref = &mcc->role_ref; 750 struct rtw89_mcc_role *aux = &mcc->role_aux; 751 struct rtw89_fw_mrc_req_tsf_arg arg = {}; 752 struct rtw89_mac_mrc_tsf_rpt rpt = {}; 753 int ret; 754 755 BUILD_BUG_ON(RTW89_MAC_MRC_MAX_REQ_TSF_NUM < NUM_OF_RTW89_MCC_ROLES); 756 757 arg.num = 2; 758 arg.infos[0].band = ref->rtwvif_link->mac_idx; 759 arg.infos[0].port = ref->rtwvif_link->port; 760 arg.infos[1].band = aux->rtwvif_link->mac_idx; 761 arg.infos[1].port = aux->rtwvif_link->port; 762 763 ret = rtw89_fw_h2c_mrc_req_tsf(rtwdev, &arg, &rpt); 764 if (ret) { 765 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 766 "MRC h2c failed to request tsf: %d\n", ret); 767 return ret; 768 } 769 770 *tsf_ref = rpt.tsfs[0]; 771 *tsf_aux = rpt.tsfs[1]; 772 773 return 0; 774 } 775 776 static u16 rtw89_mcc_get_bcn_ofst(struct rtw89_dev *rtwdev) 777 { 778 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 779 struct rtw89_mcc_role *ref = &mcc->role_ref; 780 struct rtw89_mcc_role *aux = &mcc->role_aux; 781 u32 bcn_intvl_ref_us = ieee80211_tu_to_usec(ref->beacon_interval); 782 u32 tbtt_ofst_ref, tbtt_ofst_aux; 783 u64 tsf_ref, tsf_aux; 784 int ret; 785 786 if (rtw89_concurrent_via_mrc(rtwdev)) 787 ret = __mrc_fw_req_tsf(rtwdev, &tsf_ref, &tsf_aux); 788 else 789 ret = __mcc_fw_req_tsf(rtwdev, &tsf_ref, &tsf_aux); 790 791 if (ret) 792 return RTW89_MCC_DFLT_BCN_OFST_TIME; 793 794 tbtt_ofst_ref = rtw89_mcc_get_tbtt_ofst(rtwdev, ref, tsf_ref); 795 tbtt_ofst_aux = rtw89_mcc_get_tbtt_ofst(rtwdev, aux, tsf_aux); 796 797 while (tbtt_ofst_ref < tbtt_ofst_aux) 798 tbtt_ofst_ref += bcn_intvl_ref_us; 799 800 return (tbtt_ofst_ref - tbtt_ofst_aux) / 1024; 801 } 802 803 static 804 void rtw89_mcc_role_fw_macid_bitmap_set_bit(struct rtw89_mcc_role *mcc_role, 805 unsigned int bit) 806 { 807 unsigned int idx = bit / 8; 808 unsigned int pos = bit % 8; 809 810 if (idx >= ARRAY_SIZE(mcc_role->macid_bitmap)) 811 return; 812 813 mcc_role->macid_bitmap[idx] |= BIT(pos); 814 } 815 816 static 817 u32 rtw89_mcc_role_fw_macid_bitmap_to_u32(struct rtw89_mcc_role *mcc_role) 818 { 819 unsigned int macid; 820 unsigned int i, j; 821 u32 bitmap = 0; 822 823 for (i = 0; i < ARRAY_SIZE(mcc_role->macid_bitmap); i++) { 824 for (j = 0; j < 8; j++) { 825 macid = i * 8 + j; 826 if (macid >= 32) 827 goto out; 828 829 if (mcc_role->macid_bitmap[i] & BIT(j)) 830 bitmap |= BIT(macid); 831 } 832 } 833 834 out: 835 return bitmap; 836 } 837 838 static void rtw89_mcc_role_macid_sta_iter(void *data, struct ieee80211_sta *sta) 839 { 840 struct rtw89_mcc_role *mcc_role = data; 841 struct rtw89_vif *target = mcc_role->rtwvif_link->rtwvif; 842 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta); 843 struct rtw89_vif *rtwvif = rtwsta->rtwvif; 844 u8 macid; 845 846 if (rtwvif != target) 847 return; 848 849 macid = rtw89_sta_get_main_macid(rtwsta); 850 rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, macid); 851 } 852 853 static void rtw89_mcc_fill_role_macid_bitmap(struct rtw89_dev *rtwdev, 854 struct rtw89_mcc_role *mcc_role) 855 { 856 struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link; 857 858 rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwvif_link->mac_id); 859 ieee80211_iterate_stations_atomic(rtwdev->hw, 860 rtw89_mcc_role_macid_sta_iter, 861 mcc_role); 862 } 863 864 static void rtw89_mcc_fill_role_policy(struct rtw89_dev *rtwdev, 865 struct rtw89_mcc_role *mcc_role) 866 { 867 struct rtw89_mcc_policy *policy = &mcc_role->policy; 868 869 policy->c2h_rpt = RTW89_FW_MCC_C2H_RPT_ALL; 870 policy->tx_null_early = RTW89_MCC_DFLT_TX_NULL_EARLY; 871 policy->in_curr_ch = false; 872 policy->dis_sw_retry = true; 873 policy->sw_retry_count = false; 874 875 if (mcc_role->is_go) 876 policy->dis_tx_null = true; 877 else 878 policy->dis_tx_null = false; 879 } 880 881 static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev, 882 struct rtw89_mcc_role *mcc_role) 883 { 884 struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link; 885 struct ieee80211_p2p_noa_desc *noa_desc; 886 struct ieee80211_bss_conf *bss_conf; 887 u32 bcn_intvl_us = ieee80211_tu_to_usec(mcc_role->beacon_interval); 888 u32 max_toa_us, max_tob_us, max_dur_us; 889 u32 start_time, interval, duration; 890 u64 tsf, tsf_lmt; 891 int ret; 892 int i; 893 894 if (!mcc_role->is_gc) 895 return; 896 897 rtw89_p2p_noa_once_recalc(rtwvif_link); 898 899 rcu_read_lock(); 900 901 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); 902 903 /* find the first periodic NoA */ 904 for (i = 0; i < RTW89_P2P_MAX_NOA_NUM; i++) { 905 noa_desc = &bss_conf->p2p_noa_attr.desc[i]; 906 if (noa_desc->count == 255) 907 goto fill; 908 } 909 910 rcu_read_unlock(); 911 return; 912 913 fill: 914 start_time = le32_to_cpu(noa_desc->start_time); 915 interval = le32_to_cpu(noa_desc->interval); 916 duration = le32_to_cpu(noa_desc->duration); 917 918 rcu_read_unlock(); 919 920 if (interval != bcn_intvl_us) { 921 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 922 "MCC role limit: mismatch interval: %d vs. %d\n", 923 interval, bcn_intvl_us); 924 return; 925 } 926 927 ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf); 928 if (ret) { 929 rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret); 930 return; 931 } 932 933 tsf_lmt = (tsf & GENMASK_ULL(63, 32)) | start_time; 934 if (tsf_lmt < tsf) 935 tsf_lmt += roundup_u64(tsf - tsf_lmt, interval); 936 937 max_toa_us = rtw89_mcc_get_tbtt_ofst(rtwdev, mcc_role, tsf_lmt); 938 max_dur_us = interval - duration; 939 max_tob_us = max_dur_us - max_toa_us; 940 941 if (!max_toa_us || !max_tob_us) { 942 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 943 "MCC role limit: hit boundary\n"); 944 return; 945 } 946 947 if (max_dur_us < max_toa_us) { 948 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 949 "MCC role limit: insufficient duration\n"); 950 return; 951 } 952 953 mcc_role->limit.max_toa = max_toa_us / 1024; 954 mcc_role->limit.max_tob = max_tob_us / 1024; 955 mcc_role->limit.max_dur = mcc_role->limit.max_toa + mcc_role->limit.max_tob; 956 mcc_role->limit.enable = true; 957 958 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 959 "MCC role limit: max_toa %d, max_tob %d, max_dur %d\n", 960 mcc_role->limit.max_toa, mcc_role->limit.max_tob, 961 mcc_role->limit.max_dur); 962 } 963 964 static int rtw89_mcc_fill_role(struct rtw89_dev *rtwdev, 965 struct rtw89_vif_link *rtwvif_link, 966 struct rtw89_mcc_role *role) 967 { 968 struct ieee80211_bss_conf *bss_conf; 969 const struct rtw89_chan *chan; 970 971 memset(role, 0, sizeof(*role)); 972 role->rtwvif_link = rtwvif_link; 973 974 rcu_read_lock(); 975 976 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); 977 role->beacon_interval = bss_conf->beacon_int; 978 979 rcu_read_unlock(); 980 981 if (!role->beacon_interval) { 982 rtw89_warn(rtwdev, 983 "cannot handle MCC role without beacon interval\n"); 984 return -EINVAL; 985 } 986 987 role->duration = role->beacon_interval / 2; 988 989 chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx); 990 role->is_2ghz = chan->band_type == RTW89_BAND_2G; 991 role->is_go = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_GO; 992 role->is_gc = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT; 993 994 rtw89_mcc_fill_role_macid_bitmap(rtwdev, role); 995 rtw89_mcc_fill_role_policy(rtwdev, role); 996 rtw89_mcc_fill_role_limit(rtwdev, role); 997 998 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 999 "MCC role: bcn_intvl %d, is_2ghz %d, is_go %d, is_gc %d\n", 1000 role->beacon_interval, role->is_2ghz, role->is_go, role->is_gc); 1001 return 0; 1002 } 1003 1004 static void rtw89_mcc_fill_bt_role(struct rtw89_dev *rtwdev) 1005 { 1006 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1007 struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role; 1008 1009 memset(bt_role, 0, sizeof(*bt_role)); 1010 bt_role->duration = rtw89_coex_query_bt_req_len(rtwdev, RTW89_PHY_0); 1011 1012 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC bt role: dur %d\n", 1013 bt_role->duration); 1014 } 1015 1016 struct rtw89_mcc_fill_role_selector { 1017 struct rtw89_vif_link *bind_vif[NUM_OF_RTW89_CHANCTX]; 1018 }; 1019 1020 static_assert((u8)NUM_OF_RTW89_CHANCTX >= NUM_OF_RTW89_MCC_ROLES); 1021 static_assert(RTW89_MAX_INTERFACE_NUM >= NUM_OF_RTW89_MCC_ROLES); 1022 1023 static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev, 1024 struct rtw89_mcc_role *mcc_role, 1025 unsigned int ordered_idx, 1026 void *data) 1027 { 1028 struct rtw89_mcc_fill_role_selector *sel = data; 1029 struct rtw89_vif_link *role_vif = sel->bind_vif[ordered_idx]; 1030 int ret; 1031 1032 if (!role_vif) { 1033 rtw89_warn(rtwdev, "cannot handle MCC without role[%d]\n", 1034 ordered_idx); 1035 return -EINVAL; 1036 } 1037 1038 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1039 "MCC fill role[%d] with vif <macid %d>\n", 1040 ordered_idx, role_vif->mac_id); 1041 1042 ret = rtw89_mcc_fill_role(rtwdev, role_vif, mcc_role); 1043 if (ret) 1044 return ret; 1045 1046 return 0; 1047 } 1048 1049 static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev) 1050 { 1051 struct rtw89_hal *hal = &rtwdev->hal; 1052 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt; 1053 struct rtw89_mcc_fill_role_selector sel = {}; 1054 struct rtw89_vif_link *rtwvif_link; 1055 struct rtw89_vif *rtwvif; 1056 int ret; 1057 int i; 1058 1059 for (i = 0; i < NUM_OF_RTW89_MCC_ROLES; i++) { 1060 rtwvif = mgnt->active_roles[i]; 1061 if (!rtwvif) 1062 break; 1063 1064 rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0); 1065 if (unlikely(!rtwvif_link)) { 1066 rtw89_err(rtwdev, "mcc fill roles: find no link on HW-0\n"); 1067 continue; 1068 } 1069 1070 sel.bind_vif[i] = rtwvif_link; 1071 rtw89_p2p_disable_all_noa(rtwdev, rtwvif_link, NULL); 1072 } 1073 1074 ret = rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_fill_role_iterator, &sel); 1075 if (ret) 1076 return ret; 1077 1078 rtw89_mcc_fill_bt_role(rtwdev); 1079 return 0; 1080 } 1081 1082 static bool rtw89_mcc_can_courtesy(const struct rtw89_mcc_role *provider, 1083 const struct rtw89_mcc_role *receiver) 1084 { 1085 if (provider->is_go || receiver->is_gc) 1086 return false; 1087 1088 return true; 1089 } 1090 1091 static void rtw89_mcc_assign_pattern(struct rtw89_dev *rtwdev, 1092 const struct rtw89_mcc_pattern *new) 1093 { 1094 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1095 struct rtw89_mcc_role *ref = &mcc->role_ref; 1096 struct rtw89_mcc_role *aux = &mcc->role_aux; 1097 struct rtw89_mcc_config *config = &mcc->config; 1098 struct rtw89_mcc_pattern *pattern = &config->pattern; 1099 struct rtw89_mcc_courtesy_cfg *crtz; 1100 1101 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1102 "MCC assign pattern: ref {%d | %d}, aux {%d | %d}\n", 1103 new->tob_ref, new->toa_ref, new->tob_aux, new->toa_aux); 1104 1105 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC pattern plan: %d\n", new->plan); 1106 1107 *pattern = *new; 1108 memset(&pattern->courtesy, 0, sizeof(pattern->courtesy)); 1109 1110 if (RTW89_MCC_REQ_COURTESY(pattern, aux) && aux->is_gc) 1111 aux->ignore_bcn = true; 1112 else 1113 aux->ignore_bcn = false; 1114 1115 if (RTW89_MCC_REQ_COURTESY(pattern, aux) && rtw89_mcc_can_courtesy(ref, aux)) { 1116 crtz = &pattern->courtesy.ref; 1117 ref->crtz = crtz; 1118 1119 crtz->macid_tgt = aux->rtwvif_link->mac_id; 1120 crtz->slot_num = RTW89_MCC_DFLT_COURTESY_SLOT; 1121 1122 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1123 "MCC courtesy ref: tgt %d, slot %d\n", 1124 crtz->macid_tgt, crtz->slot_num); 1125 } else { 1126 ref->crtz = NULL; 1127 } 1128 1129 if (RTW89_MCC_REQ_COURTESY(pattern, ref) && ref->is_gc) 1130 ref->ignore_bcn = true; 1131 else 1132 ref->ignore_bcn = false; 1133 1134 if (RTW89_MCC_REQ_COURTESY(pattern, ref) && rtw89_mcc_can_courtesy(aux, ref)) { 1135 crtz = &pattern->courtesy.aux; 1136 aux->crtz = crtz; 1137 1138 crtz->macid_tgt = ref->rtwvif_link->mac_id; 1139 crtz->slot_num = RTW89_MCC_DFLT_COURTESY_SLOT; 1140 1141 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1142 "MCC courtesy aux: tgt %d, slot %d\n", 1143 crtz->macid_tgt, crtz->slot_num); 1144 } else { 1145 aux->crtz = NULL; 1146 } 1147 } 1148 1149 /* The follow-up roughly shows the relationship between the parameters 1150 * for pattern calculation. 1151 * 1152 * |< duration ref >| (if mid bt) |< duration aux >| 1153 * |< tob ref >|< toa ref >| ... |< tob aux >|< toa aux >| 1154 * V V 1155 * tbtt ref tbtt aux 1156 * |< beacon offset >| 1157 * 1158 * In loose pattern calculation, we only ensure at least tob_ref and 1159 * toa_ref have positive results. If tob_aux or toa_aux is negative 1160 * unfortunately, FW will be notified to handle it with courtesy 1161 * mechanism. 1162 */ 1163 static void __rtw89_mcc_calc_pattern_loose(struct rtw89_dev *rtwdev, 1164 struct rtw89_mcc_pattern *ptrn, 1165 bool hdl_bt) 1166 { 1167 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1168 struct rtw89_mcc_role *ref = &mcc->role_ref; 1169 struct rtw89_mcc_role *aux = &mcc->role_aux; 1170 struct rtw89_mcc_config *config = &mcc->config; 1171 u16 mcc_intvl = config->mcc_interval; 1172 u16 bcn_ofst = config->beacon_offset; 1173 u16 bt_dur_in_mid = 0; 1174 u16 max_bcn_ofst; 1175 s16 upper, lower; 1176 u16 res; 1177 1178 *ptrn = (typeof(*ptrn)){ 1179 .plan = hdl_bt ? RTW89_MCC_PLAN_TAIL_BT : RTW89_MCC_PLAN_NO_BT, 1180 }; 1181 1182 if (!hdl_bt) 1183 goto calc; 1184 1185 max_bcn_ofst = ref->duration + aux->duration; 1186 if (ref->limit.enable) 1187 max_bcn_ofst = min_t(u16, max_bcn_ofst, 1188 ref->limit.max_toa + aux->duration); 1189 else if (aux->limit.enable) 1190 max_bcn_ofst = min_t(u16, max_bcn_ofst, 1191 ref->duration + aux->limit.max_tob); 1192 1193 if (bcn_ofst > max_bcn_ofst && bcn_ofst >= mcc->bt_role.duration) { 1194 bt_dur_in_mid = mcc->bt_role.duration; 1195 ptrn->plan = RTW89_MCC_PLAN_MID_BT; 1196 } 1197 1198 calc: 1199 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1200 "MCC calc ptrn_ls: plan %d, bcn_ofst %d\n", 1201 ptrn->plan, bcn_ofst); 1202 1203 res = bcn_ofst - bt_dur_in_mid; 1204 upper = min_t(s16, ref->duration, res); 1205 lower = max_t(s16, 0, ref->duration - (mcc_intvl - bcn_ofst)); 1206 1207 if (ref->limit.enable) { 1208 upper = min_t(s16, upper, ref->limit.max_toa); 1209 lower = max_t(s16, lower, ref->duration - ref->limit.max_tob); 1210 } else if (aux->limit.enable) { 1211 upper = min_t(s16, upper, 1212 res - (aux->duration - aux->limit.max_toa)); 1213 lower = max_t(s16, lower, res - aux->limit.max_tob); 1214 } 1215 1216 if (lower < upper) 1217 ptrn->toa_ref = (upper + lower) / 2; 1218 else 1219 ptrn->toa_ref = lower; 1220 1221 ptrn->tob_ref = ref->duration - ptrn->toa_ref; 1222 ptrn->tob_aux = res - ptrn->toa_ref; 1223 ptrn->toa_aux = aux->duration - ptrn->tob_aux; 1224 } 1225 1226 /* In strict pattern calculation, we consider timing that might need 1227 * for HW stuffs, i.e. min_tob and min_toa. 1228 */ 1229 static int __rtw89_mcc_calc_pattern_strict(struct rtw89_dev *rtwdev, 1230 struct rtw89_mcc_pattern *ptrn) 1231 { 1232 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1233 struct rtw89_mcc_role *ref = &mcc->role_ref; 1234 struct rtw89_mcc_role *aux = &mcc->role_aux; 1235 struct rtw89_mcc_config *config = &mcc->config; 1236 u16 min_tob = RTW89_MCC_EARLY_RX_BCN_TIME + RTW89_MCC_SWITCH_CH_TIME; 1237 u16 min_toa = RTW89_MCC_MIN_RX_BCN_TIME; 1238 u16 bcn_ofst = config->beacon_offset; 1239 s16 upper_toa_ref, lower_toa_ref; 1240 s16 upper_tob_aux, lower_tob_aux; 1241 u16 bt_dur_in_mid; 1242 s16 res; 1243 1244 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1245 "MCC calc ptrn_st: plan %d, bcn_ofst %d\n", 1246 ptrn->plan, bcn_ofst); 1247 1248 if (ptrn->plan == RTW89_MCC_PLAN_MID_BT) 1249 bt_dur_in_mid = mcc->bt_role.duration; 1250 else 1251 bt_dur_in_mid = 0; 1252 1253 if (ref->duration < min_tob + min_toa) { 1254 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1255 "MCC calc ptrn_st: not meet ref dur cond\n"); 1256 return -EINVAL; 1257 } 1258 1259 if (aux->duration < min_tob + min_toa) { 1260 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1261 "MCC calc ptrn_st: not meet aux dur cond\n"); 1262 return -EINVAL; 1263 } 1264 1265 res = bcn_ofst - min_toa - min_tob - bt_dur_in_mid; 1266 if (res < 0) { 1267 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1268 "MCC calc ptrn_st: not meet bcn_ofst cond\n"); 1269 return -EINVAL; 1270 } 1271 1272 upper_toa_ref = min_t(s16, min_toa + res, ref->duration - min_tob); 1273 lower_toa_ref = min_toa; 1274 upper_tob_aux = min_t(s16, min_tob + res, aux->duration - min_toa); 1275 lower_tob_aux = min_tob; 1276 1277 if (ref->limit.enable) { 1278 if (min_tob > ref->limit.max_tob || min_toa > ref->limit.max_toa) { 1279 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1280 "MCC calc ptrn_st: conflict ref limit\n"); 1281 return -EINVAL; 1282 } 1283 1284 upper_toa_ref = min_t(s16, upper_toa_ref, ref->limit.max_toa); 1285 lower_toa_ref = max_t(s16, lower_toa_ref, 1286 ref->duration - ref->limit.max_tob); 1287 } else if (aux->limit.enable) { 1288 if (min_tob > aux->limit.max_tob || min_toa > aux->limit.max_toa) { 1289 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1290 "MCC calc ptrn_st: conflict aux limit\n"); 1291 return -EINVAL; 1292 } 1293 1294 upper_tob_aux = min_t(s16, upper_tob_aux, aux->limit.max_tob); 1295 lower_tob_aux = max_t(s16, lower_tob_aux, 1296 aux->duration - aux->limit.max_toa); 1297 } 1298 1299 upper_toa_ref = min_t(s16, upper_toa_ref, 1300 bcn_ofst - bt_dur_in_mid - lower_tob_aux); 1301 lower_toa_ref = max_t(s16, lower_toa_ref, 1302 bcn_ofst - bt_dur_in_mid - upper_tob_aux); 1303 if (lower_toa_ref > upper_toa_ref) { 1304 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1305 "MCC calc ptrn_st: conflict boundary\n"); 1306 return -EINVAL; 1307 } 1308 1309 ptrn->toa_ref = (upper_toa_ref + lower_toa_ref) / 2; 1310 ptrn->tob_ref = ref->duration - ptrn->toa_ref; 1311 ptrn->tob_aux = bcn_ofst - ptrn->toa_ref - bt_dur_in_mid; 1312 ptrn->toa_aux = aux->duration - ptrn->tob_aux; 1313 return 0; 1314 } 1315 1316 static void __rtw89_mcc_fill_ptrn_anchor_ref(struct rtw89_dev *rtwdev, 1317 struct rtw89_mcc_pattern *ptrn, 1318 bool small_bcn_ofst) 1319 { 1320 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1321 struct rtw89_mcc_role *ref = &mcc->role_ref; 1322 struct rtw89_mcc_role *aux = &mcc->role_aux; 1323 struct rtw89_mcc_config *config = &mcc->config; 1324 u16 bcn_ofst = config->beacon_offset; 1325 u16 ref_tob; 1326 u16 ref_toa; 1327 1328 if (ref->limit.enable) { 1329 ref_tob = ref->limit.max_tob; 1330 ref_toa = ref->limit.max_toa; 1331 } else { 1332 ref_tob = ref->duration / 2; 1333 ref_toa = ref->duration / 2; 1334 } 1335 1336 if (small_bcn_ofst) { 1337 ptrn->toa_ref = ref_toa; 1338 ptrn->tob_ref = ref->duration - ptrn->toa_ref; 1339 } else { 1340 ptrn->tob_ref = ref_tob; 1341 ptrn->toa_ref = ref->duration - ptrn->tob_ref; 1342 } 1343 1344 ptrn->tob_aux = bcn_ofst - ptrn->toa_ref; 1345 ptrn->toa_aux = aux->duration - ptrn->tob_aux; 1346 } 1347 1348 static void __rtw89_mcc_fill_ptrn_anchor_aux(struct rtw89_dev *rtwdev, 1349 struct rtw89_mcc_pattern *ptrn, 1350 bool small_bcn_ofst) 1351 { 1352 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1353 struct rtw89_mcc_role *ref = &mcc->role_ref; 1354 struct rtw89_mcc_role *aux = &mcc->role_aux; 1355 struct rtw89_mcc_config *config = &mcc->config; 1356 u16 bcn_ofst = config->beacon_offset; 1357 u16 aux_tob; 1358 u16 aux_toa; 1359 1360 if (aux->limit.enable) { 1361 aux_tob = aux->limit.max_tob; 1362 aux_toa = aux->limit.max_toa; 1363 } else { 1364 aux_tob = aux->duration / 2; 1365 aux_toa = aux->duration / 2; 1366 } 1367 1368 if (small_bcn_ofst) { 1369 ptrn->tob_aux = aux_tob; 1370 ptrn->toa_aux = aux->duration - ptrn->tob_aux; 1371 } else { 1372 ptrn->toa_aux = aux_toa; 1373 ptrn->tob_aux = aux->duration - ptrn->toa_aux; 1374 } 1375 1376 ptrn->toa_ref = bcn_ofst - ptrn->tob_aux; 1377 ptrn->tob_ref = ref->duration - ptrn->toa_ref; 1378 } 1379 1380 static int __rtw89_mcc_calc_pattern_anchor(struct rtw89_dev *rtwdev, 1381 struct rtw89_mcc_pattern *ptrn, 1382 bool hdl_bt) 1383 { 1384 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1385 struct rtw89_mcc_role *ref = &mcc->role_ref; 1386 struct rtw89_mcc_role *aux = &mcc->role_aux; 1387 struct rtw89_mcc_config *config = &mcc->config; 1388 u16 mcc_intvl = config->mcc_interval; 1389 u16 bcn_ofst = config->beacon_offset; 1390 bool small_bcn_ofst; 1391 1392 if (bcn_ofst < RTW89_MCC_MIN_RX_BCN_WITH_SWITCH_CH_TIME) 1393 small_bcn_ofst = true; 1394 else if (bcn_ofst < aux->duration - aux->limit.max_toa) 1395 small_bcn_ofst = true; 1396 else if (mcc_intvl - bcn_ofst < RTW89_MCC_MIN_RX_BCN_WITH_SWITCH_CH_TIME) 1397 small_bcn_ofst = false; 1398 else 1399 return -EPERM; 1400 1401 *ptrn = (typeof(*ptrn)){ 1402 .plan = hdl_bt ? RTW89_MCC_PLAN_TAIL_BT : RTW89_MCC_PLAN_NO_BT, 1403 }; 1404 1405 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1406 "MCC calc ptrn_ac: plan %d, bcn_ofst %d\n", 1407 ptrn->plan, bcn_ofst); 1408 1409 if (ref->is_go || ref->is_gc) 1410 __rtw89_mcc_fill_ptrn_anchor_ref(rtwdev, ptrn, small_bcn_ofst); 1411 else if (aux->is_go || aux->is_gc) 1412 __rtw89_mcc_fill_ptrn_anchor_aux(rtwdev, ptrn, small_bcn_ofst); 1413 else 1414 __rtw89_mcc_fill_ptrn_anchor_ref(rtwdev, ptrn, small_bcn_ofst); 1415 1416 return 0; 1417 } 1418 1419 static int rtw89_mcc_calc_pattern(struct rtw89_dev *rtwdev, bool hdl_bt) 1420 { 1421 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1422 struct rtw89_mcc_role *ref = &mcc->role_ref; 1423 struct rtw89_mcc_role *aux = &mcc->role_aux; 1424 bool sel_plan[NUM_OF_RTW89_MCC_PLAN] = {}; 1425 struct rtw89_mcc_pattern ptrn; 1426 int ret; 1427 int i; 1428 1429 if (ref->limit.enable && aux->limit.enable) { 1430 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1431 "MCC calc ptrn: not support dual limited roles\n"); 1432 return -EINVAL; 1433 } 1434 1435 if (ref->limit.enable && 1436 ref->duration > ref->limit.max_tob + ref->limit.max_toa) { 1437 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1438 "MCC calc ptrn: not fit ref limit\n"); 1439 return -EINVAL; 1440 } 1441 1442 if (aux->limit.enable && 1443 aux->duration > aux->limit.max_tob + aux->limit.max_toa) { 1444 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1445 "MCC calc ptrn: not fit aux limit\n"); 1446 return -EINVAL; 1447 } 1448 1449 if (hdl_bt) { 1450 sel_plan[RTW89_MCC_PLAN_TAIL_BT] = true; 1451 sel_plan[RTW89_MCC_PLAN_MID_BT] = true; 1452 } else { 1453 sel_plan[RTW89_MCC_PLAN_NO_BT] = true; 1454 } 1455 1456 for (i = 0; i < NUM_OF_RTW89_MCC_PLAN; i++) { 1457 if (!sel_plan[i]) 1458 continue; 1459 1460 ptrn = (typeof(ptrn)){ 1461 .plan = i, 1462 }; 1463 1464 ret = __rtw89_mcc_calc_pattern_strict(rtwdev, &ptrn); 1465 if (ret) 1466 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1467 "MCC calc ptrn_st with plan %d: fail\n", i); 1468 else 1469 goto done; 1470 } 1471 1472 ret = __rtw89_mcc_calc_pattern_anchor(rtwdev, &ptrn, hdl_bt); 1473 if (!ret) 1474 goto done; 1475 1476 __rtw89_mcc_calc_pattern_loose(rtwdev, &ptrn, hdl_bt); 1477 1478 done: 1479 rtw89_mcc_assign_pattern(rtwdev, &ptrn); 1480 return 0; 1481 } 1482 1483 static void rtw89_mcc_set_default_pattern(struct rtw89_dev *rtwdev) 1484 { 1485 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1486 struct rtw89_mcc_role *ref = &mcc->role_ref; 1487 struct rtw89_mcc_role *aux = &mcc->role_aux; 1488 struct rtw89_mcc_pattern tmp = {}; 1489 1490 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1491 "MCC use default pattern unexpectedly\n"); 1492 1493 tmp.plan = RTW89_MCC_PLAN_NO_BT; 1494 tmp.tob_ref = ref->duration / 2; 1495 tmp.toa_ref = ref->duration - tmp.tob_ref; 1496 tmp.tob_aux = aux->duration / 2; 1497 tmp.toa_aux = aux->duration - tmp.tob_aux; 1498 1499 rtw89_mcc_assign_pattern(rtwdev, &tmp); 1500 } 1501 1502 static void rtw89_mcc_set_duration_go_sta(struct rtw89_dev *rtwdev, 1503 struct rtw89_mcc_role *role_go, 1504 struct rtw89_mcc_role *role_sta) 1505 { 1506 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1507 struct rtw89_mcc_config *config = &mcc->config; 1508 u16 mcc_intvl = config->mcc_interval; 1509 u16 dur_go, dur_sta; 1510 1511 dur_go = clamp_t(u16, role_go->duration, RTW89_MCC_MIN_GO_DURATION, 1512 mcc_intvl - RTW89_MCC_MIN_STA_DURATION); 1513 if (role_go->limit.enable) 1514 dur_go = min(dur_go, role_go->limit.max_dur); 1515 dur_sta = mcc_intvl - dur_go; 1516 1517 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1518 "MCC set dur: (go, sta) {%d, %d} -> {%d, %d}\n", 1519 role_go->duration, role_sta->duration, dur_go, dur_sta); 1520 1521 role_go->duration = dur_go; 1522 role_sta->duration = dur_sta; 1523 } 1524 1525 static void rtw89_mcc_set_duration_gc_sta(struct rtw89_dev *rtwdev) 1526 { 1527 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1528 struct rtw89_mcc_role *ref = &mcc->role_ref; 1529 struct rtw89_mcc_role *aux = &mcc->role_aux; 1530 struct rtw89_mcc_config *config = &mcc->config; 1531 u16 mcc_intvl = config->mcc_interval; 1532 u16 dur_ref, dur_aux; 1533 1534 if (ref->duration < RTW89_MCC_MIN_STA_DURATION) { 1535 dur_ref = RTW89_MCC_MIN_STA_DURATION; 1536 dur_aux = mcc_intvl - dur_ref; 1537 } else if (aux->duration < RTW89_MCC_MIN_STA_DURATION) { 1538 dur_aux = RTW89_MCC_MIN_STA_DURATION; 1539 dur_ref = mcc_intvl - dur_aux; 1540 } else { 1541 dur_ref = ref->duration; 1542 dur_aux = mcc_intvl - dur_ref; 1543 } 1544 1545 if (ref->limit.enable) { 1546 dur_ref = min(dur_ref, ref->limit.max_dur); 1547 dur_aux = mcc_intvl - dur_ref; 1548 } else if (aux->limit.enable) { 1549 dur_aux = min(dur_aux, aux->limit.max_dur); 1550 dur_ref = mcc_intvl - dur_aux; 1551 } 1552 1553 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1554 "MCC set dur: (ref, aux) {%d ~ %d} -> {%d ~ %d}\n", 1555 ref->duration, aux->duration, dur_ref, dur_aux); 1556 1557 ref->duration = dur_ref; 1558 aux->duration = dur_aux; 1559 } 1560 1561 struct rtw89_mcc_mod_dur_data { 1562 u16 available; 1563 struct { 1564 u16 dur; 1565 u16 room; 1566 } parm[NUM_OF_RTW89_MCC_ROLES]; 1567 }; 1568 1569 static int rtw89_mcc_mod_dur_get_iterator(struct rtw89_dev *rtwdev, 1570 struct rtw89_mcc_role *mcc_role, 1571 unsigned int ordered_idx, 1572 void *data) 1573 { 1574 struct rtw89_mcc_mod_dur_data *p = data; 1575 u16 min; 1576 1577 p->parm[ordered_idx].dur = mcc_role->duration; 1578 1579 if (mcc_role->is_go) 1580 min = RTW89_MCC_MIN_GO_DURATION; 1581 else 1582 min = RTW89_MCC_MIN_STA_DURATION; 1583 1584 p->parm[ordered_idx].room = max_t(s32, p->parm[ordered_idx].dur - min, 0); 1585 1586 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1587 "MCC mod dur: chk role[%u]: dur %u, min %u, room %u\n", 1588 ordered_idx, p->parm[ordered_idx].dur, min, 1589 p->parm[ordered_idx].room); 1590 1591 p->available += p->parm[ordered_idx].room; 1592 return 0; 1593 } 1594 1595 static int rtw89_mcc_mod_dur_put_iterator(struct rtw89_dev *rtwdev, 1596 struct rtw89_mcc_role *mcc_role, 1597 unsigned int ordered_idx, 1598 void *data) 1599 { 1600 struct rtw89_mcc_mod_dur_data *p = data; 1601 1602 mcc_role->duration = p->parm[ordered_idx].dur; 1603 1604 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1605 "MCC mod dur: set role[%u]: dur %u\n", 1606 ordered_idx, p->parm[ordered_idx].dur); 1607 return 0; 1608 } 1609 1610 static void rtw89_mcc_mod_duration_dual_2ghz_with_bt(struct rtw89_dev *rtwdev) 1611 { 1612 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1613 struct rtw89_mcc_config *config = &mcc->config; 1614 struct rtw89_mcc_mod_dur_data data = {}; 1615 u16 mcc_intvl = config->mcc_interval; 1616 u16 bt_dur = mcc->bt_role.duration; 1617 u16 wifi_dur; 1618 1619 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1620 "MCC mod dur (dual 2ghz): mcc_intvl %u, raw bt_dur %u\n", 1621 mcc_intvl, bt_dur); 1622 1623 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_mod_dur_get_iterator, &data); 1624 1625 bt_dur = clamp_t(u16, bt_dur, 1, data.available / 3); 1626 wifi_dur = mcc_intvl - bt_dur; 1627 1628 if (data.parm[0].room <= data.parm[1].room) { 1629 data.parm[0].dur -= min_t(u16, bt_dur / 2, data.parm[0].room); 1630 data.parm[1].dur = wifi_dur - data.parm[0].dur; 1631 } else { 1632 data.parm[1].dur -= min_t(u16, bt_dur / 2, data.parm[1].room); 1633 data.parm[0].dur = wifi_dur - data.parm[1].dur; 1634 } 1635 1636 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_mod_dur_put_iterator, &data); 1637 1638 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC mod dur: set bt: dur %u\n", bt_dur); 1639 mcc->bt_role.duration = bt_dur; 1640 } 1641 1642 static 1643 void rtw89_mcc_mod_duration_diff_band_with_bt(struct rtw89_dev *rtwdev, 1644 struct rtw89_mcc_role *role_2ghz, 1645 struct rtw89_mcc_role *role_non_2ghz) 1646 { 1647 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1648 struct rtw89_mcc_config *config = &mcc->config; 1649 u16 dur_2ghz, dur_non_2ghz; 1650 u16 bt_dur, mcc_intvl; 1651 1652 dur_2ghz = role_2ghz->duration; 1653 dur_non_2ghz = role_non_2ghz->duration; 1654 mcc_intvl = config->mcc_interval; 1655 bt_dur = mcc->bt_role.duration; 1656 1657 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1658 "MCC mod dur (diff band): mcc_intvl %u, bt_dur %u\n", 1659 mcc_intvl, bt_dur); 1660 1661 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1662 "MCC mod dur: check dur_2ghz %u, dur_non_2ghz %u\n", 1663 dur_2ghz, dur_non_2ghz); 1664 1665 if (dur_non_2ghz >= bt_dur) { 1666 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1667 "MCC mod dur: dur_non_2ghz is enough for bt\n"); 1668 return; 1669 } 1670 1671 dur_non_2ghz = bt_dur; 1672 dur_2ghz = mcc_intvl - dur_non_2ghz; 1673 1674 if (role_non_2ghz->limit.enable) { 1675 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1676 "MCC mod dur: dur_non_2ghz is limited with max %u\n", 1677 role_non_2ghz->limit.max_dur); 1678 1679 dur_non_2ghz = min(dur_non_2ghz, role_non_2ghz->limit.max_dur); 1680 dur_2ghz = mcc_intvl - dur_non_2ghz; 1681 } 1682 1683 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1684 "MCC mod dur: set dur_2ghz %u, dur_non_2ghz %u\n", 1685 dur_2ghz, dur_non_2ghz); 1686 1687 role_2ghz->duration = dur_2ghz; 1688 role_non_2ghz->duration = dur_non_2ghz; 1689 } 1690 1691 static bool rtw89_mcc_duration_decision_on_bt(struct rtw89_dev *rtwdev) 1692 { 1693 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1694 struct rtw89_mcc_role *ref = &mcc->role_ref; 1695 struct rtw89_mcc_role *aux = &mcc->role_aux; 1696 struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role; 1697 1698 if (!bt_role->duration) 1699 return false; 1700 1701 if (ref->is_2ghz && aux->is_2ghz) { 1702 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1703 "MCC dual roles are on 2GHz; consider BT duration\n"); 1704 1705 rtw89_mcc_mod_duration_dual_2ghz_with_bt(rtwdev); 1706 return true; 1707 } 1708 1709 if (!ref->is_2ghz && !aux->is_2ghz) { 1710 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1711 "MCC dual roles are not on 2GHz; ignore BT duration\n"); 1712 return false; 1713 } 1714 1715 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1716 "MCC one role is on 2GHz; modify another for BT duration\n"); 1717 1718 if (ref->is_2ghz) 1719 rtw89_mcc_mod_duration_diff_band_with_bt(rtwdev, ref, aux); 1720 else 1721 rtw89_mcc_mod_duration_diff_band_with_bt(rtwdev, aux, ref); 1722 1723 return false; 1724 } 1725 1726 void rtw89_mcc_prepare_done_work(struct wiphy *wiphy, struct wiphy_work *work) 1727 { 1728 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 1729 mcc_prepare_done_work.work); 1730 1731 lockdep_assert_wiphy(wiphy); 1732 1733 ieee80211_wake_queues(rtwdev->hw); 1734 } 1735 1736 static void rtw89_mcc_prepare(struct rtw89_dev *rtwdev, bool start) 1737 { 1738 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1739 struct rtw89_mcc_config *config = &mcc->config; 1740 1741 if (start) { 1742 ieee80211_stop_queues(rtwdev->hw); 1743 1744 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 1745 &rtwdev->mcc_prepare_done_work, 1746 usecs_to_jiffies(config->prepare_delay)); 1747 } else { 1748 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 1749 &rtwdev->mcc_prepare_done_work, 0); 1750 wiphy_delayed_work_flush(rtwdev->hw->wiphy, 1751 &rtwdev->mcc_prepare_done_work); 1752 } 1753 } 1754 1755 static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev) 1756 { 1757 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1758 struct rtw89_mcc_role *ref = &mcc->role_ref; 1759 struct rtw89_mcc_role *aux = &mcc->role_aux; 1760 struct rtw89_mcc_config *config = &mcc->config; 1761 u32 bcn_intvl_ref_us = ieee80211_tu_to_usec(ref->beacon_interval); 1762 s32 tob_ref_us = ieee80211_tu_to_usec(config->pattern.tob_ref); 1763 u64 tsf, start_tsf; 1764 u32 cur_tbtt_ofst; 1765 u64 min_time; 1766 u64 tsf_aux; 1767 int ret; 1768 1769 if (rtw89_concurrent_via_mrc(rtwdev)) 1770 ret = __mrc_fw_req_tsf(rtwdev, &tsf, &tsf_aux); 1771 else 1772 ret = __mcc_fw_req_tsf(rtwdev, &tsf, &tsf_aux); 1773 1774 if (ret) 1775 return ret; 1776 1777 min_time = tsf; 1778 if (ref->is_go || aux->is_go) 1779 min_time += ieee80211_tu_to_usec(RTW89_MCC_SHORT_TRIGGER_TIME); 1780 else 1781 min_time += ieee80211_tu_to_usec(RTW89_MCC_LONG_TRIGGER_TIME); 1782 1783 cur_tbtt_ofst = rtw89_mcc_get_tbtt_ofst(rtwdev, ref, tsf); 1784 start_tsf = tsf - cur_tbtt_ofst + bcn_intvl_ref_us - tob_ref_us; 1785 if (start_tsf < min_time) 1786 start_tsf += roundup_u64(min_time - start_tsf, bcn_intvl_ref_us); 1787 1788 config->start_tsf = start_tsf; 1789 config->start_tsf_in_aux_domain = tsf_aux + start_tsf - tsf; 1790 config->prepare_delay = start_tsf - tsf; 1791 1792 return 0; 1793 } 1794 1795 static int rtw89_mcc_fill_config(struct rtw89_dev *rtwdev) 1796 { 1797 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1798 struct rtw89_mcc_role *ref = &mcc->role_ref; 1799 struct rtw89_mcc_role *aux = &mcc->role_aux; 1800 struct rtw89_mcc_config *config = &mcc->config; 1801 bool hdl_bt; 1802 int ret; 1803 1804 memset(config, 0, sizeof(*config)); 1805 1806 switch (mcc->mode) { 1807 case RTW89_MCC_MODE_GO_STA: 1808 config->beacon_offset = rtw89_mcc_get_bcn_ofst(rtwdev); 1809 if (ref->is_go) { 1810 config->mcc_interval = ref->beacon_interval; 1811 rtw89_mcc_set_duration_go_sta(rtwdev, ref, aux); 1812 } else { 1813 config->mcc_interval = aux->beacon_interval; 1814 rtw89_mcc_set_duration_go_sta(rtwdev, aux, ref); 1815 } 1816 break; 1817 case RTW89_MCC_MODE_GC_STA: 1818 config->beacon_offset = rtw89_mcc_get_bcn_ofst(rtwdev); 1819 config->mcc_interval = ref->beacon_interval; 1820 rtw89_mcc_set_duration_gc_sta(rtwdev); 1821 break; 1822 default: 1823 rtw89_warn(rtwdev, "MCC unknown mode: %d\n", mcc->mode); 1824 return -EFAULT; 1825 } 1826 1827 hdl_bt = rtw89_mcc_duration_decision_on_bt(rtwdev); 1828 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC handle bt: %d\n", hdl_bt); 1829 1830 ret = rtw89_mcc_calc_pattern(rtwdev, hdl_bt); 1831 if (!ret) 1832 goto bottom; 1833 1834 rtw89_mcc_set_default_pattern(rtwdev); 1835 1836 bottom: 1837 return rtw89_mcc_fill_start_tsf(rtwdev); 1838 } 1839 1840 static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role) 1841 { 1842 const struct rtw89_mcc_courtesy_cfg *crtz = role->crtz; 1843 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1844 struct rtw89_mcc_policy *policy = &role->policy; 1845 struct rtw89_fw_mcc_add_req req = {}; 1846 const struct rtw89_chan *chan; 1847 int ret; 1848 1849 chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx); 1850 req.central_ch_seg0 = chan->channel; 1851 req.primary_ch = chan->primary_channel; 1852 req.bandwidth = chan->band_width; 1853 req.ch_band_type = chan->band_type; 1854 1855 req.macid = role->rtwvif_link->mac_id; 1856 req.group = mcc->group; 1857 req.c2h_rpt = policy->c2h_rpt; 1858 req.tx_null_early = policy->tx_null_early; 1859 req.dis_tx_null = policy->dis_tx_null; 1860 req.in_curr_ch = policy->in_curr_ch; 1861 req.sw_retry_count = policy->sw_retry_count; 1862 req.dis_sw_retry = policy->dis_sw_retry; 1863 req.duration = role->duration; 1864 req.btc_in_2g = false; 1865 1866 if (crtz) { 1867 req.courtesy_target = crtz->macid_tgt; 1868 req.courtesy_num = crtz->slot_num; 1869 req.courtesy_en = true; 1870 } 1871 1872 ret = rtw89_fw_h2c_add_mcc(rtwdev, &req); 1873 if (ret) { 1874 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1875 "MCC h2c failed to add wifi role: %d\n", ret); 1876 return ret; 1877 } 1878 1879 ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group, 1880 role->rtwvif_link->mac_id, 1881 role->macid_bitmap); 1882 if (ret) { 1883 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1884 "MCC h2c failed to set macid bitmap: %d\n", ret); 1885 return ret; 1886 } 1887 1888 return 0; 1889 } 1890 1891 static 1892 void __mrc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role, 1893 struct rtw89_fw_mrc_add_arg *arg, u8 slot_idx) 1894 { 1895 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1896 struct rtw89_mcc_role *ref = &mcc->role_ref; 1897 struct rtw89_mcc_policy *policy = &role->policy; 1898 struct rtw89_fw_mrc_add_slot_arg *slot_arg; 1899 const struct rtw89_chan *chan; 1900 1901 slot_arg = &arg->slots[slot_idx]; 1902 role->slot_idx = slot_idx; 1903 1904 slot_arg->duration = role->duration; 1905 slot_arg->role_num = 1; 1906 1907 chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx); 1908 1909 slot_arg->roles[0].role_type = RTW89_H2C_MRC_ROLE_WIFI; 1910 slot_arg->roles[0].is_master = role == ref; 1911 slot_arg->roles[0].band = chan->band_type; 1912 slot_arg->roles[0].bw = chan->band_width; 1913 slot_arg->roles[0].central_ch = chan->channel; 1914 slot_arg->roles[0].primary_ch = chan->primary_channel; 1915 slot_arg->roles[0].en_tx_null = !policy->dis_tx_null; 1916 slot_arg->roles[0].null_early = policy->tx_null_early; 1917 slot_arg->roles[0].macid = role->rtwvif_link->mac_id; 1918 slot_arg->roles[0].macid_main_bitmap = 1919 rtw89_mcc_role_fw_macid_bitmap_to_u32(role); 1920 } 1921 1922 static int __mcc_fw_add_bt_role(struct rtw89_dev *rtwdev) 1923 { 1924 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1925 struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role; 1926 struct rtw89_fw_mcc_add_req req = {}; 1927 int ret; 1928 1929 req.group = mcc->group; 1930 req.duration = bt_role->duration; 1931 req.btc_in_2g = true; 1932 1933 ret = rtw89_fw_h2c_add_mcc(rtwdev, &req); 1934 if (ret) { 1935 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 1936 "MCC h2c failed to add bt role: %d\n", ret); 1937 return ret; 1938 } 1939 1940 return 0; 1941 } 1942 1943 static 1944 void __mrc_fw_add_bt_role(struct rtw89_dev *rtwdev, 1945 struct rtw89_fw_mrc_add_arg *arg, u8 slot_idx) 1946 { 1947 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1948 struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role; 1949 struct rtw89_fw_mrc_add_slot_arg *slot_arg = &arg->slots[slot_idx]; 1950 1951 slot_arg->duration = bt_role->duration; 1952 slot_arg->role_num = 1; 1953 1954 slot_arg->roles[0].role_type = RTW89_H2C_MRC_ROLE_BT; 1955 } 1956 1957 static int __mcc_fw_start(struct rtw89_dev *rtwdev, bool replace) 1958 { 1959 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 1960 struct rtw89_mcc_role *ref = &mcc->role_ref; 1961 struct rtw89_mcc_role *aux = &mcc->role_aux; 1962 struct rtw89_mcc_config *config = &mcc->config; 1963 struct rtw89_mcc_pattern *pattern = &config->pattern; 1964 struct rtw89_mcc_sync *sync = &config->sync; 1965 struct rtw89_fw_mcc_start_req req = {}; 1966 int ret; 1967 1968 if (replace) { 1969 req.old_group = mcc->group; 1970 req.old_group_action = RTW89_FW_MCC_OLD_GROUP_ACT_REPLACE; 1971 mcc->group = RTW89_MCC_NEXT_GROUP(mcc->group); 1972 } 1973 1974 req.group = mcc->group; 1975 1976 switch (pattern->plan) { 1977 case RTW89_MCC_PLAN_TAIL_BT: 1978 ret = __mcc_fw_add_role(rtwdev, ref); 1979 if (ret) 1980 return ret; 1981 ret = __mcc_fw_add_role(rtwdev, aux); 1982 if (ret) 1983 return ret; 1984 ret = __mcc_fw_add_bt_role(rtwdev); 1985 if (ret) 1986 return ret; 1987 1988 req.btc_in_group = true; 1989 break; 1990 case RTW89_MCC_PLAN_MID_BT: 1991 ret = __mcc_fw_add_role(rtwdev, ref); 1992 if (ret) 1993 return ret; 1994 ret = __mcc_fw_add_bt_role(rtwdev); 1995 if (ret) 1996 return ret; 1997 ret = __mcc_fw_add_role(rtwdev, aux); 1998 if (ret) 1999 return ret; 2000 2001 req.btc_in_group = true; 2002 break; 2003 case RTW89_MCC_PLAN_NO_BT: 2004 ret = __mcc_fw_add_role(rtwdev, ref); 2005 if (ret) 2006 return ret; 2007 ret = __mcc_fw_add_role(rtwdev, aux); 2008 if (ret) 2009 return ret; 2010 2011 req.btc_in_group = false; 2012 break; 2013 default: 2014 rtw89_warn(rtwdev, "MCC unknown plan: %d\n", pattern->plan); 2015 return -EFAULT; 2016 } 2017 2018 if (sync->enable) { 2019 ret = rtw89_fw_h2c_mcc_sync(rtwdev, req.group, sync->macid_src, 2020 sync->macid_tgt, sync->offset); 2021 if (ret) { 2022 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2023 "MCC h2c failed to trigger sync: %d\n", ret); 2024 return ret; 2025 } 2026 } 2027 2028 req.macid = ref->rtwvif_link->mac_id; 2029 req.tsf_high = config->start_tsf >> 32; 2030 req.tsf_low = config->start_tsf; 2031 2032 ret = rtw89_fw_h2c_start_mcc(rtwdev, &req); 2033 if (ret) { 2034 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2035 "MCC h2c failed to trigger start: %d\n", ret); 2036 return ret; 2037 } 2038 2039 return 0; 2040 } 2041 2042 static void __mrc_fw_add_courtesy(struct rtw89_dev *rtwdev, 2043 struct rtw89_fw_mrc_add_arg *arg) 2044 { 2045 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2046 struct rtw89_mcc_role *ref = &mcc->role_ref; 2047 struct rtw89_mcc_role *aux = &mcc->role_aux; 2048 struct rtw89_fw_mrc_add_slot_arg *slot_arg_src; 2049 2050 if (ref->crtz) { 2051 slot_arg_src = &arg->slots[ref->slot_idx]; 2052 2053 slot_arg_src->courtesy_target = aux->slot_idx; 2054 slot_arg_src->courtesy_period = ref->crtz->slot_num; 2055 slot_arg_src->courtesy_en = true; 2056 } 2057 2058 if (aux->crtz) { 2059 slot_arg_src = &arg->slots[aux->slot_idx]; 2060 2061 slot_arg_src->courtesy_target = ref->slot_idx; 2062 slot_arg_src->courtesy_period = aux->crtz->slot_num; 2063 slot_arg_src->courtesy_en = true; 2064 } 2065 } 2066 2067 static int __mrc_fw_start(struct rtw89_dev *rtwdev, bool replace) 2068 { 2069 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2070 struct rtw89_mcc_role *ref = &mcc->role_ref; 2071 struct rtw89_mcc_role *aux = &mcc->role_aux; 2072 struct rtw89_mcc_config *config = &mcc->config; 2073 struct rtw89_mcc_pattern *pattern = &config->pattern; 2074 struct rtw89_mcc_sync *sync = &config->sync; 2075 struct rtw89_fw_mrc_start_arg start_arg = {}; 2076 struct rtw89_fw_mrc_add_arg add_arg = {}; 2077 int ret; 2078 2079 BUILD_BUG_ON(RTW89_MAC_MRC_MAX_ADD_SLOT_NUM < 2080 NUM_OF_RTW89_MCC_ROLES + 1 /* bt role */); 2081 2082 if (replace) { 2083 start_arg.old_sch_idx = mcc->group; 2084 start_arg.action = RTW89_H2C_MRC_START_ACTION_REPLACE_OLD; 2085 mcc->group = RTW89_MCC_NEXT_GROUP(mcc->group); 2086 } 2087 2088 add_arg.sch_idx = mcc->group; 2089 add_arg.sch_type = RTW89_H2C_MRC_SCH_BAND0_ONLY; 2090 2091 switch (pattern->plan) { 2092 case RTW89_MCC_PLAN_TAIL_BT: 2093 __mrc_fw_add_role(rtwdev, ref, &add_arg, 0); 2094 __mrc_fw_add_role(rtwdev, aux, &add_arg, 1); 2095 __mrc_fw_add_bt_role(rtwdev, &add_arg, 2); 2096 2097 add_arg.slot_num = 3; 2098 add_arg.btc_in_sch = true; 2099 break; 2100 case RTW89_MCC_PLAN_MID_BT: 2101 __mrc_fw_add_role(rtwdev, ref, &add_arg, 0); 2102 __mrc_fw_add_bt_role(rtwdev, &add_arg, 1); 2103 __mrc_fw_add_role(rtwdev, aux, &add_arg, 2); 2104 2105 add_arg.slot_num = 3; 2106 add_arg.btc_in_sch = true; 2107 break; 2108 case RTW89_MCC_PLAN_NO_BT: 2109 __mrc_fw_add_role(rtwdev, ref, &add_arg, 0); 2110 __mrc_fw_add_role(rtwdev, aux, &add_arg, 1); 2111 2112 add_arg.slot_num = 2; 2113 add_arg.btc_in_sch = false; 2114 break; 2115 default: 2116 rtw89_warn(rtwdev, "MCC unknown plan: %d\n", pattern->plan); 2117 return -EFAULT; 2118 } 2119 2120 __mrc_fw_add_courtesy(rtwdev, &add_arg); 2121 2122 ret = rtw89_fw_h2c_mrc_add(rtwdev, &add_arg); 2123 if (ret) { 2124 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2125 "MRC h2c failed to trigger add: %d\n", ret); 2126 return ret; 2127 } 2128 2129 if (sync->enable) { 2130 struct rtw89_fw_mrc_sync_arg sync_arg = { 2131 .offset = sync->offset, 2132 .src = { 2133 .band = sync->band_src, 2134 .port = sync->port_src, 2135 }, 2136 .dest = { 2137 .band = sync->band_tgt, 2138 .port = sync->port_tgt, 2139 }, 2140 }; 2141 2142 ret = rtw89_fw_h2c_mrc_sync(rtwdev, &sync_arg); 2143 if (ret) { 2144 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2145 "MRC h2c failed to trigger sync: %d\n", ret); 2146 return ret; 2147 } 2148 } 2149 2150 start_arg.sch_idx = mcc->group; 2151 start_arg.start_tsf = config->start_tsf; 2152 2153 ret = rtw89_fw_h2c_mrc_start(rtwdev, &start_arg); 2154 if (ret) { 2155 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2156 "MRC h2c failed to trigger start: %d\n", ret); 2157 return ret; 2158 } 2159 2160 return 0; 2161 } 2162 2163 static int __mcc_fw_set_duration_no_bt(struct rtw89_dev *rtwdev, bool sync_changed) 2164 { 2165 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2166 struct rtw89_mcc_config *config = &mcc->config; 2167 struct rtw89_mcc_sync *sync = &config->sync; 2168 struct rtw89_mcc_role *ref = &mcc->role_ref; 2169 struct rtw89_mcc_role *aux = &mcc->role_aux; 2170 struct rtw89_fw_mcc_duration req = { 2171 .group = mcc->group, 2172 .btc_in_group = false, 2173 .start_macid = ref->rtwvif_link->mac_id, 2174 .macid_x = ref->rtwvif_link->mac_id, 2175 .macid_y = aux->rtwvif_link->mac_id, 2176 .duration_x = ref->duration, 2177 .duration_y = aux->duration, 2178 .start_tsf_high = config->start_tsf >> 32, 2179 .start_tsf_low = config->start_tsf, 2180 }; 2181 int ret; 2182 2183 ret = rtw89_fw_h2c_mcc_set_duration(rtwdev, &req); 2184 if (ret) { 2185 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2186 "MCC h2c failed to set duration: %d\n", ret); 2187 return ret; 2188 } 2189 2190 if (!sync->enable || !sync_changed) 2191 return 0; 2192 2193 ret = rtw89_fw_h2c_mcc_sync(rtwdev, mcc->group, sync->macid_src, 2194 sync->macid_tgt, sync->offset); 2195 if (ret) { 2196 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2197 "MCC h2c failed to trigger sync: %d\n", ret); 2198 return ret; 2199 } 2200 2201 return 0; 2202 } 2203 2204 static int __mrc_fw_set_duration_no_bt(struct rtw89_dev *rtwdev, bool sync_changed) 2205 { 2206 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2207 struct rtw89_mcc_config *config = &mcc->config; 2208 struct rtw89_mcc_sync *sync = &config->sync; 2209 struct rtw89_mcc_role *ref = &mcc->role_ref; 2210 struct rtw89_mcc_role *aux = &mcc->role_aux; 2211 struct rtw89_fw_mrc_upd_duration_arg dur_arg = { 2212 .sch_idx = mcc->group, 2213 .start_tsf = config->start_tsf, 2214 .slot_num = 2, 2215 .slots[0] = { 2216 .slot_idx = ref->slot_idx, 2217 .duration = ref->duration, 2218 }, 2219 .slots[1] = { 2220 .slot_idx = aux->slot_idx, 2221 .duration = aux->duration, 2222 }, 2223 }; 2224 struct rtw89_fw_mrc_sync_arg sync_arg = { 2225 .offset = sync->offset, 2226 .src = { 2227 .band = sync->band_src, 2228 .port = sync->port_src, 2229 }, 2230 .dest = { 2231 .band = sync->band_tgt, 2232 .port = sync->port_tgt, 2233 }, 2234 2235 }; 2236 int ret; 2237 2238 ret = rtw89_fw_h2c_mrc_upd_duration(rtwdev, &dur_arg); 2239 if (ret) { 2240 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2241 "MRC h2c failed to update duration: %d\n", ret); 2242 return ret; 2243 } 2244 2245 if (!sync->enable || !sync_changed) 2246 return 0; 2247 2248 ret = rtw89_fw_h2c_mrc_sync(rtwdev, &sync_arg); 2249 if (ret) { 2250 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2251 "MRC h2c failed to trigger sync: %d\n", ret); 2252 return ret; 2253 } 2254 2255 return 0; 2256 } 2257 2258 static void rtw89_mcc_handle_beacon_noa(struct rtw89_dev *rtwdev, bool enable) 2259 { 2260 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2261 struct rtw89_mcc_role *ref = &mcc->role_ref; 2262 struct rtw89_mcc_role *aux = &mcc->role_aux; 2263 struct rtw89_mcc_config *config = &mcc->config; 2264 struct ieee80211_p2p_noa_desc noa_desc = {}; 2265 u32 interval = config->mcc_interval; 2266 struct rtw89_vif_link *rtwvif_go; 2267 u64 start_time; 2268 u32 duration; 2269 2270 if (mcc->mode != RTW89_MCC_MODE_GO_STA) 2271 return; 2272 2273 if (ref->is_go) { 2274 start_time = config->start_tsf; 2275 rtwvif_go = ref->rtwvif_link; 2276 start_time += ieee80211_tu_to_usec(ref->duration); 2277 duration = config->mcc_interval - ref->duration; 2278 } else if (aux->is_go) { 2279 start_time = config->start_tsf_in_aux_domain; 2280 rtwvif_go = aux->rtwvif_link; 2281 duration = config->mcc_interval - aux->duration; 2282 } else { 2283 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2284 "MCC find no GO: skip updating beacon NoA\n"); 2285 return; 2286 } 2287 2288 rtw89_p2p_noa_renew(rtwvif_go); 2289 2290 if (enable) { 2291 duration += RTW89_MCC_SWITCH_CH_TIME; 2292 noa_desc.start_time = cpu_to_le32(start_time); 2293 noa_desc.interval = cpu_to_le32(ieee80211_tu_to_usec(interval)); 2294 noa_desc.duration = cpu_to_le32(ieee80211_tu_to_usec(duration)); 2295 noa_desc.count = 255; 2296 rtw89_p2p_noa_append(rtwvif_go, &noa_desc); 2297 } 2298 2299 /* without chanctx, we cannot get beacon from mac80211 stack */ 2300 if (!rtwvif_go->chanctx_assigned) 2301 return; 2302 2303 rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_go); 2304 } 2305 2306 static void rtw89_mcc_start_beacon_noa(struct rtw89_dev *rtwdev) 2307 { 2308 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2309 struct rtw89_mcc_role *ref = &mcc->role_ref; 2310 struct rtw89_mcc_role *aux = &mcc->role_aux; 2311 2312 if (mcc->mode != RTW89_MCC_MODE_GO_STA) 2313 return; 2314 2315 if (ref->is_go) 2316 rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, true); 2317 else if (aux->is_go) 2318 rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, true); 2319 2320 rtw89_mcc_handle_beacon_noa(rtwdev, true); 2321 } 2322 2323 static void rtw89_mcc_stop_beacon_noa(struct rtw89_dev *rtwdev) 2324 { 2325 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2326 struct rtw89_mcc_role *ref = &mcc->role_ref; 2327 struct rtw89_mcc_role *aux = &mcc->role_aux; 2328 2329 if (mcc->mode != RTW89_MCC_MODE_GO_STA) 2330 return; 2331 2332 if (ref->is_go) 2333 rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, false); 2334 else if (aux->is_go) 2335 rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, false); 2336 2337 rtw89_mcc_handle_beacon_noa(rtwdev, false); 2338 } 2339 2340 static bool rtw89_mcc_ignore_bcn(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role) 2341 { 2342 enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen; 2343 2344 if (role->is_go) 2345 return true; 2346 else if (chip_gen == RTW89_CHIP_BE && role->is_gc) 2347 return true; 2348 else 2349 return false; 2350 } 2351 2352 static int rtw89_mcc_start(struct rtw89_dev *rtwdev) 2353 { 2354 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2355 struct rtw89_mcc_role *ref = &mcc->role_ref; 2356 struct rtw89_mcc_role *aux = &mcc->role_aux; 2357 int ret; 2358 2359 if (rtwdev->scanning) 2360 rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); 2361 2362 rtw89_leave_lps(rtwdev); 2363 2364 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC start\n"); 2365 2366 ret = rtw89_mcc_fill_all_roles(rtwdev); 2367 if (ret) 2368 return ret; 2369 2370 if (ref->is_go || aux->is_go) 2371 mcc->mode = RTW89_MCC_MODE_GO_STA; 2372 else 2373 mcc->mode = RTW89_MCC_MODE_GC_STA; 2374 2375 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC sel mode: %d\n", mcc->mode); 2376 2377 mcc->group = RTW89_MCC_DFLT_GROUP; 2378 2379 ret = rtw89_mcc_fill_config(rtwdev); 2380 if (ret) 2381 return ret; 2382 2383 if (rtw89_mcc_ignore_bcn(rtwdev, ref) || aux->ignore_bcn) { 2384 rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, false); 2385 } else if (rtw89_mcc_ignore_bcn(rtwdev, aux) || ref->ignore_bcn) { 2386 rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, false); 2387 } else { 2388 rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, true); 2389 rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, true); 2390 } 2391 2392 if (rtw89_concurrent_via_mrc(rtwdev)) 2393 ret = __mrc_fw_start(rtwdev, false); 2394 else 2395 ret = __mcc_fw_start(rtwdev, false); 2396 2397 if (ret) 2398 return ret; 2399 2400 rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_START); 2401 2402 rtw89_mcc_start_beacon_noa(rtwdev); 2403 rtw89_phy_dig_suspend(rtwdev); 2404 2405 rtw89_mcc_prepare(rtwdev, true); 2406 return 0; 2407 } 2408 2409 struct rtw89_mcc_stop_sel { 2410 struct { 2411 const struct rtw89_vif_link *target; 2412 } hint; 2413 2414 /* selection content */ 2415 bool filled; 2416 u8 mac_id; 2417 u8 slot_idx; 2418 }; 2419 2420 static void rtw89_mcc_stop_sel_fill(struct rtw89_mcc_stop_sel *sel, 2421 const struct rtw89_mcc_role *mcc_role) 2422 { 2423 sel->mac_id = mcc_role->rtwvif_link->mac_id; 2424 sel->slot_idx = mcc_role->slot_idx; 2425 sel->filled = true; 2426 } 2427 2428 static int rtw89_mcc_stop_sel_iterator(struct rtw89_dev *rtwdev, 2429 struct rtw89_mcc_role *mcc_role, 2430 unsigned int ordered_idx, 2431 void *data) 2432 { 2433 struct rtw89_mcc_stop_sel *sel = data; 2434 2435 if (mcc_role->rtwvif_link == sel->hint.target) { 2436 rtw89_mcc_stop_sel_fill(sel, mcc_role); 2437 return 1; /* break iteration */ 2438 } 2439 2440 if (sel->filled) 2441 return 0; 2442 2443 if (!mcc_role->rtwvif_link->chanctx_assigned) 2444 return 0; 2445 2446 rtw89_mcc_stop_sel_fill(sel, mcc_role); 2447 return 0; 2448 } 2449 2450 static void rtw89_mcc_stop(struct rtw89_dev *rtwdev, 2451 const struct rtw89_chanctx_pause_parm *pause) 2452 { 2453 struct rtw89_hal *hal = &rtwdev->hal; 2454 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2455 struct rtw89_mcc_role *ref = &mcc->role_ref; 2456 struct rtw89_mcc_role *aux = &mcc->role_aux; 2457 struct rtw89_mcc_stop_sel sel = { 2458 .hint.target = pause ? pause->trigger : NULL, 2459 }; 2460 bool rsn_scan; 2461 int ret; 2462 2463 if (!pause) { 2464 wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->chanctx_work); 2465 bitmap_zero(hal->changes, NUM_OF_RTW89_CHANCTX_CHANGES); 2466 } 2467 2468 rsn_scan = pause && pause->rsn == RTW89_CHANCTX_PAUSE_REASON_HW_SCAN; 2469 if (rsn_scan && ref->is_go) 2470 sel.hint.target = ref->rtwvif_link; 2471 else if (rsn_scan && aux->is_go) 2472 sel.hint.target = aux->rtwvif_link; 2473 2474 /* by default, stop at ref */ 2475 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_stop_sel_iterator, &sel); 2476 if (!sel.filled) 2477 rtw89_mcc_stop_sel_fill(&sel, ref); 2478 2479 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC stop at <macid %d>\n", sel.mac_id); 2480 2481 if (rtw89_concurrent_via_mrc(rtwdev)) { 2482 ret = rtw89_fw_h2c_mrc_del(rtwdev, mcc->group, sel.slot_idx); 2483 if (ret) 2484 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2485 "MRC h2c failed to trigger del: %d\n", ret); 2486 } else { 2487 ret = rtw89_fw_h2c_stop_mcc(rtwdev, mcc->group, 2488 sel.mac_id, true); 2489 if (ret) 2490 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2491 "MCC h2c failed to trigger stop: %d\n", ret); 2492 2493 ret = rtw89_fw_h2c_del_mcc_group(rtwdev, mcc->group, true); 2494 if (ret) 2495 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2496 "MCC h2c failed to delete group: %d\n", ret); 2497 } 2498 2499 rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_STOP); 2500 2501 rtw89_mcc_stop_beacon_noa(rtwdev); 2502 rtw89_fw_h2c_mcc_dig(rtwdev, RTW89_CHANCTX_0, 0, 0, false); 2503 rtw89_phy_dig_resume(rtwdev, true); 2504 2505 rtw89_mcc_prepare(rtwdev, false); 2506 } 2507 2508 static int rtw89_mcc_update(struct rtw89_dev *rtwdev) 2509 { 2510 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2511 bool old_ref_ignore_bcn = mcc->role_ref.ignore_bcn; 2512 bool old_aux_ignore_bcn = mcc->role_aux.ignore_bcn; 2513 struct rtw89_mcc_config *config = &mcc->config; 2514 struct rtw89_mcc_role *ref = &mcc->role_ref; 2515 struct rtw89_mcc_role *aux = &mcc->role_aux; 2516 struct rtw89_mcc_config old_cfg = *config; 2517 bool courtesy_changed; 2518 bool sync_changed; 2519 int ret; 2520 2521 if (rtwdev->scanning) 2522 rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); 2523 2524 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC update\n"); 2525 2526 ret = rtw89_mcc_fill_config(rtwdev); 2527 if (ret) 2528 return ret; 2529 2530 if (old_ref_ignore_bcn != ref->ignore_bcn) 2531 rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, !ref->ignore_bcn); 2532 else if (old_aux_ignore_bcn != aux->ignore_bcn) 2533 rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, !aux->ignore_bcn); 2534 2535 if (memcmp(&old_cfg.pattern.courtesy, &config->pattern.courtesy, 2536 sizeof(old_cfg.pattern.courtesy)) == 0) 2537 courtesy_changed = false; 2538 else 2539 courtesy_changed = true; 2540 2541 if (old_cfg.pattern.plan != RTW89_MCC_PLAN_NO_BT || 2542 config->pattern.plan != RTW89_MCC_PLAN_NO_BT || 2543 courtesy_changed) { 2544 if (rtw89_concurrent_via_mrc(rtwdev)) 2545 ret = __mrc_fw_start(rtwdev, true); 2546 else 2547 ret = __mcc_fw_start(rtwdev, true); 2548 2549 if (ret) 2550 return ret; 2551 } else { 2552 if (memcmp(&old_cfg.sync, &config->sync, sizeof(old_cfg.sync)) == 0) 2553 sync_changed = false; 2554 else 2555 sync_changed = true; 2556 2557 if (rtw89_concurrent_via_mrc(rtwdev)) 2558 ret = __mrc_fw_set_duration_no_bt(rtwdev, sync_changed); 2559 else 2560 ret = __mcc_fw_set_duration_no_bt(rtwdev, sync_changed); 2561 2562 if (ret) 2563 return ret; 2564 } 2565 2566 rtw89_mcc_handle_beacon_noa(rtwdev, true); 2567 return 0; 2568 } 2569 2570 static int rtw89_mcc_search_gc_iterator(struct rtw89_dev *rtwdev, 2571 struct rtw89_mcc_role *mcc_role, 2572 unsigned int ordered_idx, 2573 void *data) 2574 { 2575 struct rtw89_mcc_role **role = data; 2576 2577 if (mcc_role->is_gc) 2578 *role = mcc_role; 2579 2580 return 0; 2581 } 2582 2583 static struct rtw89_mcc_role *rtw89_mcc_get_gc_role(struct rtw89_dev *rtwdev) 2584 { 2585 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2586 struct rtw89_mcc_role *role = NULL; 2587 2588 if (mcc->mode != RTW89_MCC_MODE_GC_STA) 2589 return NULL; 2590 2591 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_search_gc_iterator, &role); 2592 2593 return role; 2594 } 2595 2596 void rtw89_mcc_gc_detect_beacon_work(struct wiphy *wiphy, struct wiphy_work *work) 2597 { 2598 struct rtw89_vif_link *rtwvif_link = container_of(work, struct rtw89_vif_link, 2599 mcc_gc_detect_beacon_work.work); 2600 struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link); 2601 enum rtw89_entity_mode mode; 2602 struct rtw89_dev *rtwdev; 2603 2604 lockdep_assert_wiphy(wiphy); 2605 2606 rtwdev = rtwvif_link->rtwvif->rtwdev; 2607 2608 mode = rtw89_get_entity_mode(rtwdev); 2609 if (mode != RTW89_ENTITY_MODE_MCC) 2610 return; 2611 2612 if (READ_ONCE(rtwvif_link->sync_bcn_tsf) > rtwvif_link->last_sync_bcn_tsf) 2613 rtwvif_link->detect_bcn_count = 0; 2614 else 2615 rtwvif_link->detect_bcn_count++; 2616 2617 if (rtwvif_link->detect_bcn_count < RTW89_MCC_DETECT_BCN_MAX_TRIES) 2618 rtw89_chanctx_proceed(rtwdev, NULL); 2619 else 2620 ieee80211_connection_loss(vif); 2621 } 2622 2623 bool rtw89_mcc_detect_go_bcn(struct rtw89_dev *rtwdev, 2624 struct rtw89_vif_link *rtwvif_link) 2625 { 2626 enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev); 2627 struct rtw89_chanctx_pause_parm pause_parm = { 2628 .rsn = RTW89_CHANCTX_PAUSE_REASON_GC_BCN_LOSS, 2629 .trigger = rtwvif_link, 2630 }; 2631 struct ieee80211_bss_conf *bss_conf; 2632 struct rtw89_mcc_role *role; 2633 u16 bcn_int; 2634 2635 if (mode != RTW89_ENTITY_MODE_MCC) 2636 return false; 2637 2638 role = rtw89_mcc_get_gc_role(rtwdev); 2639 if (!role) 2640 return false; 2641 2642 if (role->rtwvif_link != rtwvif_link) 2643 return false; 2644 2645 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2646 "MCC GC beacon loss, pause MCC to detect GO beacon\n"); 2647 2648 rcu_read_lock(); 2649 2650 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true); 2651 bcn_int = bss_conf->beacon_int; 2652 2653 rcu_read_unlock(); 2654 2655 rtw89_chanctx_pause(rtwdev, &pause_parm); 2656 rtwvif_link->last_sync_bcn_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf); 2657 wiphy_delayed_work_queue(rtwdev->hw->wiphy, 2658 &rtwvif_link->mcc_gc_detect_beacon_work, 2659 usecs_to_jiffies(ieee80211_tu_to_usec(bcn_int))); 2660 2661 return true; 2662 } 2663 2664 static void rtw89_mcc_detect_connection(struct rtw89_dev *rtwdev, 2665 struct rtw89_mcc_role *role) 2666 { 2667 struct rtw89_vif_link *rtwvif_link = role->rtwvif_link; 2668 struct ieee80211_vif *vif; 2669 bool start_detect; 2670 int ret; 2671 2672 ret = rtw89_core_send_nullfunc(rtwdev, role->rtwvif_link, true, false, 2673 RTW89_MCC_PROBE_TIMEOUT); 2674 if (ret && 2675 READ_ONCE(rtwvif_link->sync_bcn_tsf) == rtwvif_link->last_sync_bcn_tsf) 2676 role->probe_count++; 2677 else 2678 role->probe_count = 0; 2679 2680 rtwvif_link->last_sync_bcn_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf); 2681 if (role->probe_count < RTW89_MCC_PROBE_MAX_TRIES) 2682 return; 2683 2684 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2685 "MCC <macid %d> can not detect AP/GO\n", role->rtwvif_link->mac_id); 2686 2687 start_detect = rtw89_mcc_detect_go_bcn(rtwdev, role->rtwvif_link); 2688 if (start_detect) 2689 return; 2690 2691 vif = rtwvif_link_to_vif(role->rtwvif_link); 2692 ieee80211_connection_loss(vif); 2693 } 2694 2695 static void rtw89_mcc_track(struct rtw89_dev *rtwdev) 2696 { 2697 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2698 struct rtw89_mcc_config *config = &mcc->config; 2699 struct rtw89_mcc_pattern *pattern = &config->pattern; 2700 struct rtw89_mcc_role *ref = &mcc->role_ref; 2701 struct rtw89_mcc_role *aux = &mcc->role_aux; 2702 u16 tolerance; 2703 u16 bcn_ofst; 2704 u16 diff; 2705 2706 if (rtw89_mcc_ignore_bcn(rtwdev, ref) || aux->ignore_bcn) 2707 rtw89_mcc_detect_connection(rtwdev, aux); 2708 else if (rtw89_mcc_ignore_bcn(rtwdev, aux) || ref->ignore_bcn) 2709 rtw89_mcc_detect_connection(rtwdev, ref); 2710 2711 if (mcc->mode != RTW89_MCC_MODE_GC_STA) 2712 return; 2713 2714 bcn_ofst = rtw89_mcc_get_bcn_ofst(rtwdev); 2715 if (bcn_ofst == config->beacon_offset) 2716 return; 2717 2718 if (bcn_ofst > config->beacon_offset) { 2719 diff = bcn_ofst - config->beacon_offset; 2720 if (pattern->tob_aux < 0) 2721 tolerance = -pattern->tob_aux; 2722 else if (pattern->toa_aux > 0) 2723 tolerance = pattern->toa_aux; 2724 else 2725 return; /* no chance to improve */ 2726 } else { 2727 diff = config->beacon_offset - bcn_ofst; 2728 if (pattern->toa_aux < 0) 2729 tolerance = -pattern->toa_aux; 2730 else if (pattern->tob_aux > 0) 2731 tolerance = pattern->tob_aux; 2732 else 2733 return; /* no chance to improve */ 2734 } 2735 2736 if (diff <= tolerance) 2737 return; 2738 2739 rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_BCN_OFFSET_CHANGE); 2740 } 2741 2742 static int __mcc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev, 2743 struct rtw89_mcc_role *upd) 2744 { 2745 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2746 int ret; 2747 2748 ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group, 2749 upd->rtwvif_link->mac_id, 2750 upd->macid_bitmap); 2751 if (ret) { 2752 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2753 "MCC h2c failed to update macid bitmap: %d\n", ret); 2754 return ret; 2755 } 2756 2757 return 0; 2758 } 2759 2760 static int __mrc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev, 2761 struct rtw89_mcc_role *cur, 2762 struct rtw89_mcc_role *upd) 2763 { 2764 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2765 struct rtw89_fw_mrc_upd_bitmap_arg arg = {}; 2766 u32 old = rtw89_mcc_role_fw_macid_bitmap_to_u32(cur); 2767 u32 new = rtw89_mcc_role_fw_macid_bitmap_to_u32(upd); 2768 u32 add = new & ~old; 2769 u32 del = old & ~new; 2770 int ret; 2771 int i; 2772 2773 arg.sch_idx = mcc->group; 2774 arg.macid = upd->rtwvif_link->mac_id; 2775 2776 for (i = 0; i < 32; i++) { 2777 if (add & BIT(i)) { 2778 arg.client_macid = i; 2779 arg.action = RTW89_H2C_MRC_UPD_BITMAP_ACTION_ADD; 2780 2781 ret = rtw89_fw_h2c_mrc_upd_bitmap(rtwdev, &arg); 2782 if (ret) 2783 goto err; 2784 } 2785 } 2786 2787 for (i = 0; i < 32; i++) { 2788 if (del & BIT(i)) { 2789 arg.client_macid = i; 2790 arg.action = RTW89_H2C_MRC_UPD_BITMAP_ACTION_DEL; 2791 2792 ret = rtw89_fw_h2c_mrc_upd_bitmap(rtwdev, &arg); 2793 if (ret) 2794 goto err; 2795 } 2796 } 2797 2798 return 0; 2799 2800 err: 2801 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2802 "MRC h2c failed to update bitmap: %d\n", ret); 2803 return ret; 2804 } 2805 2806 static int rtw89_mcc_upd_map_iterator(struct rtw89_dev *rtwdev, 2807 struct rtw89_mcc_role *mcc_role, 2808 unsigned int ordered_idx, 2809 void *data) 2810 { 2811 struct rtw89_mcc_role upd = { 2812 .rtwvif_link = mcc_role->rtwvif_link, 2813 }; 2814 int ret; 2815 2816 if (!mcc_role->is_go) 2817 return 0; 2818 2819 rtw89_mcc_fill_role_macid_bitmap(rtwdev, &upd); 2820 if (memcmp(mcc_role->macid_bitmap, upd.macid_bitmap, 2821 sizeof(mcc_role->macid_bitmap)) == 0) 2822 return 0; 2823 2824 if (rtw89_concurrent_via_mrc(rtwdev)) 2825 ret = __mrc_fw_upd_macid_bitmap(rtwdev, mcc_role, &upd); 2826 else 2827 ret = __mcc_fw_upd_macid_bitmap(rtwdev, &upd); 2828 2829 if (ret) 2830 return ret; 2831 2832 memcpy(mcc_role->macid_bitmap, upd.macid_bitmap, 2833 sizeof(mcc_role->macid_bitmap)); 2834 return 0; 2835 } 2836 2837 static void rtw89_mcc_update_macid_bitmap(struct rtw89_dev *rtwdev) 2838 { 2839 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2840 2841 if (mcc->mode != RTW89_MCC_MODE_GO_STA) 2842 return; 2843 2844 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_upd_map_iterator, NULL); 2845 } 2846 2847 static int rtw89_mcc_upd_lmt_iterator(struct rtw89_dev *rtwdev, 2848 struct rtw89_mcc_role *mcc_role, 2849 unsigned int ordered_idx, 2850 void *data) 2851 { 2852 memset(&mcc_role->limit, 0, sizeof(mcc_role->limit)); 2853 rtw89_mcc_fill_role_limit(rtwdev, mcc_role); 2854 return 0; 2855 } 2856 2857 static void rtw89_mcc_update_limit(struct rtw89_dev *rtwdev) 2858 { 2859 struct rtw89_mcc_info *mcc = &rtwdev->mcc; 2860 2861 if (mcc->mode != RTW89_MCC_MODE_GC_STA) 2862 return; 2863 2864 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_upd_lmt_iterator, NULL); 2865 } 2866 2867 static int rtw89_mcc_get_links_iterator(struct rtw89_dev *rtwdev, 2868 struct rtw89_mcc_role *mcc_role, 2869 unsigned int ordered_idx, 2870 void *data) 2871 { 2872 struct rtw89_mcc_links_info *info = data; 2873 2874 info->links[ordered_idx] = mcc_role->rtwvif_link; 2875 return 0; 2876 } 2877 2878 void rtw89_mcc_get_links(struct rtw89_dev *rtwdev, struct rtw89_mcc_links_info *info) 2879 { 2880 enum rtw89_entity_mode mode; 2881 2882 memset(info, 0, sizeof(*info)); 2883 2884 mode = rtw89_get_entity_mode(rtwdev); 2885 if (unlikely(mode != RTW89_ENTITY_MODE_MCC)) 2886 return; 2887 2888 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_get_links_iterator, info); 2889 } 2890 2891 void rtw89_chanctx_work(struct wiphy *wiphy, struct wiphy_work *work) 2892 { 2893 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev, 2894 chanctx_work.work); 2895 struct rtw89_hal *hal = &rtwdev->hal; 2896 bool update_mcc_pattern = false; 2897 enum rtw89_entity_mode mode; 2898 u32 changed = 0; 2899 int ret; 2900 int i; 2901 2902 lockdep_assert_wiphy(wiphy); 2903 2904 if (hal->entity_pause) 2905 return; 2906 2907 for (i = 0; i < NUM_OF_RTW89_CHANCTX_CHANGES; i++) { 2908 if (test_and_clear_bit(i, hal->changes)) 2909 changed |= BIT(i); 2910 } 2911 2912 mode = rtw89_get_entity_mode(rtwdev); 2913 switch (mode) { 2914 case RTW89_ENTITY_MODE_MCC_PREPARE: 2915 rtw89_set_entity_mode(rtwdev, RTW89_ENTITY_MODE_MCC); 2916 rtw89_set_channel(rtwdev); 2917 2918 ret = rtw89_mcc_start(rtwdev); 2919 if (ret) 2920 rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret); 2921 break; 2922 case RTW89_ENTITY_MODE_MCC: 2923 if (changed & BIT(RTW89_CHANCTX_BCN_OFFSET_CHANGE) || 2924 changed & BIT(RTW89_CHANCTX_P2P_PS_CHANGE) || 2925 changed & BIT(RTW89_CHANCTX_BT_SLOT_CHANGE) || 2926 changed & BIT(RTW89_CHANCTX_TSF32_TOGGLE_CHANGE)) 2927 update_mcc_pattern = true; 2928 if (changed & BIT(RTW89_CHANCTX_REMOTE_STA_CHANGE)) 2929 rtw89_mcc_update_macid_bitmap(rtwdev); 2930 if (changed & BIT(RTW89_CHANCTX_P2P_PS_CHANGE)) 2931 rtw89_mcc_update_limit(rtwdev); 2932 if (changed & BIT(RTW89_CHANCTX_BT_SLOT_CHANGE)) 2933 rtw89_mcc_fill_bt_role(rtwdev); 2934 if (update_mcc_pattern) { 2935 ret = rtw89_mcc_update(rtwdev); 2936 if (ret) 2937 rtw89_warn(rtwdev, "failed to update MCC: %d\n", 2938 ret); 2939 } 2940 break; 2941 default: 2942 break; 2943 } 2944 } 2945 2946 void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev, 2947 enum rtw89_chanctx_changes change) 2948 { 2949 struct rtw89_hal *hal = &rtwdev->hal; 2950 enum rtw89_entity_mode mode; 2951 u32 delay; 2952 2953 mode = rtw89_get_entity_mode(rtwdev); 2954 switch (mode) { 2955 default: 2956 return; 2957 case RTW89_ENTITY_MODE_MCC_PREPARE: 2958 delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC_PREPARE); 2959 rtw89_phy_dig_suspend(rtwdev); 2960 break; 2961 case RTW89_ENTITY_MODE_MCC: 2962 delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC); 2963 break; 2964 } 2965 2966 if (change != RTW89_CHANCTX_CHANGE_DFLT) { 2967 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "set chanctx change %d\n", 2968 change); 2969 set_bit(change, hal->changes); 2970 } 2971 2972 rtw89_debug(rtwdev, RTW89_DBG_CHAN, 2973 "queue chanctx work for mode %d with delay %d us\n", 2974 mode, delay); 2975 wiphy_delayed_work_queue(rtwdev->hw->wiphy, &rtwdev->chanctx_work, 2976 usecs_to_jiffies(delay)); 2977 } 2978 2979 void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev) 2980 { 2981 rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_CHANGE_DFLT); 2982 } 2983 2984 static enum rtw89_mr_wtype __rtw89_query_mr_wtype(struct rtw89_dev *rtwdev) 2985 { 2986 struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt; 2987 enum rtw89_chanctx_idx chanctx_idx; 2988 struct ieee80211_vif *vif; 2989 struct rtw89_vif *rtwvif; 2990 unsigned int num_mld = 0; 2991 unsigned int num_ml = 0; 2992 unsigned int cnt = 0; 2993 u8 role_idx; 2994 u8 idx; 2995 2996 for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) { 2997 rtwvif = mgnt->active_roles[role_idx]; 2998 if (!rtwvif) 2999 continue; 3000 3001 cnt++; 3002 3003 vif = rtwvif_to_vif(rtwvif); 3004 if (!ieee80211_vif_is_mld(vif)) 3005 continue; 3006 3007 num_mld++; 3008 3009 for (idx = 0; idx < __RTW89_MLD_MAX_LINK_NUM; idx++) { 3010 chanctx_idx = mgnt->chanctx_tbl[role_idx][idx]; 3011 if (chanctx_idx != RTW89_CHANCTX_IDLE) 3012 num_ml++; 3013 } 3014 } 3015 3016 if (num_mld > 1) 3017 goto err; 3018 3019 switch (cnt) { 3020 case 0: 3021 return RTW89_MR_WTYPE_NONE; 3022 case 1: 3023 if (!num_mld) 3024 return RTW89_MR_WTYPE_NONMLD; 3025 switch (num_ml) { 3026 case 1: 3027 return RTW89_MR_WTYPE_MLD1L1R; 3028 case 2: 3029 return RTW89_MR_WTYPE_MLD2L1R; 3030 default: 3031 break; 3032 } 3033 break; 3034 case 2: 3035 if (!num_mld) 3036 return RTW89_MR_WTYPE_NONMLD_NONMLD; 3037 switch (num_ml) { 3038 case 1: 3039 return RTW89_MR_WTYPE_MLD1L1R_NONMLD; 3040 case 2: 3041 return RTW89_MR_WTYPE_MLD2L1R_NONMLD; 3042 default: 3043 break; 3044 } 3045 break; 3046 default: 3047 break; 3048 } 3049 3050 err: 3051 rtw89_warn(rtwdev, "%s: unhandled cnt %u mld %u ml %u\n", __func__, 3052 cnt, num_mld, num_ml); 3053 return RTW89_MR_WTYPE_UNKNOWN; 3054 } 3055 3056 static enum rtw89_mr_wmode __rtw89_query_mr_wmode(struct rtw89_dev *rtwdev, 3057 u8 inst_idx) 3058 { 3059 struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt; 3060 unsigned int num[NUM_NL80211_IFTYPES] = {}; 3061 enum rtw89_chanctx_idx chanctx_idx; 3062 struct ieee80211_vif *vif; 3063 struct rtw89_vif *rtwvif; 3064 unsigned int cnt = 0; 3065 u8 role_idx; 3066 3067 if (unlikely(inst_idx >= __RTW89_MLD_MAX_LINK_NUM)) 3068 return RTW89_MR_WMODE_UNKNOWN; 3069 3070 for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) { 3071 chanctx_idx = mgnt->chanctx_tbl[role_idx][inst_idx]; 3072 if (chanctx_idx == RTW89_CHANCTX_IDLE) 3073 continue; 3074 3075 rtwvif = mgnt->active_roles[role_idx]; 3076 if (unlikely(!rtwvif)) 3077 continue; 3078 3079 vif = rtwvif_to_vif(rtwvif); 3080 num[vif->type]++; 3081 cnt++; 3082 } 3083 3084 switch (cnt) { 3085 case 0: 3086 return RTW89_MR_WMODE_NONE; 3087 case 1: 3088 if (num[NL80211_IFTYPE_STATION]) 3089 return RTW89_MR_WMODE_1CLIENT; 3090 if (num[NL80211_IFTYPE_AP]) 3091 return RTW89_MR_WMODE_1AP; 3092 break; 3093 case 2: 3094 if (num[NL80211_IFTYPE_STATION] == 2) 3095 return RTW89_MR_WMODE_2CLIENTS; 3096 if (num[NL80211_IFTYPE_AP] == 2) 3097 return RTW89_MR_WMODE_2APS; 3098 if (num[NL80211_IFTYPE_STATION] && num[NL80211_IFTYPE_AP]) 3099 return RTW89_MR_WMODE_1AP_1CLIENT; 3100 break; 3101 default: 3102 break; 3103 } 3104 3105 rtw89_warn(rtwdev, "%s: unhandled cnt %u\n", __func__, cnt); 3106 return RTW89_MR_WMODE_UNKNOWN; 3107 } 3108 3109 static enum rtw89_mr_ctxtype __rtw89_query_mr_ctxtype(struct rtw89_dev *rtwdev, 3110 u8 inst_idx) 3111 { 3112 struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt; 3113 DECLARE_BITMAP(map, NUM_OF_RTW89_CHANCTX) = {}; 3114 unsigned int num[RTW89_BAND_NUM] = {}; 3115 enum rtw89_chanctx_idx chanctx_idx; 3116 const struct rtw89_chan *chan; 3117 unsigned int cnt = 0; 3118 u8 role_idx; 3119 3120 if (unlikely(inst_idx >= __RTW89_MLD_MAX_LINK_NUM)) 3121 return RTW89_MR_CTX_UNKNOWN; 3122 3123 for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) { 3124 chanctx_idx = mgnt->chanctx_tbl[role_idx][inst_idx]; 3125 if (chanctx_idx == RTW89_CHANCTX_IDLE) 3126 continue; 3127 3128 if (__test_and_set_bit(chanctx_idx, map)) 3129 continue; 3130 3131 chan = rtw89_chan_get(rtwdev, chanctx_idx); 3132 num[chan->band_type]++; 3133 cnt++; 3134 } 3135 3136 switch (cnt) { 3137 case 0: 3138 return RTW89_MR_CTX_NONE; 3139 case 1: 3140 if (num[RTW89_BAND_2G]) 3141 return RTW89_MR_CTX1_2GHZ; 3142 if (num[RTW89_BAND_5G]) 3143 return RTW89_MR_CTX1_5GHZ; 3144 if (num[RTW89_BAND_6G]) 3145 return RTW89_MR_CTX1_6GHZ; 3146 break; 3147 case 2: 3148 if (num[RTW89_BAND_2G] == 2) 3149 return RTW89_MR_CTX2_2GHZ; 3150 if (num[RTW89_BAND_5G] == 2) 3151 return RTW89_MR_CTX2_5GHZ; 3152 if (num[RTW89_BAND_6G] == 2) 3153 return RTW89_MR_CTX2_6GHZ; 3154 if (num[RTW89_BAND_2G] && num[RTW89_BAND_5G]) 3155 return RTW89_MR_CTX2_2GHZ_5GHZ; 3156 if (num[RTW89_BAND_2G] && num[RTW89_BAND_6G]) 3157 return RTW89_MR_CTX2_2GHZ_6GHZ; 3158 if (num[RTW89_BAND_5G] && num[RTW89_BAND_6G]) 3159 return RTW89_MR_CTX2_5GHZ_6GHZ; 3160 break; 3161 default: 3162 break; 3163 } 3164 3165 rtw89_warn(rtwdev, "%s: unhandled cnt %u\n", __func__, cnt); 3166 return RTW89_MR_CTX_UNKNOWN; 3167 } 3168 3169 void rtw89_query_mr_chanctx_info(struct rtw89_dev *rtwdev, u8 inst_idx, 3170 struct rtw89_mr_chanctx_info *info) 3171 { 3172 lockdep_assert_wiphy(rtwdev->hw->wiphy); 3173 3174 info->wtype = __rtw89_query_mr_wtype(rtwdev); 3175 info->wmode = __rtw89_query_mr_wmode(rtwdev, inst_idx); 3176 info->ctxtype = __rtw89_query_mr_ctxtype(rtwdev, inst_idx); 3177 } 3178 3179 void rtw89_chanctx_track(struct rtw89_dev *rtwdev) 3180 { 3181 struct rtw89_hal *hal = &rtwdev->hal; 3182 enum rtw89_entity_mode mode; 3183 3184 lockdep_assert_wiphy(rtwdev->hw->wiphy); 3185 3186 if (hal->entity_pause) 3187 return; 3188 3189 mode = rtw89_get_entity_mode(rtwdev); 3190 switch (mode) { 3191 case RTW89_ENTITY_MODE_MCC: 3192 rtw89_mcc_track(rtwdev); 3193 break; 3194 default: 3195 break; 3196 } 3197 } 3198 3199 void rtw89_chanctx_pause(struct rtw89_dev *rtwdev, 3200 const struct rtw89_chanctx_pause_parm *pause_parm) 3201 { 3202 struct rtw89_hal *hal = &rtwdev->hal; 3203 enum rtw89_entity_mode mode; 3204 3205 lockdep_assert_wiphy(rtwdev->hw->wiphy); 3206 3207 if (hal->entity_pause) 3208 return; 3209 3210 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "chanctx pause (rsn: %d)\n", pause_parm->rsn); 3211 3212 mode = rtw89_get_entity_mode(rtwdev); 3213 switch (mode) { 3214 case RTW89_ENTITY_MODE_MCC: 3215 rtw89_mcc_stop(rtwdev, pause_parm); 3216 break; 3217 default: 3218 break; 3219 } 3220 3221 hal->entity_pause = true; 3222 } 3223 3224 static void rtw89_chanctx_proceed_cb(struct rtw89_dev *rtwdev, 3225 const struct rtw89_chanctx_cb_parm *parm) 3226 { 3227 int ret; 3228 3229 if (!parm || !parm->cb) 3230 return; 3231 3232 ret = parm->cb(rtwdev, parm->data); 3233 if (ret) 3234 rtw89_warn(rtwdev, "%s (%s): cb failed: %d\n", __func__, 3235 parm->caller ?: "unknown", ret); 3236 } 3237 3238 /* pass @cb_parm if there is a @cb_parm->cb which needs to invoke right after 3239 * call rtw89_set_channel() and right before proceed entity according to mode. 3240 */ 3241 void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev, 3242 const struct rtw89_chanctx_cb_parm *cb_parm) 3243 { 3244 struct rtw89_hal *hal = &rtwdev->hal; 3245 enum rtw89_entity_mode mode; 3246 int ret; 3247 3248 lockdep_assert_wiphy(rtwdev->hw->wiphy); 3249 3250 if (unlikely(!hal->entity_pause)) { 3251 rtw89_chanctx_proceed_cb(rtwdev, cb_parm); 3252 return; 3253 } 3254 3255 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "chanctx proceed\n"); 3256 3257 hal->entity_pause = false; 3258 rtw89_set_channel(rtwdev); 3259 3260 rtw89_chanctx_proceed_cb(rtwdev, cb_parm); 3261 3262 mode = rtw89_get_entity_mode(rtwdev); 3263 switch (mode) { 3264 case RTW89_ENTITY_MODE_MCC: 3265 ret = rtw89_mcc_start(rtwdev); 3266 if (ret) 3267 rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret); 3268 break; 3269 default: 3270 break; 3271 } 3272 3273 rtw89_queue_chanctx_work(rtwdev); 3274 } 3275 3276 static void __rtw89_swap_chanctx(struct rtw89_vif *rtwvif, 3277 enum rtw89_chanctx_idx idx1, 3278 enum rtw89_chanctx_idx idx2) 3279 { 3280 struct rtw89_vif_link *rtwvif_link; 3281 unsigned int link_id; 3282 3283 rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) { 3284 if (!rtwvif_link->chanctx_assigned) 3285 continue; 3286 3287 if (rtwvif_link->chanctx_idx == idx1) 3288 rtwvif_link->chanctx_idx = idx2; 3289 else if (rtwvif_link->chanctx_idx == idx2) 3290 rtwvif_link->chanctx_idx = idx1; 3291 } 3292 } 3293 3294 static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev, 3295 enum rtw89_chanctx_idx idx1, 3296 enum rtw89_chanctx_idx idx2) 3297 { 3298 struct rtw89_hal *hal = &rtwdev->hal; 3299 struct rtw89_vif *rtwvif; 3300 u8 cur; 3301 3302 if (idx1 == idx2) 3303 return; 3304 3305 hal->chanctx[idx1].cfg->idx = idx2; 3306 hal->chanctx[idx2].cfg->idx = idx1; 3307 3308 swap(hal->chanctx[idx1], hal->chanctx[idx2]); 3309 3310 rtw89_for_each_rtwvif(rtwdev, rtwvif) 3311 __rtw89_swap_chanctx(rtwvif, idx1, idx2); 3312 3313 cur = atomic_read(&hal->roc_chanctx_idx); 3314 if (cur == idx1) 3315 atomic_set(&hal->roc_chanctx_idx, idx2); 3316 else if (cur == idx2) 3317 atomic_set(&hal->roc_chanctx_idx, idx1); 3318 } 3319 3320 int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev, 3321 struct ieee80211_chanctx_conf *ctx) 3322 { 3323 struct rtw89_hal *hal = &rtwdev->hal; 3324 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; 3325 const struct rtw89_chip_info *chip = rtwdev->chip; 3326 u8 idx; 3327 3328 idx = find_first_zero_bit(hal->entity_map, NUM_OF_RTW89_CHANCTX); 3329 if (idx >= chip->support_chanctx_num) 3330 return -ENOENT; 3331 3332 rtw89_config_entity_chandef(rtwdev, idx, &ctx->def); 3333 cfg->idx = idx; 3334 cfg->ref_count = 0; 3335 hal->chanctx[idx].cfg = cfg; 3336 return 0; 3337 } 3338 3339 void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev, 3340 struct ieee80211_chanctx_conf *ctx) 3341 { 3342 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; 3343 3344 rtw89_config_entity_chandef(rtwdev, cfg->idx, NULL); 3345 } 3346 3347 void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev, 3348 struct ieee80211_chanctx_conf *ctx, 3349 u32 changed) 3350 { 3351 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; 3352 u8 idx = cfg->idx; 3353 3354 if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) { 3355 rtw89_config_entity_chandef(rtwdev, idx, &ctx->def); 3356 rtw89_set_channel(rtwdev); 3357 } 3358 3359 if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING) 3360 rtw89_chan_update_punctured(rtwdev, idx, &ctx->def); 3361 } 3362 3363 int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev, 3364 struct rtw89_vif_link *rtwvif_link, 3365 struct ieee80211_chanctx_conf *ctx) 3366 { 3367 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; 3368 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; 3369 struct rtw89_hal *hal = &rtwdev->hal; 3370 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt; 3371 struct rtw89_entity_weight w = {}; 3372 int ret; 3373 3374 rtwvif_link->chanctx_idx = cfg->idx; 3375 rtwvif_link->chanctx_assigned = true; 3376 cfg->ref_count++; 3377 3378 if (rtwdev->scanning) 3379 rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); 3380 3381 if (list_empty(&rtwvif->mgnt_entry)) 3382 list_add_tail(&rtwvif->mgnt_entry, &mgnt->active_list); 3383 3384 if (cfg->idx == RTW89_CHANCTX_0) 3385 goto out; 3386 3387 rtw89_entity_calculate_weight(rtwdev, &w); 3388 if (w.active_chanctxs != 1) 3389 goto out; 3390 3391 /* put the first active chanctx at RTW89_CHANCTX_0 */ 3392 rtw89_swap_chanctx(rtwdev, cfg->idx, RTW89_CHANCTX_0); 3393 3394 out: 3395 ret = rtw89_set_channel(rtwdev); 3396 if (ret) 3397 return ret; 3398 3399 rtw89_tas_reset(rtwdev, true); 3400 3401 return 0; 3402 } 3403 3404 void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev, 3405 struct rtw89_vif_link *rtwvif_link, 3406 struct ieee80211_chanctx_conf *ctx) 3407 { 3408 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv; 3409 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif; 3410 struct rtw89_hal *hal = &rtwdev->hal; 3411 enum rtw89_chanctx_idx roll; 3412 enum rtw89_entity_mode cur; 3413 enum rtw89_entity_mode new; 3414 int ret; 3415 3416 rtwvif_link->chanctx_idx = RTW89_CHANCTX_0; 3417 rtwvif_link->chanctx_assigned = false; 3418 cfg->ref_count--; 3419 3420 if (rtwdev->scanning) 3421 rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif); 3422 3423 if (!rtw89_vif_is_active_role(rtwvif)) 3424 list_del_init(&rtwvif->mgnt_entry); 3425 3426 if (cfg->ref_count != 0) 3427 goto out; 3428 3429 if (cfg->idx != RTW89_CHANCTX_0) 3430 goto out; 3431 3432 roll = find_next_bit(hal->entity_map, NUM_OF_RTW89_CHANCTX, 3433 cfg->idx + 1); 3434 /* Follow rtw89_config_default_chandef() when rtw89_entity_recalc(). */ 3435 if (roll == NUM_OF_RTW89_CHANCTX) 3436 goto out; 3437 3438 /* RTW89_CHANCTX_0 is going to release, and another exists. 3439 * Make another roll down to RTW89_CHANCTX_0 to replace. 3440 */ 3441 rtw89_swap_chanctx(rtwdev, cfg->idx, roll); 3442 3443 out: 3444 if (!hal->entity_pause) { 3445 cur = rtw89_get_entity_mode(rtwdev); 3446 switch (cur) { 3447 case RTW89_ENTITY_MODE_MCC: 3448 rtw89_mcc_stop(rtwdev, NULL); 3449 break; 3450 default: 3451 break; 3452 } 3453 } 3454 3455 ret = rtw89_set_channel(rtwdev); 3456 if (ret) 3457 return; 3458 3459 if (hal->entity_pause) 3460 return; 3461 3462 new = rtw89_get_entity_mode(rtwdev); 3463 switch (new) { 3464 case RTW89_ENTITY_MODE_MCC: 3465 /* re-plan MCC for chanctx changes. */ 3466 ret = rtw89_mcc_start(rtwdev); 3467 if (ret) 3468 rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret); 3469 break; 3470 default: 3471 break; 3472 } 3473 } 3474 3475 int rtw89_chanctx_ops_reassign_vif(struct rtw89_dev *rtwdev, 3476 struct rtw89_vif_link *rtwvif_link, 3477 struct ieee80211_chanctx_conf *old_ctx, 3478 struct ieee80211_chanctx_conf *new_ctx, 3479 bool replace) 3480 { 3481 int ret; 3482 3483 rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif_link, old_ctx); 3484 3485 if (!replace) 3486 goto assign; 3487 3488 rtw89_chanctx_ops_remove(rtwdev, old_ctx); 3489 ret = rtw89_chanctx_ops_add(rtwdev, new_ctx); 3490 if (ret) { 3491 rtw89_err(rtwdev, "%s: failed to add chanctx: %d\n", 3492 __func__, ret); 3493 return ret; 3494 } 3495 3496 assign: 3497 ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif_link, new_ctx); 3498 if (ret) { 3499 rtw89_err(rtwdev, "%s: failed to assign chanctx: %d\n", 3500 __func__, ret); 3501 return ret; 3502 } 3503 3504 _rtw89_chan_update_punctured(rtwdev, rtwvif_link, &new_ctx->def); 3505 3506 return 0; 3507 } 3508