xref: /dpdk/drivers/event/octeontx/timvf_probe.c (revision 68a03efeed657e6e05f281479b33b51102797e15)
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 	uint8_t in_use;
24 	uint16_t domain;
25 	uint16_t vfid;
26 	void *bar0;
27 	void *bar2;
28 	void *bar4;
29 };
30 
31 struct timdev {
32 	uint8_t total_timvfs;
33 	struct timvf_res rings[TIM_MAX_RINGS];
34 };
35 
36 static struct timdev tdev;
37 
38 uint8_t
39 timvf_get_ring(void)
40 {
41 	uint16_t global_domain = octeontx_get_global_domain();
42 	int i;
43 
44 	for (i = 0; i < tdev.total_timvfs; i++) {
45 		if (tdev.rings[i].domain != global_domain)
46 			continue;
47 		if (tdev.rings[i].in_use)
48 			continue;
49 
50 		tdev.rings[i].in_use = true;
51 		return tdev.rings[i].vfid;
52 	}
53 
54 	return UINT8_MAX;
55 }
56 
57 void
58 timvf_release_ring(uint8_t tim_ring_id)
59 {
60 	uint16_t global_domain = octeontx_get_global_domain();
61 	int i;
62 
63 	for (i = 0; i < tdev.total_timvfs; i++) {
64 		if (tdev.rings[i].domain != global_domain)
65 			continue;
66 		if (tdev.rings[i].vfid == tim_ring_id)
67 			tdev.rings[i].in_use = false;
68 	}
69 }
70 
71 void*
72 timvf_bar(uint8_t vfid, uint8_t bar)
73 {
74 	uint16_t global_domain = octeontx_get_global_domain();
75 	struct timvf_res *res = NULL;
76 	int i;
77 
78 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
79 		return NULL;
80 
81 	for (i = 0; i < tdev.total_timvfs; i++) {
82 		if (tdev.rings[i].domain != global_domain)
83 			continue;
84 		if (tdev.rings[i].vfid == vfid)
85 			res = &tdev.rings[i];
86 
87 	}
88 
89 	if (res == NULL)
90 		return NULL;
91 
92 	switch (bar) {
93 	case 0:
94 		return res->bar0;
95 	case 4:
96 		return res->bar4;
97 	default:
98 		return NULL;
99 	}
100 }
101 
102 static int
103 timvf_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
104 {
105 	uint64_t val;
106 	uint16_t vfid;
107 	struct timvf_res *res;
108 
109 	RTE_SET_USED(pci_drv);
110 
111 	/* For secondary processes, the primary has done all the work */
112 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
113 		return 0;
114 
115 	if (pci_dev->mem_resource[0].addr == NULL ||
116 			pci_dev->mem_resource[4].addr == NULL) {
117 		timvf_log_err("Empty bars %p %p",
118 				pci_dev->mem_resource[0].addr,
119 				pci_dev->mem_resource[4].addr);
120 		return -ENODEV;
121 	}
122 
123 	val = rte_read64((uint8_t *)pci_dev->mem_resource[0].addr +
124 			0x100 /* TIM_VRINGX_BASE */);
125 	vfid = (val >> 23) & 0xff;
126 	if (vfid >= TIM_MAX_RINGS) {
127 		timvf_log_err("Invalid vfid(%d/%d)", vfid, TIM_MAX_RINGS);
128 		return -EINVAL;
129 	}
130 
131 	res = &tdev.rings[tdev.total_timvfs];
132 	res->vfid = vfid;
133 	res->bar0 = pci_dev->mem_resource[0].addr;
134 	res->bar2 = pci_dev->mem_resource[2].addr;
135 	res->bar4 = pci_dev->mem_resource[4].addr;
136 	res->domain = (val >> 7) & 0xffff;
137 	res->in_use = false;
138 	tdev.total_timvfs++;
139 	rte_wmb();
140 
141 	timvf_log_dbg("Domain=%d VFid=%d bar0 %p total_timvfs=%d", res->domain,
142 			res->vfid, pci_dev->mem_resource[0].addr,
143 			tdev.total_timvfs);
144 	return 0;
145 }
146 
147 
148 static const struct rte_pci_id pci_timvf_map[] = {
149 	{
150 		RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM,
151 				PCI_DEVICE_ID_OCTEONTX_TIM_VF)
152 	},
153 	{
154 		.vendor_id = 0,
155 	},
156 };
157 
158 static struct rte_pci_driver pci_timvf = {
159 	.id_table = pci_timvf_map,
160 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_NEED_IOVA_AS_VA,
161 	.probe = timvf_probe,
162 	.remove = NULL,
163 };
164 
165 RTE_PMD_REGISTER_PCI(octeontx_timvf, pci_timvf);
166