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 */ 16 static 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 */ 33 void 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 */ 52 static 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 */ 67 int 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 } 115 EXPORT_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 */ 122 int 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 } 144 EXPORT_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 */ 151 int 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 } 175 EXPORT_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 */ 183 int 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 } 208 EXPORT_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 */ 215 void 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 } 231 EXPORT_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 */ 237 static 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 */ 256 static 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 */ 268 int 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 = pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2 ? "roce" : "iwarp"; 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 */ 313 void 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 */ 327 int 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 pf->rdma_mode |= IIDC_RDMA_PROTOCOL_ROCEV2; 339 return ice_plug_aux_dev(pf); 340 } 341