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