linux/drivers/net/ethernet/intel/ice/ice_idc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (C) 2021, Intel Corporation. */
   3
   4/* Inter-Driver Communication */
   5#include "ice.h"
   6#include "ice_lib.h"
   7#include "ice_dcb_lib.h"
   8
   9/**
  10 * ice_get_auxiliary_drv - retrieve iidc_auxiliary_drv struct
  11 * @pf: pointer to PF struct
  12 *
  13 * This function has to be called with a device_lock on the
  14 * pf->adev.dev to avoid race conditions.
  15 */
  16static struct iidc_auxiliary_drv *ice_get_auxiliary_drv(struct ice_pf *pf)
  17{
  18        struct auxiliary_device *adev;
  19
  20        adev = pf->adev;
  21        if (!adev || !adev->dev.driver)
  22                return NULL;
  23
  24        return container_of(adev->dev.driver, struct iidc_auxiliary_drv,
  25                            adrv.driver);
  26}
  27
  28/**
  29 * ice_send_event_to_aux - send event to RDMA AUX driver
  30 * @pf: pointer to PF struct
  31 * @event: event struct
  32 */
  33void ice_send_event_to_aux(struct ice_pf *pf, struct iidc_event *event)
  34{
  35        struct iidc_auxiliary_drv *iadrv;
  36
  37        if (!pf->adev)
  38                return;
  39
  40        device_lock(&pf->adev->dev);
  41        iadrv = ice_get_auxiliary_drv(pf);
  42        if (iadrv && iadrv->event_handler)
  43                iadrv->event_handler(pf, event);
  44        device_unlock(&pf->adev->dev);
  45}
  46
  47/**
  48 * ice_find_vsi - Find the VSI from VSI ID
  49 * @pf: The PF pointer to search in
  50 * @vsi_num: The VSI ID to search for
  51 */
  52static struct ice_vsi *ice_find_vsi(struct ice_pf *pf, u16 vsi_num)
  53{
  54        int i;
  55
  56        ice_for_each_vsi(pf, i)
  57                if (pf->vsi[i] && pf->vsi[i]->vsi_num == vsi_num)
  58                        return  pf->vsi[i];
  59        return NULL;
  60}
  61
  62/**
  63 * ice_add_rdma_qset - Add Leaf Node for RDMA Qset
  64 * @pf: PF struct
  65 * @qset: Resource to be allocated
  66 */
  67int ice_add_rdma_qset(struct ice_pf *pf, struct iidc_rdma_qset_params *qset)
  68{
  69        u16 max_rdmaqs[ICE_MAX_TRAFFIC_CLASS];
  70        struct ice_vsi *vsi;
  71        struct device *dev;
  72        u32 qset_teid;
  73        u16 qs_handle;
  74        int status;
  75        int i;
  76
  77        if (WARN_ON(!pf || !qset))
  78                return -EINVAL;
  79
  80        dev = ice_pf_to_dev(pf);
  81
  82        if (!test_bit(ICE_FLAG_RDMA_ENA, pf->flags))
  83                return -EINVAL;
  84
  85        vsi = ice_get_main_vsi(pf);
  86        if (!vsi) {
  87                dev_err(dev, "RDMA QSet invalid VSI\n");
  88                return -EINVAL;
  89        }
  90
  91        ice_for_each_traffic_class(i)
  92                max_rdmaqs[i] = 0;
  93
  94        max_rdmaqs[qset->tc]++;
  95        qs_handle = qset->qs_handle;
  96
  97        status = ice_cfg_vsi_rdma(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,
  98                                  max_rdmaqs);
  99        if (status) {
 100                dev_err(dev, "Failed VSI RDMA Qset config\n");
 101                return status;
 102        }
 103
 104        status = ice_ena_vsi_rdma_qset(vsi->port_info, vsi->idx, qset->tc,
 105                                       &qs_handle, 1, &qset_teid);
 106        if (status) {
 107                dev_err(dev, "Failed VSI RDMA Qset enable\n");
 108                return status;
 109        }
 110        vsi->qset_handle[qset->tc] = qset->qs_handle;
 111        qset->teid = qset_teid;
 112
 113        return 0;
 114}
 115EXPORT_SYMBOL_GPL(ice_add_rdma_qset);
 116
 117/**
 118 * ice_del_rdma_qset - Delete leaf node for RDMA Qset
 119 * @pf: PF struct
 120 * @qset: Resource to be freed
 121 */
 122int ice_del_rdma_qset(struct ice_pf *pf, struct iidc_rdma_qset_params *qset)
 123{
 124        struct ice_vsi *vsi;
 125        u32 teid;
 126        u16 q_id;
 127
 128        if (WARN_ON(!pf || !qset))
 129                return -EINVAL;
 130
 131        vsi = ice_find_vsi(pf, qset->vport_id);
 132        if (!vsi) {
 133                dev_err(ice_pf_to_dev(pf), "RDMA Invalid VSI\n");
 134                return -EINVAL;
 135        }
 136
 137        q_id = qset->qs_handle;
 138        teid = qset->teid;
 139
 140        vsi->qset_handle[qset->tc] = 0;
 141
 142        return ice_dis_vsi_rdma_qset(vsi->port_info, 1, &teid, &q_id);
 143}
 144EXPORT_SYMBOL_GPL(ice_del_rdma_qset);
 145
 146/**
 147 * ice_rdma_request_reset - accept request from RDMA to perform a reset
 148 * @pf: struct for PF
 149 * @reset_type: type of reset
 150 */
 151int ice_rdma_request_reset(struct ice_pf *pf, enum iidc_reset_type reset_type)
 152{
 153        enum ice_reset_req reset;
 154
 155        if (WARN_ON(!pf))
 156                return -EINVAL;
 157
 158        switch (reset_type) {
 159        case IIDC_PFR:
 160                reset = ICE_RESET_PFR;
 161                break;
 162        case IIDC_CORER:
 163                reset = ICE_RESET_CORER;
 164                break;
 165        case IIDC_GLOBR:
 166                reset = ICE_RESET_GLOBR;
 167                break;
 168        default:
 169                dev_err(ice_pf_to_dev(pf), "incorrect reset request\n");
 170                return -EINVAL;
 171        }
 172
 173        return ice_schedule_reset(pf, reset);
 174}
 175EXPORT_SYMBOL_GPL(ice_rdma_request_reset);
 176
 177/**
 178 * ice_rdma_update_vsi_filter - update main VSI filters for RDMA
 179 * @pf: pointer to struct for PF
 180 * @vsi_id: VSI HW idx to update filter on
 181 * @enable: bool whether to enable or disable filters
 182 */
 183int ice_rdma_update_vsi_filter(struct ice_pf *pf, u16 vsi_id, bool enable)
 184{
 185        struct ice_vsi *vsi;
 186        int status;
 187
 188        if (WARN_ON(!pf))
 189                return -EINVAL;
 190
 191        vsi = ice_find_vsi(pf, vsi_id);
 192        if (!vsi)
 193                return -EINVAL;
 194
 195        status = ice_cfg_rdma_fltr(&pf->hw, vsi->idx, enable);
 196        if (status) {
 197                dev_err(ice_pf_to_dev(pf), "Failed to  %sable RDMA filtering\n",
 198                        enable ? "en" : "dis");
 199        } else {
 200                if (enable)
 201                        vsi->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
 202                else
 203                        vsi->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
 204        }
 205
 206        return status;
 207}
 208EXPORT_SYMBOL_GPL(ice_rdma_update_vsi_filter);
 209
 210/**
 211 * ice_get_qos_params - parse QoS params for RDMA consumption
 212 * @pf: pointer to PF struct
 213 * @qos: set of QoS values
 214 */
 215void ice_get_qos_params(struct ice_pf *pf, struct iidc_qos_params *qos)
 216{
 217        struct ice_dcbx_cfg *dcbx_cfg;
 218        unsigned int i;
 219        u32 up2tc;
 220
 221        dcbx_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;
 222        up2tc = rd32(&pf->hw, PRTDCB_TUP2TC);
 223
 224        qos->num_tc = ice_dcb_get_num_tc(dcbx_cfg);
 225        for (i = 0; i < IIDC_MAX_USER_PRIORITY; i++)
 226                qos->up2tc[i] = (up2tc >> (i * 3)) & 0x7;
 227
 228        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
 229                qos->tc_info[i].rel_bw = dcbx_cfg->etscfg.tcbwtable[i];
 230}
 231EXPORT_SYMBOL_GPL(ice_get_qos_params);
 232
 233/**
 234 * ice_reserve_rdma_qvector - Reserve vector resources for RDMA driver
 235 * @pf: board private structure to initialize
 236 */
 237static int ice_reserve_rdma_qvector(struct ice_pf *pf)
 238{
 239        if (test_bit(ICE_FLAG_RDMA_ENA, pf->flags)) {
 240                int index;
 241
 242                index = ice_get_res(pf, pf->irq_tracker, pf->num_rdma_msix,
 243                                    ICE_RES_RDMA_VEC_ID);
 244                if (index < 0)
 245                        return index;
 246                pf->num_avail_sw_msix -= pf->num_rdma_msix;
 247                pf->rdma_base_vector = (u16)index;
 248        }
 249        return 0;
 250}
 251
 252/**
 253 * ice_adev_release - function to be mapped to AUX dev's release op
 254 * @dev: pointer to device to free
 255 */
 256static void ice_adev_release(struct device *dev)
 257{
 258        struct iidc_auxiliary_dev *iadev;
 259
 260        iadev = container_of(dev, struct iidc_auxiliary_dev, adev.dev);
 261        kfree(iadev);
 262}
 263
 264/**
 265 * ice_plug_aux_dev - allocate and register AUX device
 266 * @pf: pointer to pf struct
 267 */
 268int ice_plug_aux_dev(struct ice_pf *pf)
 269{
 270        struct iidc_auxiliary_dev *iadev;
 271        struct auxiliary_device *adev;
 272        int ret;
 273
 274        /* if this PF doesn't support a technology that requires auxiliary
 275         * devices, then gracefully exit
 276         */
 277        if (!ice_is_aux_ena(pf))
 278                return 0;
 279
 280        iadev = kzalloc(sizeof(*iadev), GFP_KERNEL);
 281        if (!iadev)
 282                return -ENOMEM;
 283
 284        adev = &iadev->adev;
 285        pf->adev = adev;
 286        iadev->pf = pf;
 287
 288        adev->id = pf->aux_idx;
 289        adev->dev.release = ice_adev_release;
 290        adev->dev.parent = &pf->pdev->dev;
 291        adev->name = IIDC_RDMA_ROCE_NAME;
 292
 293        ret = auxiliary_device_init(adev);
 294        if (ret) {
 295                pf->adev = NULL;
 296                kfree(iadev);
 297                return ret;
 298        }
 299
 300        ret = auxiliary_device_add(adev);
 301        if (ret) {
 302                pf->adev = NULL;
 303                auxiliary_device_uninit(adev);
 304                return ret;
 305        }
 306
 307        return 0;
 308}
 309
 310/* ice_unplug_aux_dev - unregister and free AUX device
 311 * @pf: pointer to pf struct
 312 */
 313void ice_unplug_aux_dev(struct ice_pf *pf)
 314{
 315        if (!pf->adev)
 316                return;
 317
 318        auxiliary_device_delete(pf->adev);
 319        auxiliary_device_uninit(pf->adev);
 320        pf->adev = NULL;
 321}
 322
 323/**
 324 * ice_init_rdma - initializes PF for RDMA use
 325 * @pf: ptr to ice_pf
 326 */
 327int ice_init_rdma(struct ice_pf *pf)
 328{
 329        struct device *dev = &pf->pdev->dev;
 330        int ret;
 331
 332        /* Reserve vector resources */
 333        ret = ice_reserve_rdma_qvector(pf);
 334        if (ret < 0) {
 335                dev_err(dev, "failed to reserve vectors for RDMA\n");
 336                return ret;
 337        }
 338
 339        return ice_plug_aux_dev(pf);
 340}
 341