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