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