common/cnxk: add NIX Tx queue management API
[dpdk.git] / drivers / common / cnxk / roc_nix.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 bool
9 roc_nix_is_lbk(struct roc_nix *roc_nix)
10 {
11         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
12
13         return nix->lbk_link;
14 }
15
16 int
17 roc_nix_get_base_chan(struct roc_nix *roc_nix)
18 {
19         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
20
21         return nix->rx_chan_base;
22 }
23
24 uint16_t
25 roc_nix_get_vwqe_interval(struct roc_nix *roc_nix)
26 {
27         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
28
29         return nix->vwqe_interval;
30 }
31
32 bool
33 roc_nix_is_sdp(struct roc_nix *roc_nix)
34 {
35         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
36
37         return nix->sdp_link;
38 }
39
40 bool
41 roc_nix_is_pf(struct roc_nix *roc_nix)
42 {
43         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
44
45         return !dev_is_vf(&nix->dev);
46 }
47
48 int
49 roc_nix_get_pf(struct roc_nix *roc_nix)
50 {
51         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
52         struct dev *dev = &nix->dev;
53
54         return dev_get_pf(dev->pf_func);
55 }
56
57 int
58 roc_nix_get_vf(struct roc_nix *roc_nix)
59 {
60         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
61         struct dev *dev = &nix->dev;
62
63         return dev_get_vf(dev->pf_func);
64 }
65
66 bool
67 roc_nix_is_vf_or_sdp(struct roc_nix *roc_nix)
68 {
69         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
70
71         return (dev_is_vf(&nix->dev) != 0) || roc_nix_is_sdp(roc_nix);
72 }
73
74 uint16_t
75 roc_nix_get_pf_func(struct roc_nix *roc_nix)
76 {
77         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
78         struct dev *dev = &nix->dev;
79
80         return dev->pf_func;
81 }
82
83 int
84 roc_nix_max_pkt_len(struct roc_nix *roc_nix)
85 {
86         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
87
88         if (roc_model_is_cn9k())
89                 return NIX_CN9K_MAX_HW_FRS;
90
91         if (nix->lbk_link || roc_nix_is_sdp(roc_nix))
92                 return NIX_LBK_MAX_HW_FRS;
93
94         return NIX_RPM_MAX_HW_FRS;
95 }
96
97 int
98 roc_nix_lf_alloc(struct roc_nix *roc_nix, uint32_t nb_rxq, uint32_t nb_txq,
99                  uint64_t rx_cfg)
100 {
101         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
102         struct mbox *mbox = (&nix->dev)->mbox;
103         struct nix_lf_alloc_req *req;
104         struct nix_lf_alloc_rsp *rsp;
105         int rc = -ENOSPC;
106
107         req = mbox_alloc_msg_nix_lf_alloc(mbox);
108         if (req == NULL)
109                 return rc;
110         req->rq_cnt = nb_rxq;
111         req->sq_cnt = nb_txq;
112         req->cq_cnt = nb_rxq;
113         /* XQESZ can be W64 or W16 */
114         req->xqe_sz = NIX_XQESZ_W16;
115         req->rss_sz = nix->reta_sz;
116         req->rss_grps = ROC_NIX_RSS_GRPS;
117         req->npa_func = idev_npa_pffunc_get();
118         req->rx_cfg = rx_cfg;
119
120         if (!roc_nix->rss_tag_as_xor)
121                 req->flags = NIX_LF_RSS_TAG_LSB_AS_ADDER;
122
123         rc = mbox_process_msg(mbox, (void *)&rsp);
124         if (rc)
125                 goto fail;
126
127         nix->sqb_size = rsp->sqb_size;
128         nix->tx_chan_base = rsp->tx_chan_base;
129         nix->rx_chan_base = rsp->rx_chan_base;
130         if (roc_nix_is_lbk(roc_nix) && roc_nix->enable_loop)
131                 nix->tx_chan_base = rsp->rx_chan_base;
132         nix->rx_chan_cnt = rsp->rx_chan_cnt;
133         nix->tx_chan_cnt = rsp->tx_chan_cnt;
134         nix->lso_tsov4_idx = rsp->lso_tsov4_idx;
135         nix->lso_tsov6_idx = rsp->lso_tsov6_idx;
136         nix->lf_tx_stats = rsp->lf_tx_stats;
137         nix->lf_rx_stats = rsp->lf_rx_stats;
138         nix->cints = rsp->cints;
139         roc_nix->cints = rsp->cints;
140         nix->qints = rsp->qints;
141         nix->ptp_en = rsp->hw_rx_tstamp_en;
142         roc_nix->rx_ptp_ena = rsp->hw_rx_tstamp_en;
143         nix->cgx_links = rsp->cgx_links;
144         nix->lbk_links = rsp->lbk_links;
145         nix->sdp_links = rsp->sdp_links;
146         nix->tx_link = rsp->tx_link;
147         nix->nb_rx_queues = nb_rxq;
148         nix->nb_tx_queues = nb_txq;
149         nix->sqs = plt_zmalloc(sizeof(struct roc_nix_sq *) * nb_txq, 0);
150         if (!nix->sqs)
151                 return -ENOMEM;
152 fail:
153         return rc;
154 }
155
156 int
157 roc_nix_lf_free(struct roc_nix *roc_nix)
158 {
159         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
160         struct mbox *mbox = (&nix->dev)->mbox;
161         struct nix_lf_free_req *req;
162         struct ndc_sync_op *ndc_req;
163         int rc = -ENOSPC;
164
165         plt_free(nix->sqs);
166         nix->sqs = NULL;
167
168         /* Sync NDC-NIX for LF */
169         ndc_req = mbox_alloc_msg_ndc_sync_op(mbox);
170         if (ndc_req == NULL)
171                 return rc;
172         ndc_req->nix_lf_tx_sync = 1;
173         ndc_req->nix_lf_rx_sync = 1;
174         rc = mbox_process(mbox);
175         if (rc)
176                 plt_err("Error on NDC-NIX-[TX, RX] LF sync, rc %d", rc);
177
178         req = mbox_alloc_msg_nix_lf_free(mbox);
179         if (req == NULL)
180                 return -ENOSPC;
181         /* Let AF driver free all this nix lf's
182          * NPC entries allocated using NPC MBOX.
183          */
184         req->flags = 0;
185
186         return mbox_process(mbox);
187 }
188
189 static inline int
190 nix_lf_attach(struct dev *dev)
191 {
192         struct mbox *mbox = dev->mbox;
193         struct rsrc_attach_req *req;
194         int rc = -ENOSPC;
195
196         /* Attach NIX(lf) */
197         req = mbox_alloc_msg_attach_resources(mbox);
198         if (req == NULL)
199                 return rc;
200         req->modify = true;
201         req->nixlf = true;
202
203         return mbox_process(mbox);
204 }
205
206 static inline int
207 nix_lf_get_msix_offset(struct dev *dev, struct nix *nix)
208 {
209         struct msix_offset_rsp *msix_rsp;
210         struct mbox *mbox = dev->mbox;
211         int rc;
212
213         /* Get MSIX vector offsets */
214         mbox_alloc_msg_msix_offset(mbox);
215         rc = mbox_process_msg(mbox, (void *)&msix_rsp);
216         if (rc == 0)
217                 nix->msixoff = msix_rsp->nix_msixoff;
218
219         return rc;
220 }
221
222 static inline int
223 nix_lf_detach(struct nix *nix)
224 {
225         struct mbox *mbox = (&nix->dev)->mbox;
226         struct rsrc_detach_req *req;
227         int rc = -ENOSPC;
228
229         req = mbox_alloc_msg_detach_resources(mbox);
230         if (req == NULL)
231                 return rc;
232         req->partial = true;
233         req->nixlf = true;
234
235         return mbox_process(mbox);
236 }
237
238 static int
239 roc_nix_get_hw_info(struct roc_nix *roc_nix)
240 {
241         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
242         struct mbox *mbox = (&nix->dev)->mbox;
243         struct nix_hw_info *hw_info;
244         int rc;
245
246         mbox_alloc_msg_nix_get_hw_info(mbox);
247         rc = mbox_process_msg(mbox, (void *)&hw_info);
248         if (rc == 0)
249                 nix->vwqe_interval = hw_info->vwqe_delay;
250
251         return rc;
252 }
253
254 static void
255 sdp_lbk_id_update(struct plt_pci_device *pci_dev, struct nix *nix)
256 {
257         nix->sdp_link = false;
258         nix->lbk_link = false;
259
260         /* Update SDP/LBK link based on PCI device id */
261         switch (pci_dev->id.device_id) {
262         case PCI_DEVID_CNXK_RVU_SDP_PF:
263         case PCI_DEVID_CNXK_RVU_SDP_VF:
264                 nix->sdp_link = true;
265                 break;
266         case PCI_DEVID_CNXK_RVU_AF_VF:
267                 nix->lbk_link = true;
268                 break;
269         default:
270                 break;
271         }
272 }
273
274 static inline uint64_t
275 nix_get_blkaddr(struct dev *dev)
276 {
277         uint64_t reg;
278
279         /* Reading the discovery register to know which NIX is the LF
280          * attached to.
281          */
282         reg = plt_read64(dev->bar2 +
283                          RVU_PF_BLOCK_ADDRX_DISC(RVU_BLOCK_ADDR_NIX0));
284
285         return reg & 0x1FFULL ? RVU_BLOCK_ADDR_NIX0 : RVU_BLOCK_ADDR_NIX1;
286 }
287
288 int
289 roc_nix_dev_init(struct roc_nix *roc_nix)
290 {
291         enum roc_nix_rss_reta_sz reta_sz;
292         struct plt_pci_device *pci_dev;
293         uint16_t max_sqb_count;
294         uint64_t blkaddr;
295         struct dev *dev;
296         struct nix *nix;
297         int rc;
298
299         if (roc_nix == NULL || roc_nix->pci_dev == NULL)
300                 return NIX_ERR_PARAM;
301
302         reta_sz = roc_nix->reta_sz;
303         if (reta_sz != 0 && reta_sz != 64 && reta_sz != 128 && reta_sz != 256)
304                 return NIX_ERR_PARAM;
305
306         if (reta_sz == 0)
307                 reta_sz = ROC_NIX_RSS_RETA_SZ_64;
308
309         max_sqb_count = roc_nix->max_sqb_count;
310         max_sqb_count = PLT_MIN(max_sqb_count, NIX_MAX_SQB);
311         max_sqb_count = PLT_MAX(max_sqb_count, NIX_MIN_SQB);
312         roc_nix->max_sqb_count = max_sqb_count;
313
314         PLT_STATIC_ASSERT(sizeof(struct nix) <= ROC_NIX_MEM_SZ);
315         nix = roc_nix_to_nix_priv(roc_nix);
316         pci_dev = roc_nix->pci_dev;
317         dev = &nix->dev;
318
319         if (nix->dev.drv_inited)
320                 return 0;
321
322         if (dev->mbox_active)
323                 goto skip_dev_init;
324
325         memset(nix, 0, sizeof(*nix));
326         /* Initialize device  */
327         rc = dev_init(dev, pci_dev);
328         if (rc) {
329                 plt_err("Failed to init roc device");
330                 goto fail;
331         }
332
333 skip_dev_init:
334         dev->roc_nix = roc_nix;
335
336         nix->lmt_base = dev->lmt_base;
337         /* Expose base LMT line address for
338          * "Per Core LMT line" mode.
339          */
340         roc_nix->lmt_base = dev->lmt_base;
341
342         /* Attach NIX LF */
343         rc = nix_lf_attach(dev);
344         if (rc)
345                 goto dev_fini;
346
347         blkaddr = nix_get_blkaddr(dev);
348         nix->is_nix1 = (blkaddr == RVU_BLOCK_ADDR_NIX1);
349
350         /* Calculating base address based on which NIX block LF
351          * is attached to.
352          */
353         nix->base = dev->bar2 + (blkaddr << 20);
354
355         /* Get NIX MSIX offset */
356         rc = nix_lf_get_msix_offset(dev, nix);
357         if (rc)
358                 goto lf_detach;
359
360         /* Update nix context */
361         sdp_lbk_id_update(pci_dev, nix);
362         nix->pci_dev = pci_dev;
363         nix->reta_sz = reta_sz;
364         nix->mtu = ROC_NIX_DEFAULT_HW_FRS;
365
366         /* Register error and ras interrupts */
367         rc = nix_register_irqs(nix);
368         if (rc)
369                 goto lf_detach;
370
371         /* Get NIX HW info */
372         roc_nix_get_hw_info(roc_nix);
373         nix->dev.drv_inited = true;
374
375         return 0;
376 lf_detach:
377         nix_lf_detach(nix);
378 dev_fini:
379         rc |= dev_fini(dev, pci_dev);
380 fail:
381         return rc;
382 }
383
384 int
385 roc_nix_dev_fini(struct roc_nix *roc_nix)
386 {
387         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
388         int rc = 0;
389
390         if (nix == NULL)
391                 return NIX_ERR_PARAM;
392
393         if (!nix->dev.drv_inited)
394                 goto fini;
395
396         nix_unregister_irqs(nix);
397
398         rc = nix_lf_detach(nix);
399         nix->dev.drv_inited = false;
400 fini:
401         rc |= dev_fini(&nix->dev, nix->pci_dev);
402         return rc;
403 }