18a13362dSEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */ 2015f8cc5SEric Joyner /* Copyright (c) 2024, Intel Corporation 38a13362dSEric Joyner * All rights reserved. 48a13362dSEric Joyner * 58a13362dSEric Joyner * Redistribution and use in source and binary forms, with or without 68a13362dSEric Joyner * modification, are permitted provided that the following conditions are met: 78a13362dSEric Joyner * 88a13362dSEric Joyner * 1. Redistributions of source code must retain the above copyright notice, 98a13362dSEric Joyner * this list of conditions and the following disclaimer. 108a13362dSEric Joyner * 118a13362dSEric Joyner * 2. Redistributions in binary form must reproduce the above copyright 128a13362dSEric Joyner * notice, this list of conditions and the following disclaimer in the 138a13362dSEric Joyner * documentation and/or other materials provided with the distribution. 148a13362dSEric Joyner * 158a13362dSEric Joyner * 3. Neither the name of the Intel Corporation nor the names of its 168a13362dSEric Joyner * contributors may be used to endorse or promote products derived from 178a13362dSEric Joyner * this software without specific prior written permission. 188a13362dSEric Joyner * 198a13362dSEric Joyner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 208a13362dSEric Joyner * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 218a13362dSEric Joyner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 228a13362dSEric Joyner * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 238a13362dSEric Joyner * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 248a13362dSEric Joyner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 258a13362dSEric Joyner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 268a13362dSEric Joyner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 278a13362dSEric Joyner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 288a13362dSEric Joyner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 298a13362dSEric Joyner * POSSIBILITY OF SUCH DAMAGE. 308a13362dSEric Joyner */ 318a13362dSEric Joyner 328a13362dSEric Joyner /** 338a13362dSEric Joyner * @file ice_rdma.c 348a13362dSEric Joyner * @brief RDMA client driver interface 358a13362dSEric Joyner * 368a13362dSEric Joyner * Functions to interface with the RDMA client driver, for enabling RMDA 378a13362dSEric Joyner * functionality for the ice driver. 388a13362dSEric Joyner * 398a13362dSEric Joyner * The RDMA client interface is based on a simple kobject interface which is 408a13362dSEric Joyner * defined by the rmda_if.m and irdma_di_if.m interfaces. 418a13362dSEric Joyner * 428a13362dSEric Joyner * The ice device driver provides the rmda_di_if.m interface methods, while 438a13362dSEric Joyner * the client RDMA driver provides the irdma_if.m interface methods as an 448a13362dSEric Joyner * extension ontop of the irdma_di_if kobject. 458a13362dSEric Joyner * 468a13362dSEric Joyner * The initial connection between drivers is done via the RDMA client driver 478a13362dSEric Joyner * calling ice_rdma_register. 488a13362dSEric Joyner */ 498a13362dSEric Joyner 508a13362dSEric Joyner #include "ice_iflib.h" 518a13362dSEric Joyner #include "ice_rdma_internal.h" 528a13362dSEric Joyner 538a13362dSEric Joyner #include "irdma_if.h" 548a13362dSEric Joyner #include "irdma_di_if.h" 558a13362dSEric Joyner 568a13362dSEric Joyner /** 578a13362dSEric Joyner * @var ice_rdma 588a13362dSEric Joyner * @brief global RDMA driver state 598a13362dSEric Joyner * 608a13362dSEric Joyner * Contains global state the driver uses to connect to a client RDMA interface 618a13362dSEric Joyner * driver. 628a13362dSEric Joyner */ 638a13362dSEric Joyner static struct ice_rdma_state ice_rdma; 648a13362dSEric Joyner 658a13362dSEric Joyner /* 668a13362dSEric Joyner * Helper function prototypes 678a13362dSEric Joyner */ 688a13362dSEric Joyner static int ice_rdma_pf_attach_locked(struct ice_softc *sc); 698a13362dSEric Joyner static void ice_rdma_pf_detach_locked(struct ice_softc *sc); 708a13362dSEric Joyner static int ice_rdma_check_version(struct ice_rdma_info *info); 718a13362dSEric Joyner static void ice_rdma_cp_qos_info(struct ice_hw *hw, 728a13362dSEric Joyner struct ice_dcbx_cfg *dcbx_cfg, 738a13362dSEric Joyner struct ice_qos_params *qos_info); 748a13362dSEric Joyner 758a13362dSEric Joyner /* 768a13362dSEric Joyner * RDMA Device Interface prototypes 778a13362dSEric Joyner */ 788a13362dSEric Joyner static int ice_rdma_pf_reset(struct ice_rdma_peer *peer); 798a13362dSEric Joyner static int ice_rdma_pf_msix_init(struct ice_rdma_peer *peer, 808a13362dSEric Joyner struct ice_rdma_msix_mapping *msix_info); 818a13362dSEric Joyner static int ice_rdma_qset_register_request(struct ice_rdma_peer *peer, 828a13362dSEric Joyner struct ice_rdma_qset_update *res); 838a13362dSEric Joyner static int ice_rdma_update_vsi_filter(struct ice_rdma_peer *peer_dev, 848a13362dSEric Joyner bool enable); 858a13362dSEric Joyner static void ice_rdma_request_handler(struct ice_rdma_peer *peer, 868a13362dSEric Joyner struct ice_rdma_request *req); 878a13362dSEric Joyner 888a13362dSEric Joyner 898a13362dSEric Joyner /** 908a13362dSEric Joyner * @var ice_rdma_di_methods 918a13362dSEric Joyner * @brief RDMA driver interface methods 928a13362dSEric Joyner * 938a13362dSEric Joyner * Kobject methods implementing the driver-side interface for the RDMA peer 948a13362dSEric Joyner * clients. This method table contains the operations which the client can 958a13362dSEric Joyner * request from the driver. 968a13362dSEric Joyner * 978a13362dSEric Joyner * The client driver will then extend this kobject class with methods that the 988a13362dSEric Joyner * driver can request from the client. 998a13362dSEric Joyner */ 1008a13362dSEric Joyner static kobj_method_t ice_rdma_di_methods[] = { 1018a13362dSEric Joyner KOBJMETHOD(irdma_di_reset, ice_rdma_pf_reset), 1028a13362dSEric Joyner KOBJMETHOD(irdma_di_msix_init, ice_rdma_pf_msix_init), 1038a13362dSEric Joyner KOBJMETHOD(irdma_di_qset_register_request, ice_rdma_qset_register_request), 1048a13362dSEric Joyner KOBJMETHOD(irdma_di_vsi_filter_update, ice_rdma_update_vsi_filter), 1058a13362dSEric Joyner KOBJMETHOD(irdma_di_req_handler, ice_rdma_request_handler), 1068a13362dSEric Joyner KOBJMETHOD_END 1078a13362dSEric Joyner }; 1088a13362dSEric Joyner 1098a13362dSEric Joyner /* Define ice_rdma_di class which will be extended by the iRDMA driver */ 1108a13362dSEric Joyner DEFINE_CLASS_0(ice_rdma_di, ice_rdma_di_class, ice_rdma_di_methods, sizeof(struct ice_rdma_peer)); 1118a13362dSEric Joyner 1128a13362dSEric Joyner /** 1138a13362dSEric Joyner * ice_rdma_pf_reset - RDMA client interface requested a reset 1148a13362dSEric Joyner * @peer: the RDMA peer client structure 1158a13362dSEric Joyner * 1168a13362dSEric Joyner * Implements IRDMA_DI_RESET, called by the RDMA client driver to request 1178a13362dSEric Joyner * a reset of an ice driver device. 1189c30461dSEric Joyner * @return 0 on success 1198a13362dSEric Joyner */ 1208a13362dSEric Joyner static int 1218a13362dSEric Joyner ice_rdma_pf_reset(struct ice_rdma_peer *peer) 1228a13362dSEric Joyner { 1238a13362dSEric Joyner struct ice_softc *sc = ice_rdma_peer_to_sc(peer); 1248a13362dSEric Joyner 12501fbb869SBartosz Sobczak /* Tell the base driver that RDMA is requesting a PFR */ 12601fbb869SBartosz Sobczak ice_set_state(&sc->state, ICE_STATE_RESET_PFR_REQ); 12701fbb869SBartosz Sobczak 12801fbb869SBartosz Sobczak /* XXX: Base driver will notify RDMA when it's done */ 1298a13362dSEric Joyner 1308a13362dSEric Joyner return (0); 1318a13362dSEric Joyner } 1328a13362dSEric Joyner 1338a13362dSEric Joyner /** 1348a13362dSEric Joyner * ice_rdma_pf_msix_init - RDMA client interface request MSI-X initialization 1358a13362dSEric Joyner * @peer: the RDMA peer client structure 1368a13362dSEric Joyner * @msix_info: requested MSI-X mapping 1378a13362dSEric Joyner * 1388a13362dSEric Joyner * Implements IRDMA_DI_MSIX_INIT, called by the RDMA client driver to 1398a13362dSEric Joyner * initialize the MSI-X resources required for RDMA functionality. 1409c30461dSEric Joyner * @returns ENOSYS 1418a13362dSEric Joyner */ 1428a13362dSEric Joyner static int 1438a13362dSEric Joyner ice_rdma_pf_msix_init(struct ice_rdma_peer *peer, 1448a13362dSEric Joyner struct ice_rdma_msix_mapping __unused *msix_info) 1458a13362dSEric Joyner { 1468a13362dSEric Joyner struct ice_softc *sc = ice_rdma_peer_to_sc(peer); 1478a13362dSEric Joyner 1488a13362dSEric Joyner MPASS(msix_info != NULL); 1498a13362dSEric Joyner 1508a13362dSEric Joyner device_printf(sc->dev, "%s: iRDMA MSI-X initialization request is not yet implemented\n", __func__); 1518a13362dSEric Joyner 1528a13362dSEric Joyner /* TODO: implement MSI-X initialization for RDMA */ 1538a13362dSEric Joyner return (ENOSYS); 1548a13362dSEric Joyner } 1558a13362dSEric Joyner 1568a13362dSEric Joyner /** 1578a13362dSEric Joyner * ice_rdma_register_request - RDMA client interface request qset 1588a13362dSEric Joyner * registration or unregistration 1598a13362dSEric Joyner * @peer: the RDMA peer client structure 1608a13362dSEric Joyner * @res: resources to be registered or unregistered 1619c30461dSEric Joyner * @returns 0 on success, EINVAL on argument issues, ENOMEM on memory 1629c30461dSEric Joyner * allocation failure, EXDEV on vsi device mismatch 1638a13362dSEric Joyner */ 1648a13362dSEric Joyner static int 1658a13362dSEric Joyner ice_rdma_qset_register_request(struct ice_rdma_peer *peer, struct ice_rdma_qset_update *res) 1668a13362dSEric Joyner { 1678a13362dSEric Joyner struct ice_softc *sc = ice_rdma_peer_to_sc(peer); 1688a13362dSEric Joyner struct ice_vsi *vsi = NULL; 1698a13362dSEric Joyner struct ice_dcbx_cfg *dcbx_cfg; 1708a13362dSEric Joyner struct ice_hw *hw = &sc->hw; 171*f2635e84SEric Joyner int status; 1728a13362dSEric Joyner int count, i, ret = 0; 1738a13362dSEric Joyner uint32_t *qset_teid; 1748a13362dSEric Joyner uint16_t *qs_handle; 1758a13362dSEric Joyner uint16_t max_rdmaqs[ICE_MAX_TRAFFIC_CLASS]; 1768a13362dSEric Joyner uint16_t vsi_id; 1778a13362dSEric Joyner uint8_t ena_tc = 0; 1788a13362dSEric Joyner 1798a13362dSEric Joyner if (!res) 1808a13362dSEric Joyner return -EINVAL; 1818a13362dSEric Joyner 1828a13362dSEric Joyner if (res->cnt_req > ICE_MAX_TXQ_PER_TXQG) 1838a13362dSEric Joyner return -EINVAL; 1848a13362dSEric Joyner 1858a13362dSEric Joyner switch(res->res_type) { 1868a13362dSEric Joyner case ICE_RDMA_QSET_ALLOC: 1878a13362dSEric Joyner count = res->cnt_req; 1888a13362dSEric Joyner vsi_id = peer->pf_vsi_num; 1898a13362dSEric Joyner break; 1908a13362dSEric Joyner case ICE_RDMA_QSET_FREE: 1918a13362dSEric Joyner count = res->res_allocated; 1928a13362dSEric Joyner vsi_id = res->qsets.vsi_id; 1938a13362dSEric Joyner break; 1948a13362dSEric Joyner default: 1958a13362dSEric Joyner return -EINVAL; 1968a13362dSEric Joyner } 1978a13362dSEric Joyner qset_teid = (uint32_t *)ice_calloc(hw, count, sizeof(*qset_teid)); 1988a13362dSEric Joyner if (!qset_teid) 1998a13362dSEric Joyner return -ENOMEM; 2008a13362dSEric Joyner 2018a13362dSEric Joyner qs_handle = (uint16_t *)ice_calloc(hw, count, sizeof(*qs_handle)); 2028a13362dSEric Joyner if (!qs_handle) { 2038a13362dSEric Joyner ice_free(hw, qset_teid); 2048a13362dSEric Joyner return -ENOMEM; 2058a13362dSEric Joyner } 2068a13362dSEric Joyner 2078a13362dSEric Joyner ice_for_each_traffic_class(i) 2088a13362dSEric Joyner max_rdmaqs[i] = 0; 2098a13362dSEric Joyner for (i = 0; i < sc->num_available_vsi; i++) { 2108a13362dSEric Joyner if (sc->all_vsi[i] && 2118a13362dSEric Joyner ice_get_hw_vsi_num(hw, sc->all_vsi[i]->idx) == vsi_id) { 2128a13362dSEric Joyner vsi = sc->all_vsi[i]; 2138a13362dSEric Joyner break; 2148a13362dSEric Joyner } 2158a13362dSEric Joyner } 2168a13362dSEric Joyner 2178a13362dSEric Joyner if (!vsi) { 2188a13362dSEric Joyner ice_debug(hw, ICE_DBG_RDMA, "RDMA QSet invalid VSI\n"); 2198a13362dSEric Joyner ret = -EINVAL; 2208a13362dSEric Joyner goto out; 2218a13362dSEric Joyner } 2228a13362dSEric Joyner if (sc != vsi->sc) { 2238a13362dSEric Joyner ice_debug(hw, ICE_DBG_RDMA, "VSI is tied to unexpected device\n"); 2248a13362dSEric Joyner ret = -EXDEV; 2258a13362dSEric Joyner goto out; 2268a13362dSEric Joyner } 2278a13362dSEric Joyner 2288a13362dSEric Joyner for (i = 0; i < count; i++) { 2298a13362dSEric Joyner struct ice_rdma_qset_params *qset; 2308a13362dSEric Joyner 2318a13362dSEric Joyner qset = &res->qsets; 2328a13362dSEric Joyner if (qset->vsi_id != peer->pf_vsi_num) { 2338a13362dSEric Joyner ice_debug(hw, ICE_DBG_RDMA, "RDMA QSet invalid VSI requested %d %d\n", 2348a13362dSEric Joyner qset->vsi_id, peer->pf_vsi_num); 2358a13362dSEric Joyner ret = -EINVAL; 2368a13362dSEric Joyner goto out; 2378a13362dSEric Joyner } 2388a13362dSEric Joyner max_rdmaqs[qset->tc]++; 2398a13362dSEric Joyner qs_handle[i] = qset->qs_handle; 2408a13362dSEric Joyner qset_teid[i] = qset->teid; 2418a13362dSEric Joyner } 2428a13362dSEric Joyner 2438a13362dSEric Joyner switch(res->res_type) { 2448a13362dSEric Joyner case ICE_RDMA_QSET_ALLOC: 2458a13362dSEric Joyner dcbx_cfg = &hw->port_info->qos_cfg.local_dcbx_cfg; 2468923de59SPiotr Kubaj ena_tc = ice_dcb_get_tc_map(dcbx_cfg); 2478a13362dSEric Joyner 2488a13362dSEric Joyner ice_debug(hw, ICE_DBG_RDMA, "%s:%d ena_tc=%x\n", __func__, __LINE__, ena_tc); 2498a13362dSEric Joyner status = ice_cfg_vsi_rdma(hw->port_info, vsi->idx, ena_tc, 2508a13362dSEric Joyner max_rdmaqs); 2518a13362dSEric Joyner if (status) { 2528a13362dSEric Joyner ice_debug(hw, ICE_DBG_RDMA, "Failed VSI RDMA qset config\n"); 2538a13362dSEric Joyner ret = -EINVAL; 2548a13362dSEric Joyner goto out; 2558a13362dSEric Joyner } 2568a13362dSEric Joyner 2578a13362dSEric Joyner for (i = 0; i < count; i++) { 2588a13362dSEric Joyner struct ice_rdma_qset_params *qset; 2598a13362dSEric Joyner 2608a13362dSEric Joyner qset = &res->qsets; 2618a13362dSEric Joyner status = ice_ena_vsi_rdma_qset(hw->port_info, vsi->idx, 2628a13362dSEric Joyner qset->tc, &qs_handle[i], 1, 2638a13362dSEric Joyner &qset_teid[i]); 2648a13362dSEric Joyner if (status) { 2658a13362dSEric Joyner ice_debug(hw, ICE_DBG_RDMA, "Failed VSI RDMA qset enable\n"); 2668a13362dSEric Joyner ret = -EINVAL; 2678a13362dSEric Joyner goto out; 2688a13362dSEric Joyner } 2698a13362dSEric Joyner qset->teid = qset_teid[i]; 2708a13362dSEric Joyner } 2718a13362dSEric Joyner break; 2728a13362dSEric Joyner case ICE_RDMA_QSET_FREE: 2738a13362dSEric Joyner status = ice_dis_vsi_rdma_qset(hw->port_info, count, qset_teid, qs_handle); 2748a13362dSEric Joyner if (status) 2758a13362dSEric Joyner ret = -EINVAL; 2768a13362dSEric Joyner break; 2778a13362dSEric Joyner default: 2788a13362dSEric Joyner ret = -EINVAL; 2798a13362dSEric Joyner break; 2808a13362dSEric Joyner } 2818a13362dSEric Joyner 2828a13362dSEric Joyner out: 2838a13362dSEric Joyner ice_free(hw, qs_handle); 2848a13362dSEric Joyner ice_free(hw, qset_teid); 2858a13362dSEric Joyner 2868a13362dSEric Joyner return ret; 2878a13362dSEric Joyner } 2888a13362dSEric Joyner 2898a13362dSEric Joyner /** 2908a13362dSEric Joyner * ice_rdma_update_vsi_filter - configure vsi information 2918a13362dSEric Joyner * when opening or closing rdma driver 2928a13362dSEric Joyner * @peer: the RDMA peer client structure 2938a13362dSEric Joyner * @enable: enable or disable the rdma filter 2949c30461dSEric Joyner * @return 0 on success, EINVAL on wrong vsi 2958a13362dSEric Joyner */ 2968a13362dSEric Joyner static int 2978a13362dSEric Joyner ice_rdma_update_vsi_filter(struct ice_rdma_peer *peer, 2988a13362dSEric Joyner bool enable) 2998a13362dSEric Joyner { 3008a13362dSEric Joyner struct ice_softc *sc = ice_rdma_peer_to_sc(peer); 3018a13362dSEric Joyner struct ice_vsi *vsi; 3028a13362dSEric Joyner int ret; 3038a13362dSEric Joyner 3048a13362dSEric Joyner vsi = &sc->pf_vsi; 3058a13362dSEric Joyner if (!vsi) 3068a13362dSEric Joyner return -EINVAL; 3078a13362dSEric Joyner 3088a13362dSEric Joyner ret = ice_cfg_iwarp_fltr(&sc->hw, vsi->idx, enable); 3098a13362dSEric Joyner if (ret) { 3108a13362dSEric Joyner device_printf(sc->dev, "Failed to %sable iWARP filtering\n", 3118a13362dSEric Joyner enable ? "en" : "dis"); 3128a13362dSEric Joyner } else { 3138a13362dSEric Joyner if (enable) 3148a13362dSEric Joyner vsi->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN; 3158a13362dSEric Joyner else 3168a13362dSEric Joyner vsi->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN; 3178a13362dSEric Joyner } 3188a13362dSEric Joyner 3198a13362dSEric Joyner return ret; 3208a13362dSEric Joyner } 3218a13362dSEric Joyner 3228a13362dSEric Joyner /** 3238a13362dSEric Joyner * ice_rdma_request_handler - handle requests incoming from RDMA driver 3248a13362dSEric Joyner * @peer: the RDMA peer client structure 3258a13362dSEric Joyner * @req: structure containing request 3268a13362dSEric Joyner */ 3278a13362dSEric Joyner static void 3288a13362dSEric Joyner ice_rdma_request_handler(struct ice_rdma_peer *peer, 3298a13362dSEric Joyner struct ice_rdma_request *req) 3308a13362dSEric Joyner { 3318a13362dSEric Joyner if (!req || !peer) { 3328a13362dSEric Joyner log(LOG_WARNING, "%s: peer or req are not valid\n", __func__); 3338a13362dSEric Joyner return; 3348a13362dSEric Joyner } 3358a13362dSEric Joyner 3368a13362dSEric Joyner switch(req->type) { 3378a13362dSEric Joyner case ICE_RDMA_EVENT_RESET: 33801fbb869SBartosz Sobczak ice_rdma_pf_reset(peer); 3398a13362dSEric Joyner break; 3408a13362dSEric Joyner case ICE_RDMA_EVENT_QSET_REGISTER: 3418a13362dSEric Joyner ice_rdma_qset_register_request(peer, &req->res); 3428a13362dSEric Joyner break; 3438a13362dSEric Joyner case ICE_RDMA_EVENT_VSI_FILTER_UPDATE: 3448a13362dSEric Joyner ice_rdma_update_vsi_filter(peer, req->enable_filter); 3458a13362dSEric Joyner break; 3468a13362dSEric Joyner default: 3478a13362dSEric Joyner log(LOG_WARNING, "%s: Event %d not supported\n", __func__, req->type); 3488a13362dSEric Joyner break; 3498a13362dSEric Joyner } 3508a13362dSEric Joyner } 3518a13362dSEric Joyner 3528a13362dSEric Joyner /** 3538a13362dSEric Joyner * ice_rdma_cp_qos_info - gather current QOS/DCB settings in LAN to pass 3548a13362dSEric Joyner * to RDMA driver 3558a13362dSEric Joyner * @hw: ice hw structure 3568a13362dSEric Joyner * @dcbx_cfg: current DCB settings in ice driver 3578a13362dSEric Joyner * @qos_info: destination of the DCB settings 3588a13362dSEric Joyner */ 3598a13362dSEric Joyner static void 3608a13362dSEric Joyner ice_rdma_cp_qos_info(struct ice_hw *hw, struct ice_dcbx_cfg *dcbx_cfg, 3618a13362dSEric Joyner struct ice_qos_params *qos_info) 3628a13362dSEric Joyner { 3638a13362dSEric Joyner u32 up2tc; 3648a13362dSEric Joyner u8 j; 3658a13362dSEric Joyner u8 num_tc = 0; 3668a13362dSEric Joyner u8 val_tc = 0; /* number of TC for validation */ 3678a13362dSEric Joyner u8 cnt_tc = 0; 3688a13362dSEric Joyner 3698a13362dSEric Joyner /* setup qos_info fields with defaults */ 3708a13362dSEric Joyner qos_info->num_apps = 0; 3718a13362dSEric Joyner qos_info->num_tc = 1; 3728a13362dSEric Joyner 3738a13362dSEric Joyner for (j = 0; j < ICE_TC_MAX_USER_PRIORITY; j++) 3748a13362dSEric Joyner qos_info->up2tc[j] = 0; 3758a13362dSEric Joyner 3768a13362dSEric Joyner qos_info->tc_info[0].rel_bw = 100; 3778a13362dSEric Joyner for (j = 1; j < IEEE_8021QAZ_MAX_TCS; j++) 3788a13362dSEric Joyner qos_info->tc_info[j].rel_bw = 0; 3798a13362dSEric Joyner 3808a13362dSEric Joyner /* gather current values */ 3818a13362dSEric Joyner up2tc = rd32(hw, PRTDCB_TUP2TC); 3828a13362dSEric Joyner qos_info->num_apps = dcbx_cfg->numapps; 3838a13362dSEric Joyner 3848a13362dSEric Joyner for (j = 0; j < ICE_MAX_TRAFFIC_CLASS; j++) { 3858a13362dSEric Joyner num_tc |= BIT(dcbx_cfg->etscfg.prio_table[j]); 3868a13362dSEric Joyner } 3878a13362dSEric Joyner for (j = 0; j < ICE_MAX_TRAFFIC_CLASS; j++) { 3888a13362dSEric Joyner if (num_tc & BIT(j)) { 3898a13362dSEric Joyner cnt_tc++; 3908a13362dSEric Joyner val_tc |= BIT(j); 3918a13362dSEric Joyner } else { 3928a13362dSEric Joyner break; 3938a13362dSEric Joyner } 3948a13362dSEric Joyner } 3958a13362dSEric Joyner qos_info->num_tc = (val_tc == num_tc && num_tc != 0) ? cnt_tc : 1; 3968a13362dSEric Joyner for (j = 0; j < ICE_TC_MAX_USER_PRIORITY; j++) 3978a13362dSEric Joyner qos_info->up2tc[j] = (up2tc >> (j * 3)) & 0x7; 3988a13362dSEric Joyner 3998a13362dSEric Joyner for (j = 0; j < IEEE_8021QAZ_MAX_TCS; j++) 4008a13362dSEric Joyner qos_info->tc_info[j].rel_bw = dcbx_cfg->etscfg.tcbwtable[j]; 4018a13362dSEric Joyner for (j = 0; j < qos_info->num_apps; j++) { 4028a13362dSEric Joyner qos_info->apps[j].priority = dcbx_cfg->app[j].priority; 4038a13362dSEric Joyner qos_info->apps[j].prot_id = dcbx_cfg->app[j].prot_id; 4048a13362dSEric Joyner qos_info->apps[j].selector = dcbx_cfg->app[j].selector; 4058a13362dSEric Joyner } 4068923de59SPiotr Kubaj 4078923de59SPiotr Kubaj /* Gather DSCP-to-TC mapping and QoS/PFC mode */ 4088923de59SPiotr Kubaj memcpy(qos_info->dscp_map, dcbx_cfg->dscp_map, sizeof(qos_info->dscp_map)); 4098923de59SPiotr Kubaj qos_info->pfc_mode = dcbx_cfg->pfc_mode; 4108a13362dSEric Joyner } 4118a13362dSEric Joyner 4128a13362dSEric Joyner /** 4138a13362dSEric Joyner * ice_rdma_check_version - Check that the provided RDMA version is compatible 4148a13362dSEric Joyner * @info: the RDMA client information structure 4158a13362dSEric Joyner * 4168a13362dSEric Joyner * Verify that the client RDMA driver provided a version that is compatible 4178a13362dSEric Joyner * with the driver interface. 4189c30461dSEric Joyner * @return 0 on success, ENOTSUP when LAN-RDMA interface version doesn't match, 4199c30461dSEric Joyner * EINVAL on kobject interface fail. 4208a13362dSEric Joyner */ 4218a13362dSEric Joyner static int 4228a13362dSEric Joyner ice_rdma_check_version(struct ice_rdma_info *info) 4238a13362dSEric Joyner { 4248a13362dSEric Joyner /* Make sure the MAJOR version matches */ 4258a13362dSEric Joyner if (info->major_version != ICE_RDMA_MAJOR_VERSION) { 4268a13362dSEric Joyner log(LOG_WARNING, "%s: the iRDMA driver requested version %d.%d.%d, but this driver only supports major version %d.x.x\n", 4278a13362dSEric Joyner __func__, 4288a13362dSEric Joyner info->major_version, info->minor_version, info->patch_version, 4298a13362dSEric Joyner ICE_RDMA_MAJOR_VERSION); 4308a13362dSEric Joyner return (ENOTSUP); 4318a13362dSEric Joyner } 4328a13362dSEric Joyner 4338a13362dSEric Joyner /* 4348a13362dSEric Joyner * Make sure that the MINOR version is compatible. 4358a13362dSEric Joyner * 4368a13362dSEric Joyner * This means that the RDMA client driver version MUST not be greater 4378a13362dSEric Joyner * than the version provided by the driver, as it would indicate that 4388a13362dSEric Joyner * the RDMA client expects features which are not supported by the 4398a13362dSEric Joyner * main driver. 4408a13362dSEric Joyner */ 4418a13362dSEric Joyner if (info->minor_version > ICE_RDMA_MINOR_VERSION) { 4428a13362dSEric Joyner 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", 4438a13362dSEric Joyner __func__, 4448a13362dSEric Joyner info->major_version, info->minor_version, info->patch_version, 4458a13362dSEric Joyner ICE_RDMA_MAJOR_VERSION, ICE_RDMA_MINOR_VERSION); 4468a13362dSEric Joyner return (ENOTSUP); 4478a13362dSEric Joyner } 4488a13362dSEric Joyner 4498a13362dSEric Joyner /* 4508a13362dSEric Joyner * Make sure that the PATCH version is compatible. 4518a13362dSEric Joyner * 4528a13362dSEric Joyner * This means that the RDMA client version MUST not be greater than 4538a13362dSEric Joyner * the version provided by the driver, as it may indicate that the 4548a13362dSEric Joyner * RDMA client expects certain backwards compatible bug fixes which 4558a13362dSEric Joyner * are not implemented by this version of the main driver. 4568a13362dSEric Joyner */ 4578a13362dSEric Joyner if ((info->minor_version == ICE_RDMA_MINOR_VERSION) && 4588a13362dSEric Joyner (info->patch_version > ICE_RDMA_PATCH_VERSION)) { 4598a13362dSEric Joyner 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", 4608a13362dSEric Joyner __func__, 4618a13362dSEric Joyner info->major_version, info->minor_version, info->patch_version, 4628a13362dSEric Joyner ICE_RDMA_MAJOR_VERSION, ICE_RDMA_MINOR_VERSION, ICE_RDMA_PATCH_VERSION); 4638a13362dSEric Joyner return (ENOTSUP); 4648a13362dSEric Joyner } 4658a13362dSEric Joyner 4668a13362dSEric Joyner /* Make sure that the kobject class is initialized */ 4678a13362dSEric Joyner if (info->rdma_class == NULL) { 4688a13362dSEric Joyner log(LOG_WARNING, "%s: the iRDMA driver did not specify a kobject interface\n", 4698a13362dSEric Joyner __func__); 4708a13362dSEric Joyner return (EINVAL); 4718a13362dSEric Joyner } 4728a13362dSEric Joyner 4738a13362dSEric Joyner return (0); 4748a13362dSEric Joyner } 4758a13362dSEric Joyner 4768a13362dSEric Joyner /** 4778a13362dSEric Joyner * ice_rdma_register - Register an RDMA client driver 4788a13362dSEric Joyner * @info: the RDMA client information structure 4798a13362dSEric Joyner * 4808a13362dSEric Joyner * Called by the RDMA client driver on load. Used to initialize the RDMA 4818a13362dSEric Joyner * client driver interface and enable interop between the ice driver and the 4828a13362dSEric Joyner * RDMA client driver. 4838a13362dSEric Joyner * 4848a13362dSEric Joyner * The RDMA client driver must provide the version number it expects, along 4858a13362dSEric Joyner * with a pointer to a kobject class that extends the irdma_di_if class, and 4868a13362dSEric Joyner * implements the irdma_if class interface. 4879c30461dSEric Joyner * @return 0 on success, ECONNREFUSED when RDMA is turned off, EBUSY when irdma 4889c30461dSEric Joyner * already registered, ENOTSUP when LAN-RDMA interface version doesn't match, 4899c30461dSEric Joyner * EINVAL on kobject interface fail. 4908a13362dSEric Joyner */ 4918a13362dSEric Joyner int 4928a13362dSEric Joyner ice_rdma_register(struct ice_rdma_info *info) 4938a13362dSEric Joyner { 4948a13362dSEric Joyner struct ice_rdma_entry *entry; 4958923de59SPiotr Kubaj struct ice_softc *sc; 4968a13362dSEric Joyner int err = 0; 4978a13362dSEric Joyner 4988a13362dSEric Joyner sx_xlock(&ice_rdma.mtx); 4998a13362dSEric Joyner 5008a13362dSEric Joyner if (!ice_enable_irdma) { 5018a13362dSEric Joyner log(LOG_INFO, "%s: The iRDMA driver interface has been disabled\n", __func__); 5028a13362dSEric Joyner err = (ECONNREFUSED); 5038a13362dSEric Joyner goto return_unlock; 5048a13362dSEric Joyner } 5058a13362dSEric Joyner 5068a13362dSEric Joyner if (ice_rdma.registered) { 5078a13362dSEric Joyner log(LOG_WARNING, "%s: iRDMA driver already registered\n", __func__); 5088a13362dSEric Joyner err = (EBUSY); 5098a13362dSEric Joyner goto return_unlock; 5108a13362dSEric Joyner } 5118a13362dSEric Joyner 5128a13362dSEric Joyner /* Make sure the iRDMA version is compatible */ 5138a13362dSEric Joyner err = ice_rdma_check_version(info); 5148a13362dSEric Joyner if (err) 5158a13362dSEric Joyner goto return_unlock; 5168a13362dSEric Joyner 5178a13362dSEric Joyner log(LOG_INFO, "%s: iRDMA driver registered using version %d.%d.%d\n", 5188a13362dSEric Joyner __func__, info->major_version, info->minor_version, info->patch_version); 5198a13362dSEric Joyner 5208a13362dSEric Joyner ice_rdma.peer_class = info->rdma_class; 5218a13362dSEric Joyner 5228a13362dSEric Joyner /* 5238a13362dSEric Joyner * Initialize the kobject interface and notify the RDMA client of each 5248a13362dSEric Joyner * existing PF interface. 5258a13362dSEric Joyner */ 5268a13362dSEric Joyner LIST_FOREACH(entry, &ice_rdma.peers, node) { 5278a13362dSEric Joyner kobj_init((kobj_t)&entry->peer, ice_rdma.peer_class); 5288923de59SPiotr Kubaj /* Gather DCB/QOS info into peer */ 5298923de59SPiotr Kubaj sc = __containerof(entry, struct ice_softc, rdma_entry); 5308923de59SPiotr Kubaj memset(&entry->peer.initial_qos_info, 0, sizeof(entry->peer.initial_qos_info)); 5318923de59SPiotr Kubaj ice_rdma_cp_qos_info(&sc->hw, &sc->hw.port_info->qos_cfg.local_dcbx_cfg, 5328923de59SPiotr Kubaj &entry->peer.initial_qos_info); 5338923de59SPiotr Kubaj 5348a13362dSEric Joyner IRDMA_PROBE(&entry->peer); 5358a13362dSEric Joyner if (entry->initiated) 5368a13362dSEric Joyner IRDMA_OPEN(&entry->peer); 5378a13362dSEric Joyner } 5388a13362dSEric Joyner ice_rdma.registered = true; 5398a13362dSEric Joyner 5408a13362dSEric Joyner return_unlock: 5418a13362dSEric Joyner sx_xunlock(&ice_rdma.mtx); 5428a13362dSEric Joyner 5438a13362dSEric Joyner return (err); 5448a13362dSEric Joyner } 5458a13362dSEric Joyner 5468a13362dSEric Joyner /** 5478a13362dSEric Joyner * ice_rdma_unregister - Unregister an RDMA client driver 5488a13362dSEric Joyner * 5498a13362dSEric Joyner * Called by the RDMA client driver on unload. Used to de-initialize the RDMA 5508a13362dSEric Joyner * client driver interface and shut down communication between the ice driver 5518a13362dSEric Joyner * and the RDMA client driver. 5529c30461dSEric Joyner * @return 0 on success, ENOENT when irdma driver wasn't registered 5538a13362dSEric Joyner */ 5548a13362dSEric Joyner int 5558a13362dSEric Joyner ice_rdma_unregister(void) 5568a13362dSEric Joyner { 5578a13362dSEric Joyner struct ice_rdma_entry *entry; 5588a13362dSEric Joyner 5598a13362dSEric Joyner sx_xlock(&ice_rdma.mtx); 5608a13362dSEric Joyner 5618a13362dSEric Joyner if (!ice_rdma.registered) { 5628a13362dSEric Joyner log(LOG_WARNING, "%s: iRDMA driver was not previously registered\n", 5638a13362dSEric Joyner __func__); 5648a13362dSEric Joyner sx_xunlock(&ice_rdma.mtx); 5658a13362dSEric Joyner return (ENOENT); 5668a13362dSEric Joyner } 5678a13362dSEric Joyner 5688a13362dSEric Joyner log(LOG_INFO, "%s: iRDMA driver unregistered\n", __func__); 5698a13362dSEric Joyner ice_rdma.registered = false; 5708a13362dSEric Joyner ice_rdma.peer_class = NULL; 5718a13362dSEric Joyner 5728a13362dSEric Joyner /* 5738a13362dSEric Joyner * Release the kobject interface for each of the existing PF 5748a13362dSEric Joyner * interfaces. Note that we do not notify the client about removing 5758a13362dSEric Joyner * each PF, as it is assumed that the client will have already cleaned 5768a13362dSEric Joyner * up any associated resources when it is unregistered. 5778a13362dSEric Joyner */ 5788a13362dSEric Joyner LIST_FOREACH(entry, &ice_rdma.peers, node) 5798a13362dSEric Joyner kobj_delete((kobj_t)&entry->peer, NULL); 5808a13362dSEric Joyner 5818a13362dSEric Joyner sx_xunlock(&ice_rdma.mtx); 5828a13362dSEric Joyner 5838a13362dSEric Joyner return (0); 5848a13362dSEric Joyner } 5858a13362dSEric Joyner 5868a13362dSEric Joyner /** 5878a13362dSEric Joyner * ice_rdma_init - RDMA driver init routine 5888a13362dSEric Joyner * 5898a13362dSEric Joyner * Called during ice driver module initialization to setup the RDMA client 5908a13362dSEric Joyner * interface mutex and RDMA peer structure list. 5918a13362dSEric Joyner */ 5928a13362dSEric Joyner void 5938a13362dSEric Joyner ice_rdma_init(void) 5948a13362dSEric Joyner { 5958a13362dSEric Joyner LIST_INIT(&ice_rdma.peers); 5968a13362dSEric Joyner sx_init_flags(&ice_rdma.mtx, "ice rdma interface", SX_DUPOK); 5978a13362dSEric Joyner 5988a13362dSEric Joyner ice_rdma.registered = false; 5998a13362dSEric Joyner ice_rdma.peer_class = NULL; 6008a13362dSEric Joyner } 6018a13362dSEric Joyner 6028a13362dSEric Joyner /** 6038a13362dSEric Joyner * ice_rdma_exit - RDMA driver exit routine 6048a13362dSEric Joyner * 6058a13362dSEric Joyner * Called during ice driver module exit to shutdown the RDMA client interface 6068a13362dSEric Joyner * mutex. 6078a13362dSEric Joyner */ 6088a13362dSEric Joyner void 6098a13362dSEric Joyner ice_rdma_exit(void) 6108a13362dSEric Joyner { 6118a13362dSEric Joyner MPASS(LIST_EMPTY(&ice_rdma.peers)); 6128a13362dSEric Joyner sx_destroy(&ice_rdma.mtx); 6138a13362dSEric Joyner } 6148a13362dSEric Joyner 6158a13362dSEric Joyner /** 6168a13362dSEric Joyner * ice_rdma_pf_attach_locked - Prepare a PF for RDMA connections 6178a13362dSEric Joyner * @sc: the ice driver softc 6188a13362dSEric Joyner * 6198a13362dSEric Joyner * Initialize a peer entry for this PF and add it to the RDMA interface list. 6208a13362dSEric Joyner * Notify the client RDMA driver of a new PF device. 6218a13362dSEric Joyner * 6228a13362dSEric Joyner * @pre must be called while holding the ice_rdma mutex. 6239c30461dSEric Joyner * @return 0 on success and when RDMA feature is not available, EEXIST when 6249c30461dSEric Joyner * irdma is already attached 6258a13362dSEric Joyner */ 6268a13362dSEric Joyner static int 6278a13362dSEric Joyner ice_rdma_pf_attach_locked(struct ice_softc *sc) 6288a13362dSEric Joyner { 6298a13362dSEric Joyner struct ice_rdma_entry *entry; 6308a13362dSEric Joyner 6318a13362dSEric Joyner /* Do not attach the PF unless RDMA is supported */ 6328a13362dSEric Joyner if (!ice_is_bit_set(sc->feat_cap, ICE_FEATURE_RDMA)) 6338a13362dSEric Joyner return (0); 6348a13362dSEric Joyner 6358a13362dSEric Joyner entry = &sc->rdma_entry; 6368a13362dSEric Joyner if (entry->attached) { 6378a13362dSEric Joyner device_printf(sc->dev, "iRDMA peer entry already exists\n"); 6388a13362dSEric Joyner return (EEXIST); 6398a13362dSEric Joyner } 6408a13362dSEric Joyner 6418a13362dSEric Joyner entry->attached = true; 6428a13362dSEric Joyner entry->peer.dev = sc->dev; 6438a13362dSEric Joyner entry->peer.ifp = sc->ifp; 6448a13362dSEric Joyner entry->peer.pf_id = sc->hw.pf_id; 6458a13362dSEric Joyner entry->peer.pci_mem = sc->bar0.res; 6468a13362dSEric Joyner entry->peer.pf_vsi_num = ice_get_hw_vsi_num(&sc->hw, sc->pf_vsi.idx); 6478a13362dSEric Joyner if (sc->rdma_imap && sc->rdma_imap[0] != ICE_INVALID_RES_IDX && 6488a13362dSEric Joyner sc->irdma_vectors > 0) { 6498a13362dSEric Joyner entry->peer.msix.base = sc->rdma_imap[0]; 6508a13362dSEric Joyner entry->peer.msix.count = sc->irdma_vectors; 6518a13362dSEric Joyner } 6528a13362dSEric Joyner 6538a13362dSEric Joyner /* Gather DCB/QOS info into peer */ 6548a13362dSEric Joyner memset(&entry->peer.initial_qos_info, 0, sizeof(entry->peer.initial_qos_info)); 6558a13362dSEric Joyner ice_rdma_cp_qos_info(&sc->hw, &sc->hw.port_info->qos_cfg.local_dcbx_cfg, 6568a13362dSEric Joyner &entry->peer.initial_qos_info); 6578a13362dSEric Joyner 6588a13362dSEric Joyner /* 6598a13362dSEric Joyner * If the RDMA client driver has already registered, initialize the 6608a13362dSEric Joyner * kobject and notify the client of a new PF 6618a13362dSEric Joyner */ 6628a13362dSEric Joyner if (ice_rdma.registered) { 6638a13362dSEric Joyner kobj_init((kobj_t)&entry->peer, ice_rdma.peer_class); 6648a13362dSEric Joyner IRDMA_PROBE(&entry->peer); 6658a13362dSEric Joyner } 6668a13362dSEric Joyner 6678a13362dSEric Joyner LIST_INSERT_HEAD(&ice_rdma.peers, entry, node); 6688a13362dSEric Joyner 6698a13362dSEric Joyner ice_set_bit(ICE_FEATURE_RDMA, sc->feat_en); 6708a13362dSEric Joyner 6718a13362dSEric Joyner return (0); 6728a13362dSEric Joyner } 6738a13362dSEric Joyner 6748a13362dSEric Joyner /** 6758a13362dSEric Joyner * ice_rdma_pf_attach - Notify the RDMA client of a new PF 6768a13362dSEric Joyner * @sc: the ice driver softc 6778a13362dSEric Joyner * 6788a13362dSEric Joyner * Called during PF attach to notify the RDMA client of a new PF. 6799c30461dSEric Joyner * @return 0 or EEXIST if irdma was already attached 6808a13362dSEric Joyner */ 6818a13362dSEric Joyner int 6828a13362dSEric Joyner ice_rdma_pf_attach(struct ice_softc *sc) 6838a13362dSEric Joyner { 6848a13362dSEric Joyner int err; 6858a13362dSEric Joyner 6868a13362dSEric Joyner sx_xlock(&ice_rdma.mtx); 6878a13362dSEric Joyner err = ice_rdma_pf_attach_locked(sc); 6888a13362dSEric Joyner sx_xunlock(&ice_rdma.mtx); 6898a13362dSEric Joyner 6908a13362dSEric Joyner return (err); 6918a13362dSEric Joyner } 6928a13362dSEric Joyner 6938a13362dSEric Joyner /** 6948a13362dSEric Joyner * ice_rdma_pf_detach_locked - Notify the RDMA client on PF detach 6958a13362dSEric Joyner * @sc: the ice driver softc 6968a13362dSEric Joyner * 6978a13362dSEric Joyner * Notify the RDMA peer client driver of removal of a PF, and release any 6988a13362dSEric Joyner * RDMA-specific resources associated with that PF. Remove the PF from the 6998a13362dSEric Joyner * list of available RDMA entries. 7008a13362dSEric Joyner * 7018a13362dSEric Joyner * @pre must be called while holding the ice_rdma mutex. 7028a13362dSEric Joyner */ 7038a13362dSEric Joyner static void 7048a13362dSEric Joyner ice_rdma_pf_detach_locked(struct ice_softc *sc) 7058a13362dSEric Joyner { 7068a13362dSEric Joyner struct ice_rdma_entry *entry; 7078a13362dSEric Joyner 7088a13362dSEric Joyner /* No need to detach the PF if RDMA is not enabled */ 7098a13362dSEric Joyner if (!ice_is_bit_set(sc->feat_en, ICE_FEATURE_RDMA)) 7108a13362dSEric Joyner return; 7118a13362dSEric Joyner 7128a13362dSEric Joyner entry = &sc->rdma_entry; 7138a13362dSEric Joyner if (!entry->attached) { 7148a13362dSEric Joyner device_printf(sc->dev, "iRDMA peer entry was not attached\n"); 7158a13362dSEric Joyner return; 7168a13362dSEric Joyner } 7178a13362dSEric Joyner 7188a13362dSEric Joyner /* 7198a13362dSEric Joyner * If the RDMA client driver is registered, notify the client that 7208a13362dSEric Joyner * a PF has been removed, and release the kobject reference. 7218a13362dSEric Joyner */ 7228a13362dSEric Joyner if (ice_rdma.registered) { 7238a13362dSEric Joyner IRDMA_REMOVE(&entry->peer); 7248a13362dSEric Joyner kobj_delete((kobj_t)&entry->peer, NULL); 7258a13362dSEric Joyner } 7268a13362dSEric Joyner 7278a13362dSEric Joyner LIST_REMOVE(entry, node); 7288a13362dSEric Joyner entry->attached = false; 7298a13362dSEric Joyner 7308a13362dSEric Joyner ice_clear_bit(ICE_FEATURE_RDMA, sc->feat_en); 7318a13362dSEric Joyner } 7328a13362dSEric Joyner 7338a13362dSEric Joyner /** 7348a13362dSEric Joyner * ice_rdma_pf_detach - Notify the RDMA client of a PF detaching 7358a13362dSEric Joyner * @sc: the ice driver softc 7368a13362dSEric Joyner * 7378a13362dSEric Joyner * Take the ice_rdma mutex and then notify the RDMA client that a PF has been 7388a13362dSEric Joyner * removed. 7398a13362dSEric Joyner */ 7408a13362dSEric Joyner void 7418a13362dSEric Joyner ice_rdma_pf_detach(struct ice_softc *sc) 7428a13362dSEric Joyner { 7438a13362dSEric Joyner sx_xlock(&ice_rdma.mtx); 7448a13362dSEric Joyner ice_rdma_pf_detach_locked(sc); 7458a13362dSEric Joyner sx_xunlock(&ice_rdma.mtx); 7468a13362dSEric Joyner } 7478a13362dSEric Joyner 7488a13362dSEric Joyner /** 7498a13362dSEric Joyner * ice_rdma_pf_init - Notify the RDMA client that a PF has initialized 7508a13362dSEric Joyner * @sc: the ice driver softc 7518a13362dSEric Joyner * 7528a13362dSEric Joyner * Called by the ice driver when a PF has been initialized. Notifies the RDMA 7538a13362dSEric Joyner * client that a PF is up and ready to operate. 7549c30461dSEric Joyner * @return 0 on success, propagates IRDMA_OPEN return value 7558a13362dSEric Joyner */ 7568a13362dSEric Joyner int 7578a13362dSEric Joyner ice_rdma_pf_init(struct ice_softc *sc) 7588a13362dSEric Joyner { 7598a13362dSEric Joyner struct ice_rdma_peer *peer = &sc->rdma_entry.peer; 7608a13362dSEric Joyner 7618a13362dSEric Joyner sx_xlock(&ice_rdma.mtx); 7628a13362dSEric Joyner 7638a13362dSEric Joyner /* Update the MTU */ 764402810d3SJustin Hibbits peer->mtu = if_getmtu(sc->ifp); 7658a13362dSEric Joyner sc->rdma_entry.initiated = true; 7668a13362dSEric Joyner 7678a13362dSEric Joyner if (sc->rdma_entry.attached && ice_rdma.registered) { 7688a13362dSEric Joyner sx_xunlock(&ice_rdma.mtx); 7698a13362dSEric Joyner return IRDMA_OPEN(peer); 7708a13362dSEric Joyner } 7718a13362dSEric Joyner 7728a13362dSEric Joyner sx_xunlock(&ice_rdma.mtx); 7738a13362dSEric Joyner 7748a13362dSEric Joyner return (0); 7758a13362dSEric Joyner } 7768a13362dSEric Joyner 7778a13362dSEric Joyner /** 7788a13362dSEric Joyner * ice_rdma_pf_stop - Notify the RDMA client of a stopped PF device 7798a13362dSEric Joyner * @sc: the ice driver softc 7808a13362dSEric Joyner * 7818a13362dSEric Joyner * Called by the ice driver when a PF is stopped. Notifies the RDMA client 7828a13362dSEric Joyner * driver that the PF has stopped and is not ready to operate. 7839c30461dSEric Joyner * @return 0 on success 7848a13362dSEric Joyner */ 7858a13362dSEric Joyner int 7868a13362dSEric Joyner ice_rdma_pf_stop(struct ice_softc *sc) 7878a13362dSEric Joyner { 7888a13362dSEric Joyner sx_xlock(&ice_rdma.mtx); 7898a13362dSEric Joyner 7908a13362dSEric Joyner sc->rdma_entry.initiated = false; 7918a13362dSEric Joyner if (sc->rdma_entry.attached && ice_rdma.registered) { 7928a13362dSEric Joyner sx_xunlock(&ice_rdma.mtx); 7938a13362dSEric Joyner return IRDMA_CLOSE(&sc->rdma_entry.peer); 7948a13362dSEric Joyner } 7958a13362dSEric Joyner 7968a13362dSEric Joyner sx_xunlock(&ice_rdma.mtx); 7978a13362dSEric Joyner 7988a13362dSEric Joyner return (0); 7998a13362dSEric Joyner } 8008a13362dSEric Joyner 8018a13362dSEric Joyner /** 8028a13362dSEric Joyner * ice_rdma_link_change - Notify RDMA client of a change in link status 8038a13362dSEric Joyner * @sc: the ice driver softc 8048a13362dSEric Joyner * @linkstate: the link status 8058a13362dSEric Joyner * @baudrate: the link rate in bits per second 8068a13362dSEric Joyner * 8078a13362dSEric Joyner * Notify the RDMA client of a link status change, by sending it the new link 8088a13362dSEric Joyner * state and baudrate. 8098a13362dSEric Joyner * 8108a13362dSEric Joyner * The link state is represented the same was as in the ifnet structure. It 8118a13362dSEric Joyner * should be LINK_STATE_UNKNOWN, LINK_STATE_DOWN, or LINK_STATE_UP. 8128a13362dSEric Joyner */ 8138a13362dSEric Joyner void 8148a13362dSEric Joyner ice_rdma_link_change(struct ice_softc *sc, int linkstate, uint64_t baudrate) 8158a13362dSEric Joyner { 8168a13362dSEric Joyner struct ice_rdma_peer *peer = &sc->rdma_entry.peer; 8178a13362dSEric Joyner struct ice_rdma_event event; 8188a13362dSEric Joyner 8198a13362dSEric Joyner memset(&event, 0, sizeof(struct ice_rdma_event)); 8208a13362dSEric Joyner event.type = ICE_RDMA_EVENT_LINK_CHANGE; 8218a13362dSEric Joyner event.linkstate = linkstate; 8228a13362dSEric Joyner event.baudrate = baudrate; 8238a13362dSEric Joyner 8248a13362dSEric Joyner sx_xlock(&ice_rdma.mtx); 8258a13362dSEric Joyner 8268a13362dSEric Joyner if (sc->rdma_entry.attached && ice_rdma.registered) 8278a13362dSEric Joyner IRDMA_EVENT_HANDLER(peer, &event); 8288a13362dSEric Joyner 8298a13362dSEric Joyner sx_xunlock(&ice_rdma.mtx); 8308a13362dSEric Joyner } 8318a13362dSEric Joyner 8328a13362dSEric Joyner /** 8338a13362dSEric Joyner * ice_rdma_notify_dcb_qos_change - notify RDMA driver to pause traffic 8348a13362dSEric Joyner * @sc: the ice driver softc 8358a13362dSEric Joyner * 8368a13362dSEric Joyner * Notify the RDMA driver that QOS/DCB settings are about to change. 8378a13362dSEric Joyner * Once the function return, all the QPs should be suspended. 8388a13362dSEric Joyner */ 8398a13362dSEric Joyner void 8408a13362dSEric Joyner ice_rdma_notify_dcb_qos_change(struct ice_softc *sc) 8418a13362dSEric Joyner { 8428a13362dSEric Joyner struct ice_rdma_peer *peer = &sc->rdma_entry.peer; 8438a13362dSEric Joyner struct ice_rdma_event event; 8448a13362dSEric Joyner 8458a13362dSEric Joyner memset(&event, 0, sizeof(struct ice_rdma_event)); 8468a13362dSEric Joyner event.type = ICE_RDMA_EVENT_TC_CHANGE; 8478a13362dSEric Joyner /* pre-event */ 8488a13362dSEric Joyner event.prep = true; 8498a13362dSEric Joyner 8508a13362dSEric Joyner sx_xlock(&ice_rdma.mtx); 8518a13362dSEric Joyner if (sc->rdma_entry.attached && ice_rdma.registered) 8528a13362dSEric Joyner IRDMA_EVENT_HANDLER(peer, &event); 8538a13362dSEric Joyner sx_xunlock(&ice_rdma.mtx); 8548a13362dSEric Joyner } 8558a13362dSEric Joyner 8568a13362dSEric Joyner /** 8578a13362dSEric Joyner * ice_rdma_dcb_qos_update - pass the changed dcb settings to RDMA driver 8588a13362dSEric Joyner * @sc: the ice driver softc 8598a13362dSEric Joyner * @pi: the port info structure 8608a13362dSEric Joyner * 8618a13362dSEric Joyner * Pass the changed DCB settings to RDMA traffic. This function should be 8628a13362dSEric Joyner * called only after ice_rdma_notify_dcb_qos_change has been called and 8638a13362dSEric Joyner * returned before. After the function returns, all the RDMA traffic 8648a13362dSEric Joyner * should be resumed. 8658a13362dSEric Joyner */ 8668a13362dSEric Joyner void 8678a13362dSEric Joyner ice_rdma_dcb_qos_update(struct ice_softc *sc, struct ice_port_info *pi) 8688a13362dSEric Joyner { 8698a13362dSEric Joyner struct ice_rdma_peer *peer = &sc->rdma_entry.peer; 8708a13362dSEric Joyner struct ice_rdma_event event; 8718a13362dSEric Joyner 8728a13362dSEric Joyner memset(&event, 0, sizeof(struct ice_rdma_event)); 8738a13362dSEric Joyner event.type = ICE_RDMA_EVENT_TC_CHANGE; 8748a13362dSEric Joyner /* post-event */ 8758a13362dSEric Joyner event.prep = false; 8768a13362dSEric Joyner 8778a13362dSEric Joyner /* gather current configuration */ 8788a13362dSEric Joyner ice_rdma_cp_qos_info(&sc->hw, &pi->qos_cfg.local_dcbx_cfg, &event.port_qos); 8798a13362dSEric Joyner sx_xlock(&ice_rdma.mtx); 8808a13362dSEric Joyner if (sc->rdma_entry.attached && ice_rdma.registered) 8818a13362dSEric Joyner IRDMA_EVENT_HANDLER(peer, &event); 8828a13362dSEric Joyner sx_xunlock(&ice_rdma.mtx); 8838a13362dSEric Joyner } 88401fbb869SBartosz Sobczak 88501fbb869SBartosz Sobczak /** 88601fbb869SBartosz Sobczak * ice_rdma_notify_pe_intr - notify irdma on incoming interrupts regarding PE 88701fbb869SBartosz Sobczak * @sc: the ice driver softc 88801fbb869SBartosz Sobczak * @oicr: interrupt cause 88901fbb869SBartosz Sobczak * 89001fbb869SBartosz Sobczak * Pass the information about received interrupt to RDMA driver if it was 89101fbb869SBartosz Sobczak * relating to PE. Specifically PE_CRITERR and HMC_ERR. 89201fbb869SBartosz Sobczak * The irdma driver shall decide what should be done upon these interrupts. 89301fbb869SBartosz Sobczak */ 89401fbb869SBartosz Sobczak void 89501fbb869SBartosz Sobczak ice_rdma_notify_pe_intr(struct ice_softc *sc, uint32_t oicr) 89601fbb869SBartosz Sobczak { 89701fbb869SBartosz Sobczak struct ice_rdma_peer *peer = &sc->rdma_entry.peer; 89801fbb869SBartosz Sobczak struct ice_rdma_event event; 89901fbb869SBartosz Sobczak 90001fbb869SBartosz Sobczak memset(&event, 0, sizeof(struct ice_rdma_event)); 90101fbb869SBartosz Sobczak event.type = ICE_RDMA_EVENT_CRIT_ERR; 90201fbb869SBartosz Sobczak event.oicr_reg = oicr; 90301fbb869SBartosz Sobczak 90401fbb869SBartosz Sobczak sx_xlock(&ice_rdma.mtx); 90501fbb869SBartosz Sobczak if (sc->rdma_entry.attached && ice_rdma.registered) 90601fbb869SBartosz Sobczak IRDMA_EVENT_HANDLER(peer, &event); 90701fbb869SBartosz Sobczak sx_xunlock(&ice_rdma.mtx); 90801fbb869SBartosz Sobczak } 90901fbb869SBartosz Sobczak 91001fbb869SBartosz Sobczak /** 91101fbb869SBartosz Sobczak * ice_rdma_notify_reset - notify irdma on incoming pf-reset 91201fbb869SBartosz Sobczak * @sc: the ice driver softc 91301fbb869SBartosz Sobczak * 91401fbb869SBartosz Sobczak * Inform irdma driver of an incoming PF reset. 91501fbb869SBartosz Sobczak * The irdma driver shall set its state to reset, and avoid using CQP 91601fbb869SBartosz Sobczak * anymore. Next step should be to call ice_rdma_pf_stop in order to 91701fbb869SBartosz Sobczak * remove resources. 91801fbb869SBartosz Sobczak */ 91901fbb869SBartosz Sobczak void 92001fbb869SBartosz Sobczak ice_rdma_notify_reset(struct ice_softc *sc) 92101fbb869SBartosz Sobczak { 92201fbb869SBartosz Sobczak struct ice_rdma_peer *peer = &sc->rdma_entry.peer; 92301fbb869SBartosz Sobczak struct ice_rdma_event event; 92401fbb869SBartosz Sobczak 92501fbb869SBartosz Sobczak memset(&event, 0, sizeof(struct ice_rdma_event)); 92601fbb869SBartosz Sobczak event.type = ICE_RDMA_EVENT_RESET; 92701fbb869SBartosz Sobczak 92801fbb869SBartosz Sobczak sx_xlock(&ice_rdma.mtx); 92901fbb869SBartosz Sobczak if (sc->rdma_entry.attached && ice_rdma.registered) 93001fbb869SBartosz Sobczak IRDMA_EVENT_HANDLER(peer, &event); 93101fbb869SBartosz Sobczak sx_xunlock(&ice_rdma.mtx); 93201fbb869SBartosz Sobczak } 933