Merge tag 'soc-drivers-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-block.git] / 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
9 static DEFINE_XARRAY_ALLOC1(ice_aux_id);
10
11 /**
12  * ice_get_auxiliary_drv - retrieve iidc_auxiliary_drv struct
13  * @pf: pointer to PF struct
14  *
15  * This function has to be called with a device_lock on the
16  * pf->adev.dev to avoid race conditions.
17  */
18 static 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 driver
32  * @pf: pointer to PF struct
33  * @event: event struct
34  */
35 void 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);
51 finish:
52         mutex_unlock(&pf->adev_mutex);
53 }
54
55 /**
56  * ice_add_rdma_qset - Add Leaf Node for RDMA Qset
57  * @pf: PF struct
58  * @qset: Resource to be allocated
59  */
60 int 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 }
108 EXPORT_SYMBOL_GPL(ice_add_rdma_qset);
109
110 /**
111  * ice_del_rdma_qset - Delete leaf node for RDMA Qset
112  * @pf: PF struct
113  * @qset: Resource to be freed
114  */
115 int 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 }
137 EXPORT_SYMBOL_GPL(ice_del_rdma_qset);
138
139 /**
140  * ice_rdma_request_reset - accept request from RDMA to perform a reset
141  * @pf: struct for PF
142  * @reset_type: type of reset
143  */
144 int 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 }
168 EXPORT_SYMBOL_GPL(ice_rdma_request_reset);
169
170 /**
171  * ice_rdma_update_vsi_filter - update main VSI filters for RDMA
172  * @pf: pointer to struct for PF
173  * @vsi_id: VSI HW idx to update filter on
174  * @enable: bool whether to enable or disable filters
175  */
176 int 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                 else
196                         vsi->info.q_opt_flags &= ~ICE_AQ_VSI_Q_OPT_PE_FLTR_EN;
197         }
198
199         return status;
200 }
201 EXPORT_SYMBOL_GPL(ice_rdma_update_vsi_filter);
202
203 /**
204  * ice_get_qos_params - parse QoS params for RDMA consumption
205  * @pf: pointer to PF struct
206  * @qos: set of QoS values
207  */
208 void 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 }
229 EXPORT_SYMBOL_GPL(ice_get_qos_params);
230
231 /**
232  * ice_alloc_rdma_qvectors - Allocate vector resources for RDMA driver
233  * @pf: board private structure to initialize
234  */
235 static 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 driver
266  * @pf: board private structure to initialize
267  */
268 static 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 op
289  * @dev: pointer to device to free
290  */
291 static 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 device
301  * @pf: pointer to pf struct
302  */
303 int 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 auxiliary
310          * devices, then gracefully exit
311          */
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 device
347  * @pf: pointer to pf struct
348  */
349 void 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 use
366  * @pf: ptr to ice_pf
367  */
368 int 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
397 err_plug_aux_dev:
398         ice_free_rdma_qvector(pf);
399 err_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 PF
407  * @pf: ptr to ice_pf
408  */
409 void 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 }