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