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