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