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 */
ifpga_acc_get_uuid(struct opae_accelerator * acc,struct uuid * uuid)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
ifpga_acc_set_irq(struct opae_accelerator * acc,u32 start,u32 count,s32 evtfds[])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
ifpga_acc_get_info(struct opae_accelerator * acc,struct opae_acc_info * info)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
ifpga_acc_get_region_info(struct opae_accelerator * acc,struct opae_acc_region_info * info)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;
79 info->phys_addr = afu_info->region[info->index].phys_addr;
80
81 return 0;
82 }
83
ifpga_acc_read(struct opae_accelerator * acc,unsigned int region_idx,u64 offset,unsigned int byte,void * data)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
ifpga_acc_write(struct opae_accelerator * acc,unsigned int region_idx,u64 offset,unsigned int byte,void * data)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 */
ifpga_br_reset(struct opae_bridge * br)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 */
ifpga_mgr_flash(struct opae_manager * mgr,int id,const char * buf,u32 size,u64 * status)186 static int ifpga_mgr_flash(struct opae_manager *mgr, int id, const char *buf,
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
ifpga_mgr_get_eth_group_region_info(struct opae_manager * mgr,struct opae_eth_group_region_info * info)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
ifpga_mgr_get_sensor_value(struct opae_manager * mgr,struct opae_sensor_info * sensor,unsigned int * value)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
ifpga_mgr_get_board_info(struct opae_manager * mgr,struct opae_board_info ** info)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
231 struct opae_manager_ops ifpga_mgr_ops = {
232 .flash = ifpga_mgr_flash,
233 .get_eth_group_region_info = ifpga_mgr_get_eth_group_region_info,
234 .get_sensor_value = ifpga_mgr_get_sensor_value,
235 .get_board_info = ifpga_mgr_get_board_info,
236 };
237
ifpga_mgr_read_mac_rom(struct opae_manager * mgr,int offset,void * buf,int size)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
ifpga_mgr_write_mac_rom(struct opae_manager * mgr,int offset,void * buf,int size)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
ifpga_mgr_get_eth_group_nums(struct opae_manager * mgr)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
ifpga_mgr_get_eth_group_info(struct opae_manager * mgr,u8 group_id,struct opae_eth_group_info * info)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
ifpga_mgr_eth_group_reg_read(struct opae_manager * mgr,u8 group_id,u8 type,u8 index,u16 addr,u32 * data)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
ifpga_mgr_eth_group_reg_write(struct opae_manager * mgr,u8 group_id,u8 type,u8 index,u16 addr,u32 data)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
ifpga_mgr_get_retimer_info(struct opae_manager * mgr,struct opae_retimer_info * info)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
ifpga_mgr_get_retimer_status(struct opae_manager * mgr,struct opae_retimer_status * status)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,
313 };
314
315 /* Adapter APIs */
ifpga_adapter_enumerate(struct opae_adapter * adapter)316 static int ifpga_adapter_enumerate(struct opae_adapter *adapter)
317 {
318 struct ifpga_hw *hw = malloc(sizeof(*hw));
319
320 if (hw) {
321 opae_memset(hw, 0, sizeof(*hw));
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
ifpga_adapter_destroy(struct opae_adapter * adapter)333 static void ifpga_adapter_destroy(struct opae_adapter *adapter)
334 {
335 struct ifpga_fme_hw *fme;
336
337 if (adapter && adapter->mgr && adapter->mgr->data) {
338 fme = (struct ifpga_fme_hw *)adapter->mgr->data;
339 if (fme->parent)
340 ifpga_bus_uinit(fme->parent);
341 }
342 }
343
344 struct opae_adapter_ops ifpga_adapter_ops = {
345 .enumerate = ifpga_adapter_enumerate,
346 .destroy = ifpga_adapter_destroy,
347 };
348
349 /**
350 * ifpga_pr - do the partial reconfiguration for a given port device
351 * @hw: pointer to the HW structure
352 * @port_id: the port device id
353 * @buffer: the buffer of the bitstream
354 * @size: the size of the bitstream
355 * @status: hardware status including PR error code if return -EIO.
356 *
357 * @return
358 * - 0: Success, partial reconfiguration finished.
359 * - <0: Error code returned in partial reconfiguration.
360 **/
ifpga_pr(struct ifpga_hw * hw,u32 port_id,const char * buffer,u32 size,u64 * status)361 int ifpga_pr(struct ifpga_hw *hw, u32 port_id, const char *buffer, u32 size,
362 u64 *status)
363 {
364 if (!is_valid_port_id(hw, port_id))
365 return -ENODEV;
366
367 return do_pr(hw, port_id, buffer, size, status);
368 }
369
ifpga_get_prop(struct ifpga_hw * hw,u32 fiu_id,u32 port_id,struct feature_prop * prop)370 int ifpga_get_prop(struct ifpga_hw *hw, u32 fiu_id, u32 port_id,
371 struct feature_prop *prop)
372 {
373 if (!hw || !prop)
374 return -EINVAL;
375
376 switch (fiu_id) {
377 case FEATURE_FIU_ID_FME:
378 return fme_get_prop(&hw->fme, prop);
379 case FEATURE_FIU_ID_PORT:
380 if (!is_valid_port_id(hw, port_id))
381 return -ENODEV;
382 return port_get_prop(&hw->port[port_id], prop);
383 }
384
385 return -ENOENT;
386 }
387
ifpga_set_prop(struct ifpga_hw * hw,u32 fiu_id,u32 port_id,struct feature_prop * prop)388 int ifpga_set_prop(struct ifpga_hw *hw, u32 fiu_id, u32 port_id,
389 struct feature_prop *prop)
390 {
391 if (!hw || !prop)
392 return -EINVAL;
393
394 switch (fiu_id) {
395 case FEATURE_FIU_ID_FME:
396 return fme_set_prop(&hw->fme, prop);
397 case FEATURE_FIU_ID_PORT:
398 if (!is_valid_port_id(hw, port_id))
399 return -ENODEV;
400 return port_set_prop(&hw->port[port_id], prop);
401 }
402
403 return -ENOENT;
404 }
405
ifpga_set_irq(struct ifpga_hw * hw,u32 fiu_id,u32 port_id,u32 feature_id,void * irq_set)406 int ifpga_set_irq(struct ifpga_hw *hw, u32 fiu_id, u32 port_id,
407 u32 feature_id, void *irq_set)
408 {
409 if (!hw || !irq_set)
410 return -EINVAL;
411
412 switch (fiu_id) {
413 case FEATURE_FIU_ID_FME:
414 return fme_set_irq(&hw->fme, feature_id, irq_set);
415 case FEATURE_FIU_ID_PORT:
416 if (!is_valid_port_id(hw, port_id))
417 return -ENODEV;
418 return port_set_irq(&hw->port[port_id], feature_id, irq_set);
419 }
420
421 return -ENOENT;
422 }
423