brintos

brintos / linux-shallow public Read only

0
0
Text · 8.9 KiB · 145b27f Raw
418 lines · c
1// SPDX-License-Identifier: GPL-2.02/* 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_auxiliary_drv struct13 * @pf: pointer to PF struct14 *15 * This function has to be called with a device_lock on the16 * pf->adev.dev to avoid race conditions.17 */18static struct iidc_auxiliary_drv *ice_get_auxiliary_drv(struct ice_pf *pf)19{20	struct auxiliary_device *adev;21 22	adev = pf->adev;23	if (!adev || !adev->dev.driver)24		return NULL;25 26	return container_of(adev->dev.driver, struct iidc_auxiliary_drv,27			    adrv.driver);28}29 30/**31 * ice_send_event_to_aux - send event to RDMA AUX driver32 * @pf: pointer to PF struct33 * @event: event struct34 */35void ice_send_event_to_aux(struct ice_pf *pf, struct iidc_event *event)36{37	struct iidc_auxiliary_drv *iadrv;38 39	if (WARN_ON_ONCE(!in_task()))40		return;41 42	mutex_lock(&pf->adev_mutex);43	if (!pf->adev)44		goto finish;45 46	device_lock(&pf->adev->dev);47	iadrv = ice_get_auxiliary_drv(pf);48	if (iadrv && iadrv->event_handler)49		iadrv->event_handler(pf, event);50	device_unlock(&pf->adev->dev);51finish:52	mutex_unlock(&pf->adev_mutex);53}54 55/**56 * ice_add_rdma_qset - Add Leaf Node for RDMA Qset57 * @pf: PF struct58 * @qset: Resource to be allocated59 */60int ice_add_rdma_qset(struct ice_pf *pf, struct iidc_rdma_qset_params *qset)61{62	u16 max_rdmaqs[ICE_MAX_TRAFFIC_CLASS];63	struct ice_vsi *vsi;64	struct device *dev;65	u32 qset_teid;66	u16 qs_handle;67	int status;68	int i;69 70	if (WARN_ON(!pf || !qset))71		return -EINVAL;72 73	dev = ice_pf_to_dev(pf);74 75	if (!ice_is_rdma_ena(pf))76		return -EINVAL;77 78	vsi = ice_get_main_vsi(pf);79	if (!vsi) {80		dev_err(dev, "RDMA QSet invalid VSI\n");81		return -EINVAL;82	}83 84	ice_for_each_traffic_class(i)85		max_rdmaqs[i] = 0;86 87	max_rdmaqs[qset->tc]++;88	qs_handle = qset->qs_handle;89 90	status = ice_cfg_vsi_rdma(vsi->port_info, vsi->idx, vsi->tc_cfg.ena_tc,91				  max_rdmaqs);92	if (status) {93		dev_err(dev, "Failed VSI RDMA Qset config\n");94		return status;95	}96 97	status = ice_ena_vsi_rdma_qset(vsi->port_info, vsi->idx, qset->tc,98				       &qs_handle, 1, &qset_teid);99	if (status) {100		dev_err(dev, "Failed VSI RDMA Qset enable\n");101		return status;102	}103	vsi->qset_handle[qset->tc] = qset->qs_handle;104	qset->teid = qset_teid;105 106	return 0;107}108EXPORT_SYMBOL_GPL(ice_add_rdma_qset);109 110/**111 * ice_del_rdma_qset - Delete leaf node for RDMA Qset112 * @pf: PF struct113 * @qset: Resource to be freed114 */115int ice_del_rdma_qset(struct ice_pf *pf, struct iidc_rdma_qset_params *qset)116{117	struct ice_vsi *vsi;118	u32 teid;119	u16 q_id;120 121	if (WARN_ON(!pf || !qset))122		return -EINVAL;123 124	vsi = ice_find_vsi(pf, qset->vport_id);125	if (!vsi) {126		dev_err(ice_pf_to_dev(pf), "RDMA Invalid VSI\n");127		return -EINVAL;128	}129 130	q_id = qset->qs_handle;131	teid = qset->teid;132 133	vsi->qset_handle[qset->tc] = 0;134 135	return ice_dis_vsi_rdma_qset(vsi->port_info, 1, &teid, &q_id);136}137EXPORT_SYMBOL_GPL(ice_del_rdma_qset);138 139/**140 * ice_rdma_request_reset - accept request from RDMA to perform a reset141 * @pf: struct for PF142 * @reset_type: type of reset143 */144int ice_rdma_request_reset(struct ice_pf *pf, enum iidc_reset_type reset_type)145{146	enum ice_reset_req reset;147 148	if (WARN_ON(!pf))149		return -EINVAL;150 151	switch (reset_type) {152	case IIDC_PFR:153		reset = ICE_RESET_PFR;154		break;155	case IIDC_CORER:156		reset = ICE_RESET_CORER;157		break;158	case IIDC_GLOBR:159		reset = ICE_RESET_GLOBR;160		break;161	default:162		dev_err(ice_pf_to_dev(pf), "incorrect reset request\n");163		return -EINVAL;164	}165 166	return ice_schedule_reset(pf, reset);167}168EXPORT_SYMBOL_GPL(ice_rdma_request_reset);169 170/**171 * ice_rdma_update_vsi_filter - update main VSI filters for RDMA172 * @pf: pointer to struct for PF173 * @vsi_id: VSI HW idx to update filter on174 * @enable: bool whether to enable or disable filters175 */176int ice_rdma_update_vsi_filter(struct ice_pf *pf, u16 vsi_id, bool enable)177{178	struct ice_vsi *vsi;179	int status;180 181	if (WARN_ON(!pf))182		return -EINVAL;183 184	vsi = ice_find_vsi(pf, vsi_id);185	if (!vsi)186		return -EINVAL;187 188	status = ice_cfg_rdma_fltr(&pf->hw, vsi->idx, enable);189	if (status) {190		dev_err(ice_pf_to_dev(pf), "Failed to  %sable RDMA filtering\n",191			enable ? "en" : "dis");192	} else {193		if (enable)194			vsi->info.q_opt_flags |= ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;195		else196			vsi->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;197	}198 199	return status;200}201EXPORT_SYMBOL_GPL(ice_rdma_update_vsi_filter);202 203/**204 * ice_get_qos_params - parse QoS params for RDMA consumption205 * @pf: pointer to PF struct206 * @qos: set of QoS values207 */208void ice_get_qos_params(struct ice_pf *pf, struct iidc_qos_params *qos)209{210	struct ice_dcbx_cfg *dcbx_cfg;211	unsigned int i;212	u32 up2tc;213 214	dcbx_cfg = &pf->hw.port_info->qos_cfg.local_dcbx_cfg;215	up2tc = rd32(&pf->hw, PRTDCB_TUP2TC);216 217	qos->num_tc = ice_dcb_get_num_tc(dcbx_cfg);218	for (i = 0; i < IIDC_MAX_USER_PRIORITY; i++)219		qos->up2tc[i] = (up2tc >> (i * 3)) & 0x7;220 221	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)222		qos->tc_info[i].rel_bw = dcbx_cfg->etscfg.tcbwtable[i];223 224	qos->pfc_mode = dcbx_cfg->pfc_mode;225	if (qos->pfc_mode == IIDC_DSCP_PFC_MODE)226		for (i = 0; i < IIDC_MAX_DSCP_MAPPING; i++)227			qos->dscp_map[i] = dcbx_cfg->dscp_map[i];228}229EXPORT_SYMBOL_GPL(ice_get_qos_params);230 231/**232 * ice_alloc_rdma_qvectors - Allocate vector resources for RDMA driver233 * @pf: board private structure to initialize234 */235static int ice_alloc_rdma_qvectors(struct ice_pf *pf)236{237	if (ice_is_rdma_ena(pf)) {238		int i;239 240		pf->msix_entries = kcalloc(pf->num_rdma_msix,241					   sizeof(*pf->msix_entries),242						  GFP_KERNEL);243		if (!pf->msix_entries)244			return -ENOMEM;245 246		/* RDMA is the only user of pf->msix_entries array */247		pf->rdma_base_vector = 0;248 249		for (i = 0; i < pf->num_rdma_msix; i++) {250			struct msix_entry *entry = &pf->msix_entries[i];251			struct msi_map map;252 253			map = ice_alloc_irq(pf, false);254			if (map.index < 0)255				break;256 257			entry->entry = map.index;258			entry->vector = map.virq;259		}260	}261	return 0;262}263 264/**265 * ice_free_rdma_qvector - free vector resources reserved for RDMA driver266 * @pf: board private structure to initialize267 */268static void ice_free_rdma_qvector(struct ice_pf *pf)269{270	int i;271 272	if (!pf->msix_entries)273		return;274 275	for (i = 0; i < pf->num_rdma_msix; i++) {276		struct msi_map map;277 278		map.index = pf->msix_entries[i].entry;279		map.virq = pf->msix_entries[i].vector;280		ice_free_irq(pf, map);281	}282 283	kfree(pf->msix_entries);284	pf->msix_entries = NULL;285}286 287/**288 * ice_adev_release - function to be mapped to AUX dev's release op289 * @dev: pointer to device to free290 */291static void ice_adev_release(struct device *dev)292{293	struct iidc_auxiliary_dev *iadev;294 295	iadev = container_of(dev, struct iidc_auxiliary_dev, adev.dev);296	kfree(iadev);297}298 299/**300 * ice_plug_aux_dev - allocate and register AUX device301 * @pf: pointer to pf struct302 */303int ice_plug_aux_dev(struct ice_pf *pf)304{305	struct iidc_auxiliary_dev *iadev;306	struct auxiliary_device *adev;307	int ret;308 309	/* if this PF doesn't support a technology that requires auxiliary310	 * devices, then gracefully exit311	 */312	if (!ice_is_rdma_ena(pf))313		return 0;314 315	iadev = kzalloc(sizeof(*iadev), GFP_KERNEL);316	if (!iadev)317		return -ENOMEM;318 319	adev = &iadev->adev;320	iadev->pf = pf;321 322	adev->id = pf->aux_idx;323	adev->dev.release = ice_adev_release;324	adev->dev.parent = &pf->pdev->dev;325	adev->name = pf->rdma_mode & IIDC_RDMA_PROTOCOL_ROCEV2 ? "roce" : "iwarp";326 327	ret = auxiliary_device_init(adev);328	if (ret) {329		kfree(iadev);330		return ret;331	}332 333	ret = auxiliary_device_add(adev);334	if (ret) {335		auxiliary_device_uninit(adev);336		return ret;337	}338 339	mutex_lock(&pf->adev_mutex);340	pf->adev = adev;341	mutex_unlock(&pf->adev_mutex);342 343	return 0;344}345 346/* ice_unplug_aux_dev - unregister and free AUX device347 * @pf: pointer to pf struct348 */349void ice_unplug_aux_dev(struct ice_pf *pf)350{351	struct auxiliary_device *adev;352 353	mutex_lock(&pf->adev_mutex);354	adev = pf->adev;355	pf->adev = NULL;356	mutex_unlock(&pf->adev_mutex);357 358	if (adev) {359		auxiliary_device_delete(adev);360		auxiliary_device_uninit(adev);361	}362}363 364/**365 * ice_init_rdma - initializes PF for RDMA use366 * @pf: ptr to ice_pf367 */368int ice_init_rdma(struct ice_pf *pf)369{370	struct device *dev = &pf->pdev->dev;371	int ret;372 373	if (!ice_is_rdma_ena(pf)) {374		dev_warn(dev, "RDMA is not supported on this device\n");375		return 0;376	}377 378	ret = xa_alloc(&ice_aux_id, &pf->aux_idx, NULL, XA_LIMIT(1, INT_MAX),379		       GFP_KERNEL);380	if (ret) {381		dev_err(dev, "Failed to allocate device ID for AUX driver\n");382		return -ENOMEM;383	}384 385	/* Reserve vector resources */386	ret = ice_alloc_rdma_qvectors(pf);387	if (ret < 0) {388		dev_err(dev, "failed to reserve vectors for RDMA\n");389		goto err_reserve_rdma_qvector;390	}391	pf->rdma_mode |= IIDC_RDMA_PROTOCOL_ROCEV2;392	ret = ice_plug_aux_dev(pf);393	if (ret)394		goto err_plug_aux_dev;395	return 0;396 397err_plug_aux_dev:398	ice_free_rdma_qvector(pf);399err_reserve_rdma_qvector:400	pf->adev = NULL;401	xa_erase(&ice_aux_id, pf->aux_idx);402	return ret;403}404 405/**406 * ice_deinit_rdma - deinitialize RDMA on PF407 * @pf: ptr to ice_pf408 */409void ice_deinit_rdma(struct ice_pf *pf)410{411	if (!ice_is_rdma_ena(pf))412		return;413 414	ice_unplug_aux_dev(pf);415	ice_free_rdma_qvector(pf);416	xa_erase(&ice_aux_id, pf->aux_idx);417}418