xref: /dpdk/drivers/raw/ifpga/base/ifpga_api.c (revision b74ee6c808b3051075edfe974b92717a47580e6e)
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