1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright (c) 2023, Intel Corporation 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the Intel Corporation nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /** 33 * @file ice_rdma.c 34 * @brief RDMA client driver interface 35 * 36 * Functions to interface with the RDMA client driver, for enabling RMDA 37 * functionality for the ice driver. 38 * 39 * The RDMA client interface is based on a simple kobject interface which is 40 * defined by the rmda_if.m and irdma_di_if.m interfaces. 41 * 42 * The ice device driver provides the rmda_di_if.m interface methods, while 43 * the client RDMA driver provides the irdma_if.m interface methods as an 44 * extension ontop of the irdma_di_if kobject. 45 * 46 * The initial connection between drivers is done via the RDMA client driver 47 * calling ice_rdma_register. 48 */ 49 50 #include "ice_iflib.h" 51 #include "ice_rdma_internal.h" 52 53 #include "irdma_if.h" 54 #include "irdma_di_if.h" 55 56 /** 57 * @var ice_rdma 58 * @brief global RDMA driver state 59 * 60 * Contains global state the driver uses to connect to a client RDMA interface 61 * driver. 62 */ 63 static struct ice_rdma_state ice_rdma; 64 65 /* 66 * Helper function prototypes 67 */ 68 static int ice_rdma_pf_attach_locked(struct ice_softc *sc); 69 static void ice_rdma_pf_detach_locked(struct ice_softc *sc); 70 static int ice_rdma_check_version(struct ice_rdma_info *info); 71 static void ice_rdma_cp_qos_info(struct ice_hw *hw, 72 struct ice_dcbx_cfg *dcbx_cfg, 73 struct ice_qos_params *qos_info); 74 75 /* 76 * RDMA Device Interface prototypes 77 */ 78 static int ice_rdma_pf_reset(struct ice_rdma_peer *peer); 79 static int ice_rdma_pf_msix_init(struct ice_rdma_peer *peer, 80 struct ice_rdma_msix_mapping *msix_info); 81 static int ice_rdma_qset_register_request(struct ice_rdma_peer *peer, 82 struct ice_rdma_qset_update *res); 83 static int ice_rdma_update_vsi_filter(struct ice_rdma_peer *peer_dev, 84 bool enable); 85 static void ice_rdma_request_handler(struct ice_rdma_peer *peer, 86 struct ice_rdma_request *req); 87 88 89 /** 90 * @var ice_rdma_di_methods 91 * @brief RDMA driver interface methods 92 * 93 * Kobject methods implementing the driver-side interface for the RDMA peer 94 * clients. This method table contains the operations which the client can 95 * request from the driver. 96 * 97 * The client driver will then extend this kobject class with methods that the 98 * driver can request from the client. 99 */ 100 static kobj_method_t ice_rdma_di_methods[] = { 101 KOBJMETHOD(irdma_di_reset, ice_rdma_pf_reset), 102 KOBJMETHOD(irdma_di_msix_init, ice_rdma_pf_msix_init), 103 KOBJMETHOD(irdma_di_qset_register_request, ice_rdma_qset_register_request), 104 KOBJMETHOD(irdma_di_vsi_filter_update, ice_rdma_update_vsi_filter), 105 KOBJMETHOD(irdma_di_req_handler, ice_rdma_request_handler), 106 KOBJMETHOD_END 107 }; 108 109 /* Define ice_rdma_di class which will be extended by the iRDMA driver */ 110 DEFINE_CLASS_0(ice_rdma_di, ice_rdma_di_class, ice_rdma_di_methods, sizeof(struct ice_rdma_peer)); 111 112 /** 113 * ice_rdma_pf_reset - RDMA client interface requested a reset 114 * @peer: the RDMA peer client structure 115 * 116 * Implements IRDMA_DI_RESET, called by the RDMA client driver to request 117 * a reset of an ice driver device. 118 */ 119 static int 120 ice_rdma_pf_reset(struct ice_rdma_peer *peer) 121 { 122 struct ice_softc *sc = ice_rdma_peer_to_sc(peer); 123 124 /* 125 * Request that the driver re-initialize by bringing the interface 126 * down and up. 127 */ 128 ice_request_stack_reinit(sc); 129 130 return (0); 131 } 132 133 /** 134 * ice_rdma_pf_msix_init - RDMA client interface request MSI-X initialization 135 * @peer: the RDMA peer client structure 136 * @msix_info: requested MSI-X mapping 137 * 138 * Implements IRDMA_DI_MSIX_INIT, called by the RDMA client driver to 139 * initialize the MSI-X resources required for RDMA functionality. 140 */ 141 static int 142 ice_rdma_pf_msix_init(struct ice_rdma_peer *peer, 143 struct ice_rdma_msix_mapping __unused *msix_info) 144 { 145 struct ice_softc *sc = ice_rdma_peer_to_sc(peer); 146 147 MPASS(msix_info != NULL); 148 149 device_printf(sc->dev, "%s: iRDMA MSI-X initialization request is not yet implemented\n", __func__); 150 151 /* TODO: implement MSI-X initialization for RDMA */ 152 return (ENOSYS); 153 } 154 155 /** 156 * ice_rdma_register_request - RDMA client interface request qset 157 * registration or unregistration 158 * @peer: the RDMA peer client structure 159 * @res: resources to be registered or unregistered 160 */ 161 static int 162 ice_rdma_qset_register_request(struct ice_rdma_peer *peer, struct ice_rdma_qset_update *res) 163 { 164 struct ice_softc *sc = ice_rdma_peer_to_sc(peer); 165 struct ice_vsi *vsi = NULL; 166 struct ice_dcbx_cfg *dcbx_cfg; 167 struct ice_hw *hw = &sc->hw; 168 enum ice_status status; 169 int count, i, ret = 0; 170 uint32_t *qset_teid; 171 uint16_t *qs_handle; 172 uint16_t max_rdmaqs[ICE_MAX_TRAFFIC_CLASS]; 173 uint16_t vsi_id; 174 uint8_t ena_tc = 0; 175 176 if (!res) 177 return -EINVAL; 178 179 if (res->cnt_req > ICE_MAX_TXQ_PER_TXQG) 180 return -EINVAL; 181 182 switch(res->res_type) { 183 case ICE_RDMA_QSET_ALLOC: 184 count = res->cnt_req; 185 vsi_id = peer->pf_vsi_num; 186 break; 187 case ICE_RDMA_QSET_FREE: 188 count = res->res_allocated; 189 vsi_id = res->qsets.vsi_id; 190 break; 191 default: 192 return -EINVAL; 193 } 194 qset_teid = (uint32_t *)ice_calloc(hw, count, sizeof(*qset_teid)); 195 if (!qset_teid) 196 return -ENOMEM; 197 198 qs_handle = (uint16_t *)ice_calloc(hw, count, sizeof(*qs_handle)); 199 if (!qs_handle) { 200 ice_free(hw, qset_teid); 201 return -ENOMEM; 202 } 203 204 ice_for_each_traffic_class(i) 205 max_rdmaqs[i] = 0; 206 for (i = 0; i < sc->num_available_vsi; i++) { 207 if (sc->all_vsi[i] && 208 ice_get_hw_vsi_num(hw, sc->all_vsi[i]->idx) == vsi_id) { 209 vsi = sc->all_vsi[i]; 210 break; 211 } 212 } 213 214 if (!vsi) { 215 ice_debug(hw, ICE_DBG_RDMA, "RDMA QSet invalid VSI\n"); 216 ret = -EINVAL; 217 goto out; 218 } 219 if (sc != vsi->sc) { 220 ice_debug(hw, ICE_DBG_RDMA, "VSI is tied to unexpected device\n"); 221 ret = -EXDEV; 222 goto out; 223 } 224 225 for (i = 0; i < count; i++) { 226 struct ice_rdma_qset_params *qset; 227 228 qset = &res->qsets; 229 if (qset->vsi_id != peer->pf_vsi_num) { 230 ice_debug(hw, ICE_DBG_RDMA, "RDMA QSet invalid VSI requested %d %d\n", 231 qset->vsi_id, peer->pf_vsi_num); 232 ret = -EINVAL; 233 goto out; 234 } 235 max_rdmaqs[qset->tc]++; 236 qs_handle[i] = qset->qs_handle; 237 qset_teid[i] = qset->teid; 238 } 239 240 switch(res->res_type) { 241 case ICE_RDMA_QSET_ALLOC: 242 dcbx_cfg = &hw->port_info->qos_cfg.local_dcbx_cfg; 243 ena_tc = ice_dcb_get_tc_map(dcbx_cfg); 244 245 ice_debug(hw, ICE_DBG_RDMA, "%s:%d ena_tc=%x\n", __func__, __LINE__, ena_tc); 246 status = ice_cfg_vsi_rdma(hw->port_info, vsi->idx, ena_tc, 247 max_rdmaqs); 248 if (status) { 249 ice_debug(hw, ICE_DBG_RDMA, "Failed VSI RDMA qset config\n"); 250 ret = -EINVAL; 251 goto out; 252 } 253 254 for (i = 0; i < count; i++) { 255 struct ice_rdma_qset_params *qset; 256 257 qset = &res->qsets; 258 status = ice_ena_vsi_rdma_qset(hw->port_info, vsi->idx, 259 qset->tc, &qs_handle[i], 1, 260 &qset_teid[i]); 261 if (status) { 262 ice_debug(hw, ICE_DBG_RDMA, "Failed VSI RDMA qset enable\n"); 263 ret = -EINVAL; 264 goto out; 265 } 266 qset->teid = qset_teid[i]; 267 } 268 break; 269 case ICE_RDMA_QSET_FREE: 270 status = ice_dis_vsi_rdma_qset(hw->port_info, count, qset_teid, qs_handle); 271 if (status) 272 ret = -EINVAL; 273 break; 274 default: 275 ret = -EINVAL; 276 break; 277 } 278 279 out: 280 ice_free(hw, qs_handle); 281 ice_free(hw, qset_teid); 282 283 return ret; 284 } 285 286 /** 287 * ice_rdma_update_vsi_filter - configure vsi information 288 * when opening or closing rdma driver 289 * @peer: the RDMA peer client structure 290 * @enable: enable or disable the rdma filter 291 */ 292 static int 293 ice_rdma_update_vsi_filter(struct ice_rdma_peer *peer, 294 bool enable) 295 { 296 struct ice_softc *sc = ice_rdma_peer_to_sc(peer); 297 struct ice_vsi *vsi; 298 int ret; 299 300 vsi = &sc->pf_vsi; 301 if (!vsi) 302 return -EINVAL; 303 304 ret = ice_cfg_iwarp_fltr(&sc->hw, vsi->idx, enable); 305 if (ret) { 306 device_printf(sc->dev, "Failed to %sable iWARP filtering\n", 307 enable ? "en" : "dis"); 308 } else { 309 if (enable) 310 vsi->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN; 311 else 312 vsi->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN; 313 } 314 315 return ret; 316 } 317 318 /** 319 * ice_rdma_request_handler - handle requests incoming from RDMA driver 320 * @peer: the RDMA peer client structure 321 * @req: structure containing request 322 */ 323 static void 324 ice_rdma_request_handler(struct ice_rdma_peer *peer, 325 struct ice_rdma_request *req) 326 { 327 if (!req || !peer) { 328 log(LOG_WARNING, "%s: peer or req are not valid\n", __func__); 329 return; 330 } 331 332 switch(req->type) { 333 case ICE_RDMA_EVENT_RESET: 334 break; 335 case ICE_RDMA_EVENT_QSET_REGISTER: 336 ice_rdma_qset_register_request(peer, &req->res); 337 break; 338 case ICE_RDMA_EVENT_VSI_FILTER_UPDATE: 339 ice_rdma_update_vsi_filter(peer, req->enable_filter); 340 break; 341 default: 342 log(LOG_WARNING, "%s: Event %d not supported\n", __func__, req->type); 343 break; 344 } 345 } 346 347 /** 348 * ice_rdma_cp_qos_info - gather current QOS/DCB settings in LAN to pass 349 * to RDMA driver 350 * @hw: ice hw structure 351 * @dcbx_cfg: current DCB settings in ice driver 352 * @qos_info: destination of the DCB settings 353 */ 354 static void 355 ice_rdma_cp_qos_info(struct ice_hw *hw, struct ice_dcbx_cfg *dcbx_cfg, 356 struct ice_qos_params *qos_info) 357 { 358 u32 up2tc; 359 u8 j; 360 u8 num_tc = 0; 361 u8 val_tc = 0; /* number of TC for validation */ 362 u8 cnt_tc = 0; 363 364 /* setup qos_info fields with defaults */ 365 qos_info->num_apps = 0; 366 qos_info->num_tc = 1; 367 368 for (j = 0; j < ICE_TC_MAX_USER_PRIORITY; j++) 369 qos_info->up2tc[j] = 0; 370 371 qos_info->tc_info[0].rel_bw = 100; 372 for (j = 1; j < IEEE_8021QAZ_MAX_TCS; j++) 373 qos_info->tc_info[j].rel_bw = 0; 374 375 /* gather current values */ 376 up2tc = rd32(hw, PRTDCB_TUP2TC); 377 qos_info->num_apps = dcbx_cfg->numapps; 378 379 for (j = 0; j < ICE_MAX_TRAFFIC_CLASS; j++) { 380 num_tc |= BIT(dcbx_cfg->etscfg.prio_table[j]); 381 } 382 for (j = 0; j < ICE_MAX_TRAFFIC_CLASS; j++) { 383 if (num_tc & BIT(j)) { 384 cnt_tc++; 385 val_tc |= BIT(j); 386 } else { 387 break; 388 } 389 } 390 qos_info->num_tc = (val_tc == num_tc && num_tc != 0) ? cnt_tc : 1; 391 for (j = 0; j < ICE_TC_MAX_USER_PRIORITY; j++) 392 qos_info->up2tc[j] = (up2tc >> (j * 3)) & 0x7; 393 394 for (j = 0; j < IEEE_8021QAZ_MAX_TCS; j++) 395 qos_info->tc_info[j].rel_bw = dcbx_cfg->etscfg.tcbwtable[j]; 396 for (j = 0; j < qos_info->num_apps; j++) { 397 qos_info->apps[j].priority = dcbx_cfg->app[j].priority; 398 qos_info->apps[j].prot_id = dcbx_cfg->app[j].prot_id; 399 qos_info->apps[j].selector = dcbx_cfg->app[j].selector; 400 } 401 402 /* Gather DSCP-to-TC mapping and QoS/PFC mode */ 403 memcpy(qos_info->dscp_map, dcbx_cfg->dscp_map, sizeof(qos_info->dscp_map)); 404 qos_info->pfc_mode = dcbx_cfg->pfc_mode; 405 } 406 407 /** 408 * ice_rdma_check_version - Check that the provided RDMA version is compatible 409 * @info: the RDMA client information structure 410 * 411 * Verify that the client RDMA driver provided a version that is compatible 412 * with the driver interface. 413 */ 414 static int 415 ice_rdma_check_version(struct ice_rdma_info *info) 416 { 417 /* Make sure the MAJOR version matches */ 418 if (info->major_version != ICE_RDMA_MAJOR_VERSION) { 419 log(LOG_WARNING, "%s: the iRDMA driver requested version %d.%d.%d, but this driver only supports major version %d.x.x\n", 420 __func__, 421 info->major_version, info->minor_version, info->patch_version, 422 ICE_RDMA_MAJOR_VERSION); 423 return (ENOTSUP); 424 } 425 426 /* 427 * Make sure that the MINOR version is compatible. 428 * 429 * This means that the RDMA client driver version MUST not be greater 430 * than the version provided by the driver, as it would indicate that 431 * the RDMA client expects features which are not supported by the 432 * main driver. 433 */ 434 if (info->minor_version > ICE_RDMA_MINOR_VERSION) { 435 log(LOG_WARNING, "%s: the iRDMA driver requested version %d.%d.%d, but this driver only supports up to minor version %d.%d.x\n", 436 __func__, 437 info->major_version, info->minor_version, info->patch_version, 438 ICE_RDMA_MAJOR_VERSION, ICE_RDMA_MINOR_VERSION); 439 return (ENOTSUP); 440 } 441 442 /* 443 * Make sure that the PATCH version is compatible. 444 * 445 * This means that the RDMA client version MUST not be greater than 446 * the version provided by the driver, as it may indicate that the 447 * RDMA client expects certain backwards compatible bug fixes which 448 * are not implemented by this version of the main driver. 449 */ 450 if ((info->minor_version == ICE_RDMA_MINOR_VERSION) && 451 (info->patch_version > ICE_RDMA_PATCH_VERSION)) { 452 log(LOG_WARNING, "%s: the iRDMA driver requested version %d.%d.%d, but this driver only supports up to patch version %d.%d.%d\n", 453 __func__, 454 info->major_version, info->minor_version, info->patch_version, 455 ICE_RDMA_MAJOR_VERSION, ICE_RDMA_MINOR_VERSION, ICE_RDMA_PATCH_VERSION); 456 return (ENOTSUP); 457 } 458 459 /* Make sure that the kobject class is initialized */ 460 if (info->rdma_class == NULL) { 461 log(LOG_WARNING, "%s: the iRDMA driver did not specify a kobject interface\n", 462 __func__); 463 return (EINVAL); 464 } 465 466 return (0); 467 } 468 469 /** 470 * ice_rdma_register - Register an RDMA client driver 471 * @info: the RDMA client information structure 472 * 473 * Called by the RDMA client driver on load. Used to initialize the RDMA 474 * client driver interface and enable interop between the ice driver and the 475 * RDMA client driver. 476 * 477 * The RDMA client driver must provide the version number it expects, along 478 * with a pointer to a kobject class that extends the irdma_di_if class, and 479 * implements the irdma_if class interface. 480 */ 481 int 482 ice_rdma_register(struct ice_rdma_info *info) 483 { 484 struct ice_rdma_entry *entry; 485 struct ice_softc *sc; 486 int err = 0; 487 488 sx_xlock(&ice_rdma.mtx); 489 490 if (!ice_enable_irdma) { 491 log(LOG_INFO, "%s: The iRDMA driver interface has been disabled\n", __func__); 492 err = (ECONNREFUSED); 493 goto return_unlock; 494 } 495 496 if (ice_rdma.registered) { 497 log(LOG_WARNING, "%s: iRDMA driver already registered\n", __func__); 498 err = (EBUSY); 499 goto return_unlock; 500 } 501 502 /* Make sure the iRDMA version is compatible */ 503 err = ice_rdma_check_version(info); 504 if (err) 505 goto return_unlock; 506 507 log(LOG_INFO, "%s: iRDMA driver registered using version %d.%d.%d\n", 508 __func__, info->major_version, info->minor_version, info->patch_version); 509 510 ice_rdma.peer_class = info->rdma_class; 511 512 /* 513 * Initialize the kobject interface and notify the RDMA client of each 514 * existing PF interface. 515 */ 516 LIST_FOREACH(entry, &ice_rdma.peers, node) { 517 kobj_init((kobj_t)&entry->peer, ice_rdma.peer_class); 518 /* Gather DCB/QOS info into peer */ 519 sc = __containerof(entry, struct ice_softc, rdma_entry); 520 memset(&entry->peer.initial_qos_info, 0, sizeof(entry->peer.initial_qos_info)); 521 ice_rdma_cp_qos_info(&sc->hw, &sc->hw.port_info->qos_cfg.local_dcbx_cfg, 522 &entry->peer.initial_qos_info); 523 524 IRDMA_PROBE(&entry->peer); 525 if (entry->initiated) 526 IRDMA_OPEN(&entry->peer); 527 } 528 ice_rdma.registered = true; 529 530 return_unlock: 531 sx_xunlock(&ice_rdma.mtx); 532 533 return (err); 534 } 535 536 /** 537 * ice_rdma_unregister - Unregister an RDMA client driver 538 * 539 * Called by the RDMA client driver on unload. Used to de-initialize the RDMA 540 * client driver interface and shut down communication between the ice driver 541 * and the RDMA client driver. 542 */ 543 int 544 ice_rdma_unregister(void) 545 { 546 struct ice_rdma_entry *entry; 547 548 sx_xlock(&ice_rdma.mtx); 549 550 if (!ice_rdma.registered) { 551 log(LOG_WARNING, "%s: iRDMA driver was not previously registered\n", 552 __func__); 553 sx_xunlock(&ice_rdma.mtx); 554 return (ENOENT); 555 } 556 557 log(LOG_INFO, "%s: iRDMA driver unregistered\n", __func__); 558 ice_rdma.registered = false; 559 ice_rdma.peer_class = NULL; 560 561 /* 562 * Release the kobject interface for each of the existing PF 563 * interfaces. Note that we do not notify the client about removing 564 * each PF, as it is assumed that the client will have already cleaned 565 * up any associated resources when it is unregistered. 566 */ 567 LIST_FOREACH(entry, &ice_rdma.peers, node) 568 kobj_delete((kobj_t)&entry->peer, NULL); 569 570 sx_xunlock(&ice_rdma.mtx); 571 572 return (0); 573 } 574 575 /** 576 * ice_rdma_init - RDMA driver init routine 577 * 578 * Called during ice driver module initialization to setup the RDMA client 579 * interface mutex and RDMA peer structure list. 580 */ 581 void 582 ice_rdma_init(void) 583 { 584 LIST_INIT(&ice_rdma.peers); 585 sx_init_flags(&ice_rdma.mtx, "ice rdma interface", SX_DUPOK); 586 587 ice_rdma.registered = false; 588 ice_rdma.peer_class = NULL; 589 } 590 591 /** 592 * ice_rdma_exit - RDMA driver exit routine 593 * 594 * Called during ice driver module exit to shutdown the RDMA client interface 595 * mutex. 596 */ 597 void 598 ice_rdma_exit(void) 599 { 600 MPASS(LIST_EMPTY(&ice_rdma.peers)); 601 sx_destroy(&ice_rdma.mtx); 602 } 603 604 /** 605 * ice_rdma_pf_attach_locked - Prepare a PF for RDMA connections 606 * @sc: the ice driver softc 607 * 608 * Initialize a peer entry for this PF and add it to the RDMA interface list. 609 * Notify the client RDMA driver of a new PF device. 610 * 611 * @pre must be called while holding the ice_rdma mutex. 612 */ 613 static int 614 ice_rdma_pf_attach_locked(struct ice_softc *sc) 615 { 616 struct ice_rdma_entry *entry; 617 618 /* Do not attach the PF unless RDMA is supported */ 619 if (!ice_is_bit_set(sc->feat_cap, ICE_FEATURE_RDMA)) 620 return (0); 621 622 entry = &sc->rdma_entry; 623 if (entry->attached) { 624 device_printf(sc->dev, "iRDMA peer entry already exists\n"); 625 return (EEXIST); 626 } 627 628 entry->attached = true; 629 entry->peer.dev = sc->dev; 630 entry->peer.ifp = sc->ifp; 631 entry->peer.pf_id = sc->hw.pf_id; 632 entry->peer.pci_mem = sc->bar0.res; 633 entry->peer.pf_vsi_num = ice_get_hw_vsi_num(&sc->hw, sc->pf_vsi.idx); 634 if (sc->rdma_imap && sc->rdma_imap[0] != ICE_INVALID_RES_IDX && 635 sc->irdma_vectors > 0) { 636 entry->peer.msix.base = sc->rdma_imap[0]; 637 entry->peer.msix.count = sc->irdma_vectors; 638 } 639 640 /* Gather DCB/QOS info into peer */ 641 memset(&entry->peer.initial_qos_info, 0, sizeof(entry->peer.initial_qos_info)); 642 ice_rdma_cp_qos_info(&sc->hw, &sc->hw.port_info->qos_cfg.local_dcbx_cfg, 643 &entry->peer.initial_qos_info); 644 645 /* 646 * If the RDMA client driver has already registered, initialize the 647 * kobject and notify the client of a new PF 648 */ 649 if (ice_rdma.registered) { 650 kobj_init((kobj_t)&entry->peer, ice_rdma.peer_class); 651 IRDMA_PROBE(&entry->peer); 652 } 653 654 LIST_INSERT_HEAD(&ice_rdma.peers, entry, node); 655 656 ice_set_bit(ICE_FEATURE_RDMA, sc->feat_en); 657 658 return (0); 659 } 660 661 /** 662 * ice_rdma_pf_attach - Notify the RDMA client of a new PF 663 * @sc: the ice driver softc 664 * 665 * Called during PF attach to notify the RDMA client of a new PF. 666 */ 667 int 668 ice_rdma_pf_attach(struct ice_softc *sc) 669 { 670 int err; 671 672 sx_xlock(&ice_rdma.mtx); 673 err = ice_rdma_pf_attach_locked(sc); 674 sx_xunlock(&ice_rdma.mtx); 675 676 return (err); 677 } 678 679 /** 680 * ice_rdma_pf_detach_locked - Notify the RDMA client on PF detach 681 * @sc: the ice driver softc 682 * 683 * Notify the RDMA peer client driver of removal of a PF, and release any 684 * RDMA-specific resources associated with that PF. Remove the PF from the 685 * list of available RDMA entries. 686 * 687 * @pre must be called while holding the ice_rdma mutex. 688 */ 689 static void 690 ice_rdma_pf_detach_locked(struct ice_softc *sc) 691 { 692 struct ice_rdma_entry *entry; 693 694 /* No need to detach the PF if RDMA is not enabled */ 695 if (!ice_is_bit_set(sc->feat_en, ICE_FEATURE_RDMA)) 696 return; 697 698 entry = &sc->rdma_entry; 699 if (!entry->attached) { 700 device_printf(sc->dev, "iRDMA peer entry was not attached\n"); 701 return; 702 } 703 704 /* 705 * If the RDMA client driver is registered, notify the client that 706 * a PF has been removed, and release the kobject reference. 707 */ 708 if (ice_rdma.registered) { 709 IRDMA_REMOVE(&entry->peer); 710 kobj_delete((kobj_t)&entry->peer, NULL); 711 } 712 713 LIST_REMOVE(entry, node); 714 entry->attached = false; 715 716 ice_clear_bit(ICE_FEATURE_RDMA, sc->feat_en); 717 } 718 719 /** 720 * ice_rdma_pf_detach - Notify the RDMA client of a PF detaching 721 * @sc: the ice driver softc 722 * 723 * Take the ice_rdma mutex and then notify the RDMA client that a PF has been 724 * removed. 725 */ 726 void 727 ice_rdma_pf_detach(struct ice_softc *sc) 728 { 729 sx_xlock(&ice_rdma.mtx); 730 ice_rdma_pf_detach_locked(sc); 731 sx_xunlock(&ice_rdma.mtx); 732 } 733 734 /** 735 * ice_rdma_pf_init - Notify the RDMA client that a PF has initialized 736 * @sc: the ice driver softc 737 * 738 * Called by the ice driver when a PF has been initialized. Notifies the RDMA 739 * client that a PF is up and ready to operate. 740 */ 741 int 742 ice_rdma_pf_init(struct ice_softc *sc) 743 { 744 struct ice_rdma_peer *peer = &sc->rdma_entry.peer; 745 746 sx_xlock(&ice_rdma.mtx); 747 748 /* Update the MTU */ 749 peer->mtu = if_getmtu(sc->ifp); 750 sc->rdma_entry.initiated = true; 751 752 if (sc->rdma_entry.attached && ice_rdma.registered) { 753 sx_xunlock(&ice_rdma.mtx); 754 return IRDMA_OPEN(peer); 755 } 756 757 sx_xunlock(&ice_rdma.mtx); 758 759 return (0); 760 } 761 762 /** 763 * ice_rdma_pf_stop - Notify the RDMA client of a stopped PF device 764 * @sc: the ice driver softc 765 * 766 * Called by the ice driver when a PF is stopped. Notifies the RDMA client 767 * driver that the PF has stopped and is not ready to operate. 768 */ 769 int 770 ice_rdma_pf_stop(struct ice_softc *sc) 771 { 772 sx_xlock(&ice_rdma.mtx); 773 774 sc->rdma_entry.initiated = false; 775 if (sc->rdma_entry.attached && ice_rdma.registered) { 776 sx_xunlock(&ice_rdma.mtx); 777 return IRDMA_CLOSE(&sc->rdma_entry.peer); 778 } 779 780 sx_xunlock(&ice_rdma.mtx); 781 782 return (0); 783 } 784 785 /** 786 * ice_rdma_link_change - Notify RDMA client of a change in link status 787 * @sc: the ice driver softc 788 * @linkstate: the link status 789 * @baudrate: the link rate in bits per second 790 * 791 * Notify the RDMA client of a link status change, by sending it the new link 792 * state and baudrate. 793 * 794 * The link state is represented the same was as in the ifnet structure. It 795 * should be LINK_STATE_UNKNOWN, LINK_STATE_DOWN, or LINK_STATE_UP. 796 */ 797 void 798 ice_rdma_link_change(struct ice_softc *sc, int linkstate, uint64_t baudrate) 799 { 800 struct ice_rdma_peer *peer = &sc->rdma_entry.peer; 801 struct ice_rdma_event event; 802 803 memset(&event, 0, sizeof(struct ice_rdma_event)); 804 event.type = ICE_RDMA_EVENT_LINK_CHANGE; 805 event.linkstate = linkstate; 806 event.baudrate = baudrate; 807 808 sx_xlock(&ice_rdma.mtx); 809 810 if (sc->rdma_entry.attached && ice_rdma.registered) 811 IRDMA_EVENT_HANDLER(peer, &event); 812 813 sx_xunlock(&ice_rdma.mtx); 814 } 815 816 /** 817 * ice_rdma_notify_dcb_qos_change - notify RDMA driver to pause traffic 818 * @sc: the ice driver softc 819 * 820 * Notify the RDMA driver that QOS/DCB settings are about to change. 821 * Once the function return, all the QPs should be suspended. 822 */ 823 void 824 ice_rdma_notify_dcb_qos_change(struct ice_softc *sc) 825 { 826 struct ice_rdma_peer *peer = &sc->rdma_entry.peer; 827 struct ice_rdma_event event; 828 829 memset(&event, 0, sizeof(struct ice_rdma_event)); 830 event.type = ICE_RDMA_EVENT_TC_CHANGE; 831 /* pre-event */ 832 event.prep = true; 833 834 sx_xlock(&ice_rdma.mtx); 835 if (sc->rdma_entry.attached && ice_rdma.registered) 836 IRDMA_EVENT_HANDLER(peer, &event); 837 sx_xunlock(&ice_rdma.mtx); 838 } 839 840 /** 841 * ice_rdma_dcb_qos_update - pass the changed dcb settings to RDMA driver 842 * @sc: the ice driver softc 843 * @pi: the port info structure 844 * 845 * Pass the changed DCB settings to RDMA traffic. This function should be 846 * called only after ice_rdma_notify_dcb_qos_change has been called and 847 * returned before. After the function returns, all the RDMA traffic 848 * should be resumed. 849 */ 850 void 851 ice_rdma_dcb_qos_update(struct ice_softc *sc, struct ice_port_info *pi) 852 { 853 struct ice_rdma_peer *peer = &sc->rdma_entry.peer; 854 struct ice_rdma_event event; 855 856 memset(&event, 0, sizeof(struct ice_rdma_event)); 857 event.type = ICE_RDMA_EVENT_TC_CHANGE; 858 /* post-event */ 859 event.prep = false; 860 861 /* gather current configuration */ 862 ice_rdma_cp_qos_info(&sc->hw, &pi->qos_cfg.local_dcbx_cfg, &event.port_qos); 863 sx_xlock(&ice_rdma.mtx); 864 if (sc->rdma_entry.attached && ice_rdma.registered) 865 IRDMA_EVENT_HANDLER(peer, &event); 866 sx_xunlock(&ice_rdma.mtx); 867 } 868