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