New upstream version 17.08
[deb_dpdk.git] / drivers / event / octeontx / ssovf_probe.c
1 /*
2  *   BSD LICENSE
3  *
4  *   Copyright (C) Cavium, Inc. 2017.
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, Inc 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 <rte_atomic.h>
34 #include <rte_common.h>
35 #include <rte_eal.h>
36 #include <rte_io.h>
37 #include <rte_pci.h>
38
39 #include "ssovf_evdev.h"
40
41 struct ssovf_res {
42         uint16_t domain;
43         uint16_t vfid;
44         void *bar0;
45         void *bar2;
46 };
47
48 struct ssowvf_res {
49         uint16_t domain;
50         uint16_t vfid;
51         void *bar0;
52         void *bar2;
53         void *bar4;
54 };
55
56 struct ssowvf_identify {
57         uint16_t domain;
58         uint16_t vfid;
59 };
60
61 struct ssodev {
62         uint8_t total_ssovfs;
63         uint8_t total_ssowvfs;
64         struct ssovf_res grp[SSO_MAX_VHGRP];
65         struct ssowvf_res hws[SSO_MAX_VHWS];
66 };
67
68 static struct ssodev sdev;
69
70 /* Interface functions */
71 int
72 octeontx_ssovf_info(struct octeontx_ssovf_info *info)
73 {
74         uint8_t i;
75         uint16_t domain;
76
77         if (rte_eal_process_type() != RTE_PROC_PRIMARY || info == NULL)
78                 return -EINVAL;
79
80         if (sdev.total_ssovfs == 0 || sdev.total_ssowvfs == 0)
81                 return -ENODEV;
82
83         domain = sdev.grp[0].domain;
84         for (i = 0; i < sdev.total_ssovfs; i++) {
85                 /* Check vfid's are contiguous and belong to same domain */
86                 if (sdev.grp[i].vfid != i ||
87                         sdev.grp[i].bar0 == NULL ||
88                         sdev.grp[i].domain != domain) {
89                         ssovf_log_err("GRP error, vfid=%d/%d domain=%d/%d %p",
90                                 i, sdev.grp[i].vfid,
91                                 domain, sdev.grp[i].domain,
92                                 sdev.grp[i].bar0);
93                         return -EINVAL;
94                 }
95         }
96
97         for (i = 0; i < sdev.total_ssowvfs; i++) {
98                 /* Check vfid's are contiguous and belong to same domain */
99                 if (sdev.hws[i].vfid != i ||
100                         sdev.hws[i].bar0 == NULL ||
101                         sdev.hws[i].domain != domain) {
102                         ssovf_log_err("HWS error, vfid=%d/%d domain=%d/%d %p",
103                                 i, sdev.hws[i].vfid,
104                                 domain, sdev.hws[i].domain,
105                                 sdev.hws[i].bar0);
106                         return -EINVAL;
107                 }
108         }
109
110         info->domain = domain;
111         info->total_ssovfs = sdev.total_ssovfs;
112         info->total_ssowvfs = sdev.total_ssowvfs;
113         return 0;
114 }
115
116 void*
117 octeontx_ssovf_bar(enum octeontx_ssovf_type type, uint8_t id, uint8_t bar)
118 {
119         if (rte_eal_process_type() != RTE_PROC_PRIMARY ||
120                         type > OCTEONTX_SSO_HWS)
121                 return NULL;
122
123         if (type == OCTEONTX_SSO_GROUP) {
124                 if (id >= sdev.total_ssovfs)
125                         return NULL;
126         } else {
127                 if (id >= sdev.total_ssowvfs)
128                         return NULL;
129         }
130
131         if (type == OCTEONTX_SSO_GROUP) {
132                 switch (bar) {
133                 case 0:
134                         return sdev.grp[id].bar0;
135                 case 2:
136                         return sdev.grp[id].bar2;
137                 default:
138                         return NULL;
139                 }
140         } else {
141                 switch (bar) {
142                 case 0:
143                         return sdev.hws[id].bar0;
144                 case 2:
145                         return sdev.hws[id].bar2;
146                 case 4:
147                         return sdev.hws[id].bar4;
148                 default:
149                         return NULL;
150                 }
151         }
152 }
153
154 /* SSOWVF pcie device aka event port probe */
155
156 static int
157 ssowvf_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
158 {
159         uint16_t vfid;
160         struct ssowvf_res *res;
161         struct ssowvf_identify *id;
162
163         RTE_SET_USED(pci_drv);
164
165         /* For secondary processes, the primary has done all the work */
166         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
167                 return 0;
168
169         if (pci_dev->mem_resource[0].addr == NULL ||
170                         pci_dev->mem_resource[2].addr == NULL ||
171                         pci_dev->mem_resource[4].addr == NULL) {
172                 ssovf_log_err("Empty bars %p %p %p",
173                                 pci_dev->mem_resource[0].addr,
174                                 pci_dev->mem_resource[2].addr,
175                                 pci_dev->mem_resource[4].addr);
176                 return -ENODEV;
177         }
178
179         if (pci_dev->mem_resource[4].len != SSOW_BAR4_LEN) {
180                 ssovf_log_err("Bar4 len mismatch %d != %d",
181                         SSOW_BAR4_LEN, (int)pci_dev->mem_resource[4].len);
182                 return -EINVAL;
183         }
184
185         id = pci_dev->mem_resource[4].addr;
186         vfid = id->vfid;
187         if (vfid >= SSO_MAX_VHWS) {
188                 ssovf_log_err("Invalid vfid(%d/%d)", vfid, SSO_MAX_VHWS);
189                 return -EINVAL;
190         }
191
192         res = &sdev.hws[vfid];
193         res->vfid = vfid;
194         res->bar0 = pci_dev->mem_resource[0].addr;
195         res->bar2 = pci_dev->mem_resource[2].addr;
196         res->bar4 = pci_dev->mem_resource[4].addr;
197         res->domain = id->domain;
198
199         sdev.total_ssowvfs++;
200         rte_wmb();
201         ssovf_log_dbg("Domain=%d hws=%d total_ssowvfs=%d", res->domain,
202                         res->vfid, sdev.total_ssowvfs);
203         return 0;
204 }
205
206 static const struct rte_pci_id pci_ssowvf_map[] = {
207         {
208                 RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM,
209                                 PCI_DEVICE_ID_OCTEONTX_SSOWS_VF)
210         },
211         {
212                 .vendor_id = 0,
213         },
214 };
215
216 static struct rte_pci_driver pci_ssowvf = {
217         .id_table = pci_ssowvf_map,
218         .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
219         .probe = ssowvf_probe,
220 };
221
222 RTE_PMD_REGISTER_PCI(octeontx_ssowvf, pci_ssowvf);
223
224 /* SSOVF pcie device aka event queue probe */
225
226 static int
227 ssovf_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
228 {
229         uint64_t val;
230         uint16_t vfid;
231         uint8_t *idreg;
232         struct ssovf_res *res;
233
234         RTE_SET_USED(pci_drv);
235
236         /* For secondary processes, the primary has done all the work */
237         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
238                 return 0;
239
240         if (pci_dev->mem_resource[0].addr == NULL ||
241                         pci_dev->mem_resource[2].addr == NULL) {
242                 ssovf_log_err("Empty bars %p %p",
243                         pci_dev->mem_resource[0].addr,
244                         pci_dev->mem_resource[2].addr);
245                 return -ENODEV;
246         }
247         idreg = pci_dev->mem_resource[0].addr;
248         idreg += SSO_VHGRP_AQ_THR;
249         val = rte_read64(idreg);
250
251         /* Write back the default value of aq_thr */
252         rte_write64((1ULL << 33) - 1, idreg);
253         vfid = (val >> 16) & 0xffff;
254         if (vfid >= SSO_MAX_VHGRP) {
255                 ssovf_log_err("Invalid vfid (%d/%d)", vfid, SSO_MAX_VHGRP);
256                 return -EINVAL;
257         }
258
259         res = &sdev.grp[vfid];
260         res->vfid = vfid;
261         res->bar0 = pci_dev->mem_resource[0].addr;
262         res->bar2 = pci_dev->mem_resource[2].addr;
263         res->domain = val & 0xffff;
264
265         sdev.total_ssovfs++;
266         rte_wmb();
267         ssovf_log_dbg("Domain=%d group=%d total_ssovfs=%d", res->domain,
268                         res->vfid, sdev.total_ssovfs);
269         return 0;
270 }
271
272 static const struct rte_pci_id pci_ssovf_map[] = {
273         {
274                 RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM,
275                                 PCI_DEVICE_ID_OCTEONTX_SSOGRP_VF)
276         },
277         {
278                 .vendor_id = 0,
279         },
280 };
281
282 static struct rte_pci_driver pci_ssovf = {
283         .id_table = pci_ssovf_map,
284         .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
285         .probe = ssovf_probe,
286 };
287
288 RTE_PMD_REGISTER_PCI(octeontx_ssovf, pci_ssovf);