The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ice/ice_rdma.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: a83cbc52561117ec2e885fd76f238a76


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.