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