]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2010-2018 Intel Corporation | |
3 | */ | |
4 | ||
5 | #include "ifpga_api.h" | |
6 | #include "ifpga_enumerate.h" | |
7 | #include "ifpga_feature_dev.h" | |
8 | ||
9 | #include "opae_hw_api.h" | |
10 | ||
11 | /* Accelerator APIs */ | |
12 | static int ifpga_acc_get_uuid(struct opae_accelerator *acc, | |
13 | struct uuid *uuid) | |
14 | { | |
15 | struct opae_bridge *br = acc->br; | |
16 | struct ifpga_port_hw *port; | |
17 | ||
18 | if (!br || !br->data) | |
19 | return -EINVAL; | |
20 | ||
21 | port = br->data; | |
22 | ||
23 | return fpga_get_afu_uuid(port, uuid); | |
24 | } | |
25 | ||
26 | static int ifpga_acc_set_irq(struct opae_accelerator *acc, | |
27 | u32 start, u32 count, s32 evtfds[]) | |
28 | { | |
29 | struct ifpga_afu_info *afu_info = acc->data; | |
30 | struct opae_bridge *br = acc->br; | |
31 | struct ifpga_port_hw *port; | |
32 | struct fpga_uafu_irq_set irq_set; | |
33 | ||
34 | if (!br || !br->data) | |
35 | return -EINVAL; | |
36 | ||
37 | if (start >= afu_info->num_irqs || start + count > afu_info->num_irqs) | |
38 | return -EINVAL; | |
39 | ||
40 | port = br->data; | |
41 | ||
42 | irq_set.start = start; | |
43 | irq_set.count = count; | |
44 | irq_set.evtfds = evtfds; | |
45 | ||
46 | return ifpga_set_irq(port->parent, FEATURE_FIU_ID_PORT, port->port_id, | |
47 | IFPGA_PORT_FEATURE_ID_UINT, &irq_set); | |
48 | } | |
49 | ||
50 | static int ifpga_acc_get_info(struct opae_accelerator *acc, | |
51 | struct opae_acc_info *info) | |
52 | { | |
53 | struct ifpga_afu_info *afu_info = acc->data; | |
54 | ||
55 | if (!afu_info) | |
56 | return -ENODEV; | |
57 | ||
58 | info->num_regions = afu_info->num_regions; | |
59 | info->num_irqs = afu_info->num_irqs; | |
60 | ||
61 | return 0; | |
62 | } | |
63 | ||
64 | static int ifpga_acc_get_region_info(struct opae_accelerator *acc, | |
65 | struct opae_acc_region_info *info) | |
66 | { | |
67 | struct ifpga_afu_info *afu_info = acc->data; | |
68 | ||
69 | if (!afu_info) | |
70 | return -EINVAL; | |
71 | ||
72 | if (info->index >= afu_info->num_regions) | |
73 | return -EINVAL; | |
74 | ||
75 | /* always one RW region only for AFU now */ | |
76 | info->flags = ACC_REGION_READ | ACC_REGION_WRITE | ACC_REGION_MMIO; | |
77 | info->len = afu_info->region[info->index].len; | |
78 | info->addr = afu_info->region[info->index].addr; | |
f67539c2 | 79 | info->phys_addr = afu_info->region[info->index].phys_addr; |
11fdf7f2 TL |
80 | |
81 | return 0; | |
82 | } | |
83 | ||
84 | static int ifpga_acc_read(struct opae_accelerator *acc, unsigned int region_idx, | |
85 | u64 offset, unsigned int byte, void *data) | |
86 | { | |
87 | struct ifpga_afu_info *afu_info = acc->data; | |
88 | struct opae_reg_region *region; | |
89 | ||
90 | if (!afu_info) | |
91 | return -EINVAL; | |
92 | ||
93 | if (offset + byte <= offset) | |
94 | return -EINVAL; | |
95 | ||
96 | if (region_idx >= afu_info->num_regions) | |
97 | return -EINVAL; | |
98 | ||
99 | region = &afu_info->region[region_idx]; | |
100 | if (offset + byte > region->len) | |
101 | return -EINVAL; | |
102 | ||
103 | switch (byte) { | |
104 | case 8: | |
105 | *(u64 *)data = opae_readq(region->addr + offset); | |
106 | break; | |
107 | case 4: | |
108 | *(u32 *)data = opae_readl(region->addr + offset); | |
109 | break; | |
110 | case 2: | |
111 | *(u16 *)data = opae_readw(region->addr + offset); | |
112 | break; | |
113 | case 1: | |
114 | *(u8 *)data = opae_readb(region->addr + offset); | |
115 | break; | |
116 | default: | |
117 | return -EINVAL; | |
118 | } | |
119 | ||
120 | return 0; | |
121 | } | |
122 | ||
123 | static int ifpga_acc_write(struct opae_accelerator *acc, | |
124 | unsigned int region_idx, u64 offset, | |
125 | unsigned int byte, void *data) | |
126 | { | |
127 | struct ifpga_afu_info *afu_info = acc->data; | |
128 | struct opae_reg_region *region; | |
129 | ||
130 | if (!afu_info) | |
131 | return -EINVAL; | |
132 | ||
133 | if (offset + byte <= offset) | |
134 | return -EINVAL; | |
135 | ||
136 | if (region_idx >= afu_info->num_regions) | |
137 | return -EINVAL; | |
138 | ||
139 | region = &afu_info->region[region_idx]; | |
140 | if (offset + byte > region->len) | |
141 | return -EINVAL; | |
142 | ||
143 | /* normal mmio case */ | |
144 | switch (byte) { | |
145 | case 8: | |
146 | opae_writeq(*(u64 *)data, region->addr + offset); | |
147 | break; | |
148 | case 4: | |
149 | opae_writel(*(u32 *)data, region->addr + offset); | |
150 | break; | |
151 | case 2: | |
152 | opae_writew(*(u16 *)data, region->addr + offset); | |
153 | break; | |
154 | case 1: | |
155 | opae_writeb(*(u8 *)data, region->addr + offset); | |
156 | break; | |
157 | default: | |
158 | return -EINVAL; | |
159 | } | |
160 | ||
161 | return 0; | |
162 | } | |
163 | ||
164 | struct opae_accelerator_ops ifpga_acc_ops = { | |
165 | .read = ifpga_acc_read, | |
166 | .write = ifpga_acc_write, | |
167 | .set_irq = ifpga_acc_set_irq, | |
168 | .get_info = ifpga_acc_get_info, | |
169 | .get_region_info = ifpga_acc_get_region_info, | |
170 | .get_uuid = ifpga_acc_get_uuid, | |
171 | }; | |
172 | ||
173 | /* Bridge APIs */ | |
11fdf7f2 TL |
174 | static int ifpga_br_reset(struct opae_bridge *br) |
175 | { | |
176 | struct ifpga_port_hw *port = br->data; | |
177 | ||
178 | return fpga_port_reset(port); | |
179 | } | |
180 | ||
181 | struct opae_bridge_ops ifpga_br_ops = { | |
182 | .reset = ifpga_br_reset, | |
183 | }; | |
184 | ||
185 | /* Manager APIs */ | |
f67539c2 | 186 | static int ifpga_mgr_flash(struct opae_manager *mgr, int id, const char *buf, |
11fdf7f2 TL |
187 | u32 size, u64 *status) |
188 | { | |
189 | struct ifpga_fme_hw *fme = mgr->data; | |
190 | struct ifpga_hw *hw = fme->parent; | |
191 | ||
192 | return ifpga_pr(hw, id, buf, size, status); | |
193 | } | |
194 | ||
9f95a23c TL |
195 | static int ifpga_mgr_get_eth_group_region_info(struct opae_manager *mgr, |
196 | struct opae_eth_group_region_info *info) | |
197 | { | |
198 | struct ifpga_fme_hw *fme = mgr->data; | |
199 | ||
200 | if (info->group_id >= MAX_ETH_GROUP_DEVICES) | |
201 | return -EINVAL; | |
202 | ||
203 | info->phys_addr = fme->eth_group_region[info->group_id].phys_addr; | |
204 | info->addr = fme->eth_group_region[info->group_id].addr; | |
205 | info->len = fme->eth_group_region[info->group_id].len; | |
206 | ||
207 | info->mem_idx = fme->nums_acc_region + info->group_id; | |
208 | ||
209 | return 0; | |
210 | } | |
211 | ||
f67539c2 TL |
212 | static int ifpga_mgr_get_sensor_value(struct opae_manager *mgr, |
213 | struct opae_sensor_info *sensor, | |
214 | unsigned int *value) | |
215 | { | |
216 | struct ifpga_fme_hw *fme = mgr->data; | |
217 | ||
218 | return fme_mgr_get_sensor_value(fme, sensor, value); | |
219 | } | |
220 | ||
221 | static int ifpga_mgr_get_board_info(struct opae_manager *mgr, | |
222 | struct opae_board_info **info) | |
223 | { | |
224 | struct ifpga_fme_hw *fme = mgr->data; | |
225 | ||
226 | *info = &fme->board_info; | |
227 | ||
228 | return 0; | |
229 | } | |
230 | ||
11fdf7f2 TL |
231 | struct opae_manager_ops ifpga_mgr_ops = { |
232 | .flash = ifpga_mgr_flash, | |
9f95a23c | 233 | .get_eth_group_region_info = ifpga_mgr_get_eth_group_region_info, |
f67539c2 TL |
234 | .get_sensor_value = ifpga_mgr_get_sensor_value, |
235 | .get_board_info = ifpga_mgr_get_board_info, | |
9f95a23c TL |
236 | }; |
237 | ||
238 | static int ifpga_mgr_read_mac_rom(struct opae_manager *mgr, int offset, | |
239 | void *buf, int size) | |
240 | { | |
241 | struct ifpga_fme_hw *fme = mgr->data; | |
242 | ||
243 | return fme_mgr_read_mac_rom(fme, offset, buf, size); | |
244 | } | |
245 | ||
246 | static int ifpga_mgr_write_mac_rom(struct opae_manager *mgr, int offset, | |
247 | void *buf, int size) | |
248 | { | |
249 | struct ifpga_fme_hw *fme = mgr->data; | |
250 | ||
251 | return fme_mgr_write_mac_rom(fme, offset, buf, size); | |
252 | } | |
253 | ||
254 | static int ifpga_mgr_get_eth_group_nums(struct opae_manager *mgr) | |
255 | { | |
256 | struct ifpga_fme_hw *fme = mgr->data; | |
257 | ||
258 | return fme_mgr_get_eth_group_nums(fme); | |
259 | } | |
260 | ||
261 | static int ifpga_mgr_get_eth_group_info(struct opae_manager *mgr, | |
262 | u8 group_id, struct opae_eth_group_info *info) | |
263 | { | |
264 | struct ifpga_fme_hw *fme = mgr->data; | |
265 | ||
266 | return fme_mgr_get_eth_group_info(fme, group_id, info); | |
267 | } | |
268 | ||
269 | static int ifpga_mgr_eth_group_reg_read(struct opae_manager *mgr, u8 group_id, | |
270 | u8 type, u8 index, u16 addr, u32 *data) | |
271 | { | |
272 | struct ifpga_fme_hw *fme = mgr->data; | |
273 | ||
274 | return fme_mgr_eth_group_read_reg(fme, group_id, | |
275 | type, index, addr, data); | |
276 | } | |
277 | ||
278 | static int ifpga_mgr_eth_group_reg_write(struct opae_manager *mgr, u8 group_id, | |
279 | u8 type, u8 index, u16 addr, u32 data) | |
280 | { | |
281 | struct ifpga_fme_hw *fme = mgr->data; | |
282 | ||
283 | return fme_mgr_eth_group_write_reg(fme, group_id, | |
284 | type, index, addr, data); | |
285 | } | |
286 | ||
287 | static int ifpga_mgr_get_retimer_info(struct opae_manager *mgr, | |
288 | struct opae_retimer_info *info) | |
289 | { | |
290 | struct ifpga_fme_hw *fme = mgr->data; | |
291 | ||
292 | return fme_mgr_get_retimer_info(fme, info); | |
293 | } | |
294 | ||
295 | static int ifpga_mgr_get_retimer_status(struct opae_manager *mgr, | |
296 | struct opae_retimer_status *status) | |
297 | { | |
298 | struct ifpga_fme_hw *fme = mgr->data; | |
299 | ||
300 | return fme_mgr_get_retimer_status(fme, status); | |
301 | } | |
302 | ||
303 | /* Network APIs in FME */ | |
304 | struct opae_manager_networking_ops ifpga_mgr_network_ops = { | |
305 | .read_mac_rom = ifpga_mgr_read_mac_rom, | |
306 | .write_mac_rom = ifpga_mgr_write_mac_rom, | |
307 | .get_eth_group_nums = ifpga_mgr_get_eth_group_nums, | |
308 | .get_eth_group_info = ifpga_mgr_get_eth_group_info, | |
309 | .eth_group_reg_read = ifpga_mgr_eth_group_reg_read, | |
310 | .eth_group_reg_write = ifpga_mgr_eth_group_reg_write, | |
311 | .get_retimer_info = ifpga_mgr_get_retimer_info, | |
312 | .get_retimer_status = ifpga_mgr_get_retimer_status, | |
11fdf7f2 TL |
313 | }; |
314 | ||
315 | /* Adapter APIs */ | |
316 | static int ifpga_adapter_enumerate(struct opae_adapter *adapter) | |
317 | { | |
318 | struct ifpga_hw *hw = malloc(sizeof(*hw)); | |
319 | ||
320 | if (hw) { | |
9f95a23c | 321 | opae_memset(hw, 0, sizeof(*hw)); |
11fdf7f2 TL |
322 | hw->pci_data = adapter->data; |
323 | hw->adapter = adapter; | |
324 | if (ifpga_bus_enumerate(hw)) | |
325 | goto error; | |
326 | return ifpga_bus_init(hw); | |
327 | } | |
328 | ||
329 | error: | |
330 | return -ENOMEM; | |
331 | } | |
332 | ||
333 | struct opae_adapter_ops ifpga_adapter_ops = { | |
334 | .enumerate = ifpga_adapter_enumerate, | |
335 | }; | |
336 | ||
337 | /** | |
338 | * ifpga_pr - do the partial reconfiguration for a given port device | |
339 | * @hw: pointer to the HW structure | |
340 | * @port_id: the port device id | |
341 | * @buffer: the buffer of the bitstream | |
342 | * @size: the size of the bitstream | |
343 | * @status: hardware status including PR error code if return -EIO. | |
344 | * | |
345 | * @return | |
346 | * - 0: Success, partial reconfiguration finished. | |
347 | * - <0: Error code returned in partial reconfiguration. | |
348 | **/ | |
f67539c2 | 349 | int ifpga_pr(struct ifpga_hw *hw, u32 port_id, const char *buffer, u32 size, |
11fdf7f2 TL |
350 | u64 *status) |
351 | { | |
352 | if (!is_valid_port_id(hw, port_id)) | |
353 | return -ENODEV; | |
354 | ||
355 | return do_pr(hw, port_id, buffer, size, status); | |
356 | } | |
357 | ||
358 | int ifpga_get_prop(struct ifpga_hw *hw, u32 fiu_id, u32 port_id, | |
359 | struct feature_prop *prop) | |
360 | { | |
361 | if (!hw || !prop) | |
362 | return -EINVAL; | |
363 | ||
364 | switch (fiu_id) { | |
365 | case FEATURE_FIU_ID_FME: | |
366 | return fme_get_prop(&hw->fme, prop); | |
367 | case FEATURE_FIU_ID_PORT: | |
368 | if (!is_valid_port_id(hw, port_id)) | |
369 | return -ENODEV; | |
370 | return port_get_prop(&hw->port[port_id], prop); | |
371 | } | |
372 | ||
373 | return -ENOENT; | |
374 | } | |
375 | ||
376 | int ifpga_set_prop(struct ifpga_hw *hw, u32 fiu_id, u32 port_id, | |
377 | struct feature_prop *prop) | |
378 | { | |
379 | if (!hw || !prop) | |
380 | return -EINVAL; | |
381 | ||
382 | switch (fiu_id) { | |
383 | case FEATURE_FIU_ID_FME: | |
384 | return fme_set_prop(&hw->fme, prop); | |
385 | case FEATURE_FIU_ID_PORT: | |
386 | if (!is_valid_port_id(hw, port_id)) | |
387 | return -ENODEV; | |
388 | return port_set_prop(&hw->port[port_id], prop); | |
389 | } | |
390 | ||
391 | return -ENOENT; | |
392 | } | |
393 | ||
394 | int ifpga_set_irq(struct ifpga_hw *hw, u32 fiu_id, u32 port_id, | |
395 | u32 feature_id, void *irq_set) | |
396 | { | |
397 | if (!hw || !irq_set) | |
398 | return -EINVAL; | |
399 | ||
400 | switch (fiu_id) { | |
401 | case FEATURE_FIU_ID_FME: | |
402 | return fme_set_irq(&hw->fme, feature_id, irq_set); | |
403 | case FEATURE_FIU_ID_PORT: | |
404 | if (!is_valid_port_id(hw, port_id)) | |
405 | return -ENODEV; | |
406 | return port_set_irq(&hw->port[port_id], feature_id, irq_set); | |
407 | } | |
408 | ||
409 | return -ENOENT; | |
410 | } |