mempool/octeontx: probe fpavf PCIe devices
[dpdk.git] / drivers / mempool / octeontx / octeontx_fpavf.c
1 /*
2  *   BSD LICENSE
3  *
4  *   Copyright (C) Cavium Inc. 2017. All Right reserved.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in
14  *       the documentation and/or other materials provided with the
15  *       distribution.
16  *     * Neither the name of Cavium networks nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdbool.h>
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <errno.h>
40 #include <sys/mman.h>
41
42 #include <rte_atomic.h>
43 #include <rte_eal.h>
44 #include <rte_pci.h>
45 #include <rte_errno.h>
46 #include <rte_memory.h>
47 #include <rte_malloc.h>
48 #include <rte_spinlock.h>
49
50 #include "octeontx_fpavf.h"
51
52 struct fpavf_res {
53         void            *pool_stack_base;
54         void            *bar0;
55         uint64_t        stack_ln_ptr;
56         uint16_t        domain_id;
57         uint16_t        vf_id;  /* gpool_id */
58         uint16_t        sz128;  /* Block size in cache lines */
59         bool            is_inuse;
60 };
61
62 struct octeontx_fpadev {
63         rte_spinlock_t lock;
64         uint8_t total_gpool_cnt;
65         struct fpavf_res pool[FPA_VF_MAX];
66 };
67
68 static struct octeontx_fpadev fpadev;
69
70 static void
71 octeontx_fpavf_setup(void)
72 {
73         uint8_t i;
74         static bool init_once;
75
76         if (!init_once) {
77                 rte_spinlock_init(&fpadev.lock);
78                 fpadev.total_gpool_cnt = 0;
79
80                 for (i = 0; i < FPA_VF_MAX; i++) {
81
82                         fpadev.pool[i].domain_id = ~0;
83                         fpadev.pool[i].stack_ln_ptr = 0;
84                         fpadev.pool[i].sz128 = 0;
85                         fpadev.pool[i].bar0 = NULL;
86                         fpadev.pool[i].pool_stack_base = NULL;
87                         fpadev.pool[i].is_inuse = false;
88                 }
89                 init_once = 1;
90         }
91 }
92
93 static int
94 octeontx_fpavf_identify(void *bar0)
95 {
96         uint64_t val;
97         uint16_t domain_id;
98         uint16_t vf_id;
99         uint64_t stack_ln_ptr;
100
101         val = fpavf_read64((void *)((uintptr_t)bar0 +
102                                 FPA_VF_VHAURA_CNT_THRESHOLD(0)));
103
104         domain_id = (val >> 8) & 0xffff;
105         vf_id = (val >> 24) & 0xffff;
106
107         stack_ln_ptr = fpavf_read64((void *)((uintptr_t)bar0 +
108                                         FPA_VF_VHPOOL_THRESHOLD(0)));
109         if (vf_id >= FPA_VF_MAX) {
110                 fpavf_log_err("vf_id(%d) greater than max vf (32)\n", vf_id);
111                 return -1;
112         }
113
114         if (fpadev.pool[vf_id].is_inuse) {
115                 fpavf_log_err("vf_id %d is_inuse\n", vf_id);
116                 return -1;
117         }
118
119         fpadev.pool[vf_id].domain_id = domain_id;
120         fpadev.pool[vf_id].vf_id = vf_id;
121         fpadev.pool[vf_id].bar0 = bar0;
122         fpadev.pool[vf_id].stack_ln_ptr = stack_ln_ptr;
123
124         /* SUCCESS */
125         return vf_id;
126 }
127
128 /* FPAVF pcie device aka mempool probe */
129 static int
130 fpavf_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
131 {
132         uint8_t *idreg;
133         int res;
134         struct fpavf_res *fpa;
135
136         RTE_SET_USED(pci_drv);
137         RTE_SET_USED(fpa);
138
139         /* For secondary processes, the primary has done all the work */
140         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
141                 return 0;
142
143         if (pci_dev->mem_resource[0].addr == NULL) {
144                 fpavf_log_err("Empty bars %p ", pci_dev->mem_resource[0].addr);
145                 return -ENODEV;
146         }
147         idreg = pci_dev->mem_resource[0].addr;
148
149         octeontx_fpavf_setup();
150
151         res = octeontx_fpavf_identify(idreg);
152         if (res < 0)
153                 return -1;
154
155         fpa = &fpadev.pool[res];
156         fpadev.total_gpool_cnt++;
157         rte_wmb();
158
159         fpavf_log_dbg("total_fpavfs %d bar0 %p domain %d vf %d stk_ln_ptr 0x%x",
160                        fpadev.total_gpool_cnt, fpa->bar0, fpa->domain_id,
161                        fpa->vf_id, (unsigned int)fpa->stack_ln_ptr);
162
163         return 0;
164 }
165
166 static const struct rte_pci_id pci_fpavf_map[] = {
167         {
168                 RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM,
169                                 PCI_DEVICE_ID_OCTEONTX_FPA_VF)
170         },
171         {
172                 .vendor_id = 0,
173         },
174 };
175
176 static struct rte_pci_driver pci_fpavf = {
177         .id_table = pci_fpavf_map,
178         .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_IOVA_AS_VA,
179         .probe = fpavf_probe,
180 };
181
182 RTE_PMD_REGISTER_PCI(octeontx_fpavf, pci_fpavf);