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