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