e723ee7f8465dfd421014c21a222ff5d1313a697
[dpdk.git] / drivers / common / cnxk / roc_cpt.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include "roc_api.h"
6 #include "roc_priv.h"
7
8 int
9 roc_cpt_rxc_time_cfg(struct roc_cpt *roc_cpt, struct roc_cpt_rxc_time_cfg *cfg)
10 {
11         struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
12         struct cpt_rxc_time_cfg_req *req;
13         struct dev *dev = &cpt->dev;
14
15         req = mbox_alloc_msg_cpt_rxc_time_cfg(dev->mbox);
16         if (req == NULL)
17                 return -ENOSPC;
18
19         req->blkaddr = 0;
20
21         /* The step value is in microseconds. */
22         req->step = cfg->step;
23
24         /* The timeout will be: limit * step microseconds */
25         req->zombie_limit = cfg->zombie_limit;
26         req->zombie_thres = cfg->zombie_thres;
27
28         /* The timeout will be: limit * step microseconds */
29         req->active_limit = cfg->active_limit;
30         req->active_thres = cfg->active_thres;
31
32         return mbox_process(dev->mbox);
33 }
34
35 int
36 cpt_get_msix_offset(struct dev *dev, struct msix_offset_rsp **msix_rsp)
37 {
38         struct mbox *mbox = dev->mbox;
39         int rc;
40
41         /* Get MSIX vector offsets */
42         mbox_alloc_msg_msix_offset(mbox);
43         rc = mbox_process_msg(mbox, (void *)msix_rsp);
44
45         return rc;
46 }
47
48 int
49 cpt_lfs_attach(struct dev *dev, uint8_t blkaddr, bool modify, uint16_t nb_lf)
50 {
51         struct mbox *mbox = dev->mbox;
52         struct rsrc_attach_req *req;
53
54         if (blkaddr != RVU_BLOCK_ADDR_CPT0 && blkaddr != RVU_BLOCK_ADDR_CPT1)
55                 return -EINVAL;
56
57         /* Attach CPT(lf) */
58         req = mbox_alloc_msg_attach_resources(mbox);
59         if (req == NULL)
60                 return -ENOSPC;
61
62         req->cptlfs = nb_lf;
63         req->modify = modify;
64         req->cpt_blkaddr = blkaddr;
65
66         return mbox_process(mbox);
67 }
68
69 int
70 cpt_lfs_detach(struct dev *dev)
71 {
72         struct mbox *mbox = dev->mbox;
73         struct rsrc_detach_req *req;
74
75         req = mbox_alloc_msg_detach_resources(mbox);
76         if (req == NULL)
77                 return -ENOSPC;
78
79         req->cptlfs = 1;
80         req->partial = 1;
81
82         return mbox_process(mbox);
83 }
84
85 static int
86 cpt_available_lfs_get(struct dev *dev, uint16_t *nb_lf)
87 {
88         struct mbox *mbox = dev->mbox;
89         struct free_rsrcs_rsp *rsp;
90         int rc;
91
92         mbox_alloc_msg_free_rsrc_cnt(mbox);
93
94         rc = mbox_process_msg(mbox, (void *)&rsp);
95         if (rc)
96                 return -EIO;
97
98         *nb_lf = rsp->cpt;
99         return 0;
100 }
101
102 int
103 cpt_lfs_alloc(struct dev *dev, uint8_t eng_grpmsk, uint8_t blkaddr,
104               bool inl_dev_sso)
105 {
106         struct cpt_lf_alloc_req_msg *req;
107         struct mbox *mbox = dev->mbox;
108
109         if (blkaddr != RVU_BLOCK_ADDR_CPT0 && blkaddr != RVU_BLOCK_ADDR_CPT1)
110                 return -EINVAL;
111
112         PLT_SET_USED(inl_dev_sso);
113
114         req = mbox_alloc_msg_cpt_lf_alloc(mbox);
115         req->nix_pf_func = 0;
116         req->sso_pf_func = idev_sso_pffunc_get();
117         req->eng_grpmsk = eng_grpmsk;
118         req->blkaddr = blkaddr;
119
120         return mbox_process(mbox);
121 }
122
123 int
124 cpt_lfs_free(struct dev *dev)
125 {
126         mbox_alloc_msg_cpt_lf_free(dev->mbox);
127
128         return mbox_process(dev->mbox);
129 }
130
131 static int
132 cpt_hardware_caps_get(struct dev *dev, union cpt_eng_caps *hw_caps)
133 {
134         struct cpt_caps_rsp_msg *rsp;
135         int ret;
136
137         mbox_alloc_msg_cpt_caps_get(dev->mbox);
138
139         ret = mbox_process_msg(dev->mbox, (void *)&rsp);
140         if (ret)
141                 return -EIO;
142
143         mbox_memcpy(hw_caps, rsp->eng_caps,
144                     sizeof(union cpt_eng_caps) * CPT_MAX_ENG_TYPES);
145
146         return 0;
147 }
148
149 int
150 roc_cpt_dev_configure(struct roc_cpt *roc_cpt, int nb_lf)
151 {
152         struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
153         uint8_t blkaddr = RVU_BLOCK_ADDR_CPT0;
154         struct msix_offset_rsp *rsp;
155         uint8_t eng_grpmsk;
156         int rc, i;
157
158         /* Request LF resources */
159         rc = cpt_lfs_attach(&cpt->dev, blkaddr, false, nb_lf);
160         if (rc)
161                 return rc;
162
163         eng_grpmsk = (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_AE]) |
164                      (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_SE]) |
165                      (1 << roc_cpt->eng_grp[CPT_ENG_TYPE_IE]);
166
167         rc = cpt_lfs_alloc(&cpt->dev, eng_grpmsk, blkaddr, false);
168         if (rc)
169                 goto lfs_detach;
170
171         rc = cpt_get_msix_offset(&cpt->dev, &rsp);
172         if (rc)
173                 goto lfs_free;
174
175         for (i = 0; i < nb_lf; i++)
176                 cpt->lf_msix_off[i] =
177                         (cpt->lf_blkaddr[i] == RVU_BLOCK_ADDR_CPT1) ?
178                                 rsp->cpt1_lf_msixoff[i] :
179                                 rsp->cptlf_msixoff[i];
180
181         roc_cpt->nb_lf = nb_lf;
182
183         return 0;
184
185 lfs_free:
186         cpt_lfs_free(&cpt->dev);
187 lfs_detach:
188         cpt_lfs_detach(&cpt->dev);
189         return rc;
190 }
191
192 uint64_t
193 cpt_get_blkaddr(struct dev *dev)
194 {
195         uint64_t reg;
196         uint64_t off;
197
198         /* Reading the discovery register to know which CPT is the LF
199          * attached to. Assume CPT LF's of only one block are attached
200          * to a pffunc.
201          */
202         if (dev_is_vf(dev))
203                 off = RVU_VF_BLOCK_ADDRX_DISC(RVU_BLOCK_ADDR_CPT1);
204         else
205                 off = RVU_PF_BLOCK_ADDRX_DISC(RVU_BLOCK_ADDR_CPT1);
206
207         reg = plt_read64(dev->bar2 + off);
208
209         return reg & 0x1FFULL ? RVU_BLOCK_ADDR_CPT1 : RVU_BLOCK_ADDR_CPT0;
210 }
211
212 int
213 roc_cpt_dev_init(struct roc_cpt *roc_cpt)
214 {
215         struct plt_pci_device *pci_dev;
216         uint16_t nb_lf_avail;
217         struct dev *dev;
218         struct cpt *cpt;
219         int rc;
220
221         if (roc_cpt == NULL || roc_cpt->pci_dev == NULL)
222                 return -EINVAL;
223
224         PLT_STATIC_ASSERT(sizeof(struct cpt) <= ROC_CPT_MEM_SZ);
225
226         cpt = roc_cpt_to_cpt_priv(roc_cpt);
227         memset(cpt, 0, sizeof(*cpt));
228         pci_dev = roc_cpt->pci_dev;
229         dev = &cpt->dev;
230
231         /* Initialize device  */
232         rc = dev_init(dev, pci_dev);
233         if (rc) {
234                 plt_err("Failed to init roc device");
235                 goto fail;
236         }
237
238         cpt->pci_dev = pci_dev;
239         roc_cpt->lmt_base = dev->lmt_base;
240
241         rc = cpt_hardware_caps_get(dev, roc_cpt->hw_caps);
242         if (rc) {
243                 plt_err("Could not determine hardware capabilities");
244                 goto fail;
245         }
246
247         rc = cpt_available_lfs_get(&cpt->dev, &nb_lf_avail);
248         if (rc) {
249                 plt_err("Could not get available lfs");
250                 goto fail;
251         }
252
253         /* Reserve 1 CPT LF for inline inbound */
254         nb_lf_avail = PLT_MIN(nb_lf_avail, ROC_CPT_MAX_LFS - 1);
255
256         roc_cpt->nb_lf_avail = nb_lf_avail;
257
258         dev->roc_cpt = roc_cpt;
259
260         /* Set it to idev if not already present */
261         if (!roc_idev_cpt_get())
262                 roc_idev_cpt_set(roc_cpt);
263
264         return 0;
265
266 fail:
267         return rc;
268 }
269
270 int
271 roc_cpt_dev_fini(struct roc_cpt *roc_cpt)
272 {
273         struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
274
275         if (cpt == NULL)
276                 return -EINVAL;
277
278         /* Remove idev references */
279         if (roc_idev_cpt_get() == roc_cpt)
280                 roc_idev_cpt_set(NULL);
281
282         roc_cpt->nb_lf_avail = 0;
283
284         roc_cpt->lmt_base = 0;
285
286         return dev_fini(&cpt->dev, cpt->pci_dev);
287 }
288
289 void
290 roc_cpt_dev_clear(struct roc_cpt *roc_cpt)
291 {
292         struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
293         int i;
294
295         if (cpt == NULL)
296                 return;
297
298         for (i = 0; i < roc_cpt->nb_lf; i++)
299                 cpt->lf_msix_off[i] = 0;
300
301         roc_cpt->nb_lf = 0;
302
303         cpt_lfs_free(&cpt->dev);
304
305         cpt_lfs_detach(&cpt->dev);
306 }
307
308 int
309 roc_cpt_eng_grp_add(struct roc_cpt *roc_cpt, enum cpt_eng_type eng_type)
310 {
311         struct cpt *cpt = roc_cpt_to_cpt_priv(roc_cpt);
312         struct dev *dev = &cpt->dev;
313         struct cpt_eng_grp_req *req;
314         struct cpt_eng_grp_rsp *rsp;
315         int ret;
316
317         req = mbox_alloc_msg_cpt_eng_grp_get(dev->mbox);
318         if (req == NULL)
319                 return -EIO;
320
321         switch (eng_type) {
322         case CPT_ENG_TYPE_AE:
323         case CPT_ENG_TYPE_SE:
324         case CPT_ENG_TYPE_IE:
325                 break;
326         default:
327                 return -EINVAL;
328         }
329
330         req->eng_type = eng_type;
331         ret = mbox_process_msg(dev->mbox, (void *)&rsp);
332         if (ret)
333                 return -EIO;
334
335         if (rsp->eng_grp_num > 8) {
336                 plt_err("Invalid CPT engine group");
337                 return -ENOTSUP;
338         }
339
340         roc_cpt->eng_grp[eng_type] = rsp->eng_grp_num;
341
342         return rsp->eng_grp_num;
343 }