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