FILE
ice_idc.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/intel/ice/ice_idc.c
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 9static DEFINE_XARRAY_ALLOC1(ice_aux_id); 10 11/** 12 * ice_get_auxiliary_drv - retrieve iidc_rdma_core_auxiliary_drv struct 13 * @cdev: pointer to iidc_rdma_core_dev_info struct 14 * 15 * This function has to be called with a device_lock on the 16 * cdev->adev.dev to avoid race conditions. 17 * 18 * Return: pointer to the matched auxiliary driver struct 19 */ 20static struct iidc_rdma_core_auxiliary_drv * 21ice_get_auxiliary_drv(struct iidc_rdma_core_dev_info *cdev) 22{ 23 struct auxiliary_device *adev; 24 25 adev = cdev->adev; 26 if (!adev || !adev->dev.driver) 27 return NULL; 28 29 return container_of(adev->dev.driver, 30 struct iidc_rdma_core_auxiliary_drv, adrv.driver); 31} 32 33/** 34 * ice_send_event_to_aux - send event to RDMA AUX driver 35 * @pf: pointer to PF struct 36 * @event: event struct 37 */ 38void ice_send_event_to_aux(struct ice_pf *pf, struct iidc_rdma_event *event) 39{ 40 struct iidc_rdma_core_auxiliary_drv *iadrv; 41 struct iidc_rdma_core_dev_info *cdev; 42 43 if (WARN_ON_ONCE(!in_task())) 44 return; 45 46 cdev = pf->cdev_info; 47 if (!cdev) 48 return; 49 50 mutex_lock(&pf->adev_mutex); 51 if (!cdev->adev) 52 goto finish; 53 54 device_lock(&cdev->adev->dev); 55 iadrv = ice_get_auxiliary_drv(cdev); 56 if (iadrv && iadrv->event_handler) 57 iadrv->event_handler(cdev, event); 58 device_unlock(&cdev->adev->dev); 59finish: 60 mutex_unlock(&pf->adev_mutex); 61} 62 63/** 64 * ice_add_rdma_qset - Add Leaf Node for RDMA Qset 65 * @cdev: pointer to iidc_rdma_core_dev_info struct 66 * @qset: Resource to be allocated 67 * 68 * Return: Zero on success or error code encountered 69 */ 70int ice_add_rdma_qset(struct iidc_rdma_core_dev_info *cdev, 71 struct iidc_rdma_qset_params *qset) 72{ 73 u16 max_rdmaqs[ICE_MAX_TRAFFIC_CLASS]; 74 struct ice_vsi *vsi; 75 struct device *dev; 76 struct ice_pf *pf; 77 u32 qset_teid; 78 u16 qs_handle; 79 int status; 80 int i; 81 82 if (WARN_ON(!cdev || !qset)) 83 return -EINVAL; 84 85 pf = pci_get_drvdata(cdev->pdev); 86 dev = ice_pf_to_dev(pf); 87 88 if (!ice_is_rdma_ena(pf)) 89 return -EINVAL; 90 91 vsi = ice_get_main_vsi(pf); 92 if (!vsi) { 93 dev_err(dev, "RDMA QSet invalid VSI\n"); 94 return -EINVAL; 95 } 96 97 ice_for_each_traffic_class(i) 98 max_rdmaqs[i] = 0; 99 100 max_rdmaqs[qset->tc]++; 101 qs_handle = qset->qs_handle; 102 103 status = ice_cfg_vsi_rdma(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc, 104 max_rdmaqs); 105 if (status) { 106 dev_err(dev, "Failed VSI RDMA Qset config\n"); 107 return status; 108 } 109 110 status = ice_ena_vsi_rdma_qset(vsi->port_info, vsi->idx, qset->tc, 111 &qs_handle, 1, &qset_teid); 112 if (status) { 113 dev_err(dev, "Failed VSI RDMA Qset enable\n"); 114 return status; 115 } 116 qset->teid = qset_teid; 117 118 return 0; 119} 120EXPORT_SYMBOL_GPL(ice_add_rdma_qset); 121 122/** 123 * ice_del_rdma_qset - Delete leaf node for RDMA Qset 124 * @cdev: pointer to iidc_rdma_core_dev_info struct 125 * @qset: Resource to be freed 126 * 127 * Return: Zero on success, error code on failure 128 */ 129int ice_del_rdma_qset(struct iidc_rdma_core_dev_info *cdev, 130 struct iidc_rdma_qset_params *qset) 131{ 132 struct ice_vsi *vsi; 133 struct ice_pf *pf; 134 u32 teid; 135 u16 q_id; 136 137 if (WARN_ON(!cdev || !qset)) 138 return -EINVAL; 139 140 pf = pci_get_drvdata(cdev->pdev); 141 vsi = ice_find_vsi(pf, qset->vport_id); 142 if (!vsi) { 143 dev_err(ice_pf_to_dev(pf), "RDMA Invalid VSI\n"); 144 return -EINVAL; 145 } 146 147 q_id = qset->qs_handle; 148 teid = qset->teid; 149 150 return ice_dis_vsi_rdma_qset(vsi->port_info, 1, &teid, &q_id); 151} 152EXPORT_SYMBOL_GPL(ice_del_rdma_qset); 153 154/** 155 * ice_rdma_request_reset - accept request from RDMA to perform a reset 156 * @cdev: pointer to iidc_rdma_core_dev_info struct 157 * @reset_type: type of reset 158 * 159 * Return: Zero on success, error code on failure 160 */ 161int ice_rdma_request_reset(struct iidc_rdma_core_dev_info *cdev, 162 enum iidc_rdma_reset_type reset_type) 163{ 164 enum ice_reset_req reset; 165 struct ice_pf *pf; 166 167 if (WARN_ON(!cdev)) 168 return -EINVAL; 169 170 pf = pci_get_drvdata(cdev->pdev); 171 172 switch (reset_type) { 173 case IIDC_FUNC_RESET: 174 reset = ICE_RESET_PFR; 175 break; 176 case IIDC_DEV_RESET: 177 reset = ICE_RESET_CORER; 178 break; 179 default: 180 return -EINVAL; 181 } 182 183 return ice_schedule_reset(pf, reset); 184} 185EXPORT_SYMBOL_GPL(ice_rdma_request_reset); 186 187/** 188 * ice_rdma_update_vsi_filter - update main VSI filters for RDMA 189 * @cdev: pointer to iidc_rdma_core_dev_info struct 190 * @vsi_id: VSI HW idx to update filter on 191 * @enable: bool whether to enable or disable filters 192 * 193 * Return: Zero on success, error code on failure 194 */ 195int ice_rdma_update_vsi_filter(struct iidc_rdma_core_dev_info *cdev, 196 u16 vsi_id, bool enable) 197{ 198 struct ice_vsi *vsi; 199 struct ice_pf *pf; 200 int status; 201 202 if (WARN_ON(!cdev)) 203 return -EINVAL; 204 205 pf = pci_get_drvdata(cdev->pdev); 206 vsi = ice_find_vsi(pf, vsi_id); 207 if (!vsi) 208 return -EINVAL; 209 210 status = ice_cfg_rdma_fltr(&pf->hw, vsi->idx, enable); 211 if (status) { 212 dev_err(ice_pf_to_dev(pf), "Failed to %sable RDMA filtering\n", 213 enable ? "en" : "dis"); 214 } else { 215 if (enable) 216 vsi->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN; 217 else 218 vsi->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN; 219 } 220 221 return status; 222} 223EXPORT_SYMBOL_GPL(ice_rdma_update_vsi_filter); 224 225/** 226 * ice_alloc_rdma_qvector - alloc vector resources reserved for RDMA driver 227 * @cdev: pointer to iidc_rdma_core_dev_info struct 228 * @entry: MSI-X entry to be removed 229 * 230 * Return: Zero on success, error code on failure 231 */ 232int ice_alloc_rdma_qvector(struct iidc_rdma_core_dev_info *cdev, 233 struct msix_entry *entry) 234{ 235 struct msi_map map; 236 struct ice_pf *pf; 237 238 if (WARN_ON(!cdev)) 239 return -EINVAL; 240 241 pf = pci_get_drvdata(cdev->pdev); 242 map = ice_alloc_irq(pf, true); 243 if (map.index < 0) 244 return -ENOMEM; 245 246 entry->entry = map.index; 247 entry->vector = map.virq; 248 249 return 0; 250} 251EXPORT_SYMBOL_GPL(ice_alloc_rdma_qvector); 252 253/** 254 * ice_free_rdma_qvector - free vector resources reserved for RDMA driver 255 * @cdev: pointer to iidc_rdma_core_dev_info struct 256 * @entry: MSI-X entry to be removed 257 */ 258void ice_free_rdma_qvector(struct iidc_rdma_core_dev_info *cdev, 259 struct msix_entry *entry) 260{ 261 struct msi_map map; 262 struct ice_pf *pf; 263 264 if (WARN_ON(!cdev || !entry)) 265 return; 266 267 pf = pci_get_drvdata(cdev->pdev); 268 269 map.index = entry->entry; 270 map.virq = entry->vector; 271 ice_free_irq(pf, map); 272} 273EXPORT_SYMBOL_GPL(ice_free_rdma_qvector); 274 275/** 276 * ice_adev_release - function to be mapped to AUX dev's release op 277 * @dev: pointer to device to free 278 */ 279static void ice_adev_release(struct device *dev) 280{ 281 struct iidc_rdma_core_auxiliary_dev *iadev; 282 283 iadev = container_of(dev, struct iidc_rdma_core_auxiliary_dev, 284 adev.dev); 285 kfree(iadev); 286} 287 288/** 289 * ice_plug_aux_dev - allocate and register AUX device 290 * @pf: pointer to pf struct 291 * 292 * Return: Zero on success, error code on failure 293 */ 294int ice_plug_aux_dev(struct ice_pf *pf) 295{ 296 struct iidc_rdma_core_auxiliary_dev *iadev; 297 struct iidc_rdma_core_dev_info *cdev; 298 struct auxiliary_device *adev; 299 int ret; 300 301 /* if this PF doesn't support a technology that requires auxiliary 302 * devices, then gracefully exit 303 */ 304 if (!ice_is_rdma_ena(pf)) 305 return 0; 306 307 cdev = pf->cdev_info; 308 if (!cdev) 309 return -ENODEV; 310 311 iadev = kzalloc(sizeof(*iadev), GFP_KERNEL); 312 if (!iadev) 313 return -ENOMEM; 314 315 adev = &iadev->adev; 316 iadev->cdev_info = cdev; 317 318 adev->id = pf->aux_idx; 319 adev->dev.release = ice_adev_release; 320 adev->dev.parent = &pf->pdev->dev; 321 adev->name = cdev->rdma_protocol & IIDC_RDMA_PROTOCOL_ROCEV2 ? 322 "roce" : "iwarp"; 323 324 ret = auxiliary_device_init(adev); 325 if (ret) { 326 kfree(iadev); 327 return ret; 328 } 329 330 ret = auxiliary_device_add(adev); 331 if (ret) { 332 auxiliary_device_uninit(adev); 333 return ret; 334 } 335 336 mutex_lock(&pf->adev_mutex); 337 cdev->adev = adev; 338 mutex_unlock(&pf->adev_mutex); 339 set_bit(ICE_FLAG_AUX_DEV_CREATED, pf->flags); 340 341 return 0; 342} 343 344/* ice_unplug_aux_dev - unregister and free AUX device 345 * @pf: pointer to pf struct 346 */ 347void ice_unplug_aux_dev(struct ice_pf *pf) 348{ 349 struct auxiliary_device *adev; 350 351 if (!test_and_clear_bit(ICE_FLAG_AUX_DEV_CREATED, pf->flags)) 352 return; 353 354 mutex_lock(&pf->adev_mutex); 355 adev = pf->cdev_info->adev; 356 pf->cdev_info->adev = NULL; 357 mutex_unlock(&pf->adev_mutex); 358 359 auxiliary_device_delete(adev); 360 auxiliary_device_uninit(adev); 361} 362 363/** 364 * ice_rdma_finalize_setup - Complete RDMA setup after VSI is ready 365 * @pf: ptr to ice_pf 366 * 367 * Sets VSI-dependent information and plugs aux device. 368 * Must be called after ice_init_rdma(), ice_vsi_rebuild(), and 369 * ice_dcb_rebuild() complete. 370 */ 371void ice_rdma_finalize_setup(struct ice_pf *pf) 372{ 373 struct device *dev = ice_pf_to_dev(pf); 374 struct iidc_rdma_priv_dev_info *privd; 375 int ret; 376 377 if (!ice_is_rdma_ena(pf) || !pf->cdev_info) 378 return; 379 380 privd = pf->cdev_info->iidc_priv; 381 if (!privd || !pf->vsi || !pf->vsi[0] || !pf->vsi[0]->netdev) 382 return; 383 384 /* Assign VSI info now that VSI is valid */ 385 privd->netdev = pf->vsi[0]->netdev; 386 privd->vport_id = pf->vsi[0]->vsi_num; 387 388 /* Update QoS info after DCB has been rebuilt */ 389 ice_setup_dcb_qos_info(pf, &privd->qos_info); 390 391 ret = ice_plug_aux_dev(pf); 392 if (ret) 393 dev_warn(dev, "Failed to plug RDMA aux device: %d\n", ret); 394} 395 396/** 397 * ice_init_rdma - initializes PF for RDMA use 398 * @pf: ptr to ice_pf 399 */ 400int ice_init_rdma(struct ice_pf *pf) 401{ 402 struct iidc_rdma_priv_dev_info *privd; 403 struct device *dev = &pf->pdev->dev; 404 struct iidc_rdma_core_dev_info *cdev; 405 int ret; 406 407 if (!ice_is_rdma_ena(pf)) { 408 dev_warn(dev, "RDMA is not supported on this device\n"); 409 return 0; 410 } 411 412 cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); 413 if (!cdev) 414 return -ENOMEM; 415 416 pf->cdev_info = cdev; 417 418 privd = kzalloc(sizeof(*privd), GFP_KERNEL); 419 if (!privd) { 420 ret = -ENOMEM; 421 goto err_privd_alloc; 422 } 423 424 privd->pf_id = pf->hw.pf_id; 425 ret = xa_alloc(&ice_aux_id, &pf->aux_idx, NULL, XA_LIMIT(1, INT_MAX), 426 GFP_KERNEL); 427 if (ret) { 428 dev_err(dev, "Failed to allocate device ID for AUX driver\n"); 429 ret = -ENOMEM; 430 goto err_alloc_xa; 431 } 432 433 cdev->iidc_priv = privd; 434 435 privd->hw_addr = (u8 __iomem *)pf->hw.hw_addr; 436 cdev->pdev = pf->pdev; 437 438 pf->cdev_info->rdma_protocol |= IIDC_RDMA_PROTOCOL_ROCEV2; 439 440 return 0; 441 442err_alloc_xa: 443 kfree(privd); 444err_privd_alloc: 445 kfree(cdev); 446 pf->cdev_info = NULL; 447 448 return ret; 449} 450 451/** 452 * ice_deinit_rdma - deinitialize RDMA on PF 453 * @pf: ptr to ice_pf 454 */ 455void ice_deinit_rdma(struct ice_pf *pf) 456{ 457 if (!ice_is_rdma_ena(pf)) 458 return; 459 460 xa_erase(&ice_aux_id, pf->aux_idx); 461 kfree(pf->cdev_info->iidc_priv); 462 kfree(pf->cdev_info); 463 pf->cdev_info = NULL; 464}
~/
Read-only file preview.