]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
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 { | |
f67539c2 | 23 | uint8_t in_use; |
11fdf7f2 TL |
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 | ||
f67539c2 TL |
38 | uint8_t |
39 | timvf_get_ring(void) | |
11fdf7f2 | 40 | { |
f67539c2 | 41 | uint16_t global_domain = octeontx_get_global_domain(); |
11fdf7f2 | 42 | int i; |
11fdf7f2 | 43 | |
f67539c2 TL |
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; | |
11fdf7f2 | 49 | |
f67539c2 TL |
50 | tdev.rings[i].in_use = true; |
51 | return tdev.rings[i].vfid; | |
52 | } | |
11fdf7f2 | 53 | |
f67539c2 TL |
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; | |
11fdf7f2 TL |
62 | |
63 | for (i = 0; i < tdev.total_timvfs; i++) { | |
f67539c2 TL |
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; | |
11fdf7f2 | 68 | } |
11fdf7f2 TL |
69 | } |
70 | ||
71 | void* | |
f67539c2 | 72 | timvf_bar(uint8_t vfid, uint8_t bar) |
11fdf7f2 | 73 | { |
f67539c2 TL |
74 | uint16_t global_domain = octeontx_get_global_domain(); |
75 | struct timvf_res *res = NULL; | |
76 | int i; | |
77 | ||
11fdf7f2 TL |
78 | if (rte_eal_process_type() != RTE_PROC_PRIMARY) |
79 | return NULL; | |
80 | ||
f67539c2 TL |
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) | |
11fdf7f2 TL |
90 | return NULL; |
91 | ||
92 | switch (bar) { | |
93 | case 0: | |
f67539c2 | 94 | return res->bar0; |
11fdf7f2 | 95 | case 4: |
f67539c2 | 96 | return res->bar4; |
11fdf7f2 TL |
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; | |
f67539c2 | 137 | res->in_use = false; |
11fdf7f2 TL |
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, | |
f67539c2 | 160 | .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_NEED_IOVA_AS_VA, |
11fdf7f2 TL |
161 | .probe = timvf_probe, |
162 | .remove = NULL, | |
163 | }; | |
164 | ||
165 | RTE_PMD_REGISTER_PCI(octeontx_timvf, pci_timvf); |