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