xref: /dpdk/drivers/event/octeontx/timvf_probe.c (revision 089e5ed727a15da2729cfee9b63533dd120bd04c)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Cavium, Inc
3  */
4 
5 #include <rte_eal.h>
6 #include <rte_io.h>
7 #include <rte_pci.h>
8 #include <rte_bus_pci.h>
9 
10 #include <octeontx_mbox.h>
11 
12 #include "ssovf_evdev.h"
13 #include "timvf_evdev.h"
14 
15 #ifndef PCI_VENDOR_ID_CAVIUM
16 #define PCI_VENDOR_ID_CAVIUM			(0x177D)
17 #endif
18 
19 #define PCI_DEVICE_ID_OCTEONTX_TIM_VF		(0xA051)
20 #define TIM_MAX_RINGS				(64)
21 
22 struct timvf_res {
23 	uint16_t domain;
24 	uint16_t vfid;
25 	void *bar0;
26 	void *bar2;
27 	void *bar4;
28 };
29 
30 struct timdev {
31 	uint8_t total_timvfs;
32 	struct timvf_res rings[TIM_MAX_RINGS];
33 };
34 
35 static struct timdev tdev;
36 
37 int
38 timvf_info(struct timvf_info *tinfo)
39 {
40 	int i;
41 	struct ssovf_info info;
42 
43 	if (tinfo == NULL)
44 		return -EINVAL;
45 
46 	if (!tdev.total_timvfs)
47 		return -ENODEV;
48 
49 	if (ssovf_info(&info) < 0)
50 		return -EINVAL;
51 
52 	for (i = 0; i < tdev.total_timvfs; i++) {
53 		if (info.domain != tdev.rings[i].domain) {
54 			timvf_log_err("GRP error, vfid=%d/%d domain=%d/%d %p",
55 				i, tdev.rings[i].vfid,
56 				info.domain, tdev.rings[i].domain,
57 				tdev.rings[i].bar0);
58 			return -EINVAL;
59 		}
60 	}
61 
62 	tinfo->total_timvfs = tdev.total_timvfs;
63 	tinfo->domain = info.domain;
64 	return 0;
65 }
66 
67 void*
68 timvf_bar(uint8_t id, uint8_t bar)
69 {
70 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
71 		return NULL;
72 
73 	if (id > tdev.total_timvfs)
74 		return NULL;
75 
76 	switch (bar) {
77 	case 0:
78 		return tdev.rings[id].bar0;
79 	case 4:
80 		return tdev.rings[id].bar4;
81 	default:
82 		return NULL;
83 	}
84 }
85 
86 static int
87 timvf_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
88 {
89 	uint64_t val;
90 	uint16_t vfid;
91 	struct timvf_res *res;
92 
93 	RTE_SET_USED(pci_drv);
94 
95 	/* For secondary processes, the primary has done all the work */
96 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
97 		return 0;
98 
99 	if (pci_dev->mem_resource[0].addr == NULL ||
100 			pci_dev->mem_resource[4].addr == NULL) {
101 		timvf_log_err("Empty bars %p %p",
102 				pci_dev->mem_resource[0].addr,
103 				pci_dev->mem_resource[4].addr);
104 		return -ENODEV;
105 	}
106 
107 	val = rte_read64((uint8_t *)pci_dev->mem_resource[0].addr +
108 			0x100 /* TIM_VRINGX_BASE */);
109 	vfid = (val >> 23) & 0xff;
110 	if (vfid >= TIM_MAX_RINGS) {
111 		timvf_log_err("Invalid vfid(%d/%d)", vfid, TIM_MAX_RINGS);
112 		return -EINVAL;
113 	}
114 
115 	res = &tdev.rings[tdev.total_timvfs];
116 	res->vfid = vfid;
117 	res->bar0 = pci_dev->mem_resource[0].addr;
118 	res->bar2 = pci_dev->mem_resource[2].addr;
119 	res->bar4 = pci_dev->mem_resource[4].addr;
120 	res->domain = (val >> 7) & 0xffff;
121 	tdev.total_timvfs++;
122 	rte_wmb();
123 
124 	timvf_log_dbg("Domain=%d VFid=%d bar0 %p total_timvfs=%d", res->domain,
125 			res->vfid, pci_dev->mem_resource[0].addr,
126 			tdev.total_timvfs);
127 	return 0;
128 }
129 
130 
131 static const struct rte_pci_id pci_timvf_map[] = {
132 	{
133 		RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM,
134 				PCI_DEVICE_ID_OCTEONTX_TIM_VF)
135 	},
136 	{
137 		.vendor_id = 0,
138 	},
139 };
140 
141 static struct rte_pci_driver pci_timvf = {
142 	.id_table = pci_timvf_map,
143 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_NEED_IOVA_AS_VA,
144 	.probe = timvf_probe,
145 	.remove = NULL,
146 };
147 
148 RTE_PMD_REGISTER_PCI(octeontx_timvf, pci_timvf);
149