File Index
Files and directories
Sign in
FILE

ice_idc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/intel/ice/ice_idc.c 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.