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