New upstream version 18.08
[deb_dpdk.git] / drivers / raw / ifpga_rawdev / base / ifpga_api.c
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;
79
80         return 0;
81 }
82
83 static int ifpga_acc_read(struct opae_accelerator *acc, unsigned int region_idx,
84                           u64 offset, unsigned int byte, void *data)
85 {
86         struct ifpga_afu_info *afu_info = acc->data;
87         struct opae_reg_region *region;
88
89         if (!afu_info)
90                 return -EINVAL;
91
92         if (offset + byte <= offset)
93                 return -EINVAL;
94
95         if (region_idx >= afu_info->num_regions)
96                 return -EINVAL;
97
98         region = &afu_info->region[region_idx];
99         if (offset + byte > region->len)
100                 return -EINVAL;
101
102         switch (byte) {
103         case 8:
104                 *(u64  *)data = opae_readq(region->addr + offset);
105                 break;
106         case 4:
107                 *(u32 *)data = opae_readl(region->addr + offset);
108                 break;
109         case 2:
110                 *(u16 *)data = opae_readw(region->addr + offset);
111                 break;
112         case 1:
113                 *(u8 *)data = opae_readb(region->addr + offset);
114                 break;
115         default:
116                 return -EINVAL;
117         }
118
119         return 0;
120 }
121
122 static int ifpga_acc_write(struct opae_accelerator *acc,
123                            unsigned int region_idx, u64 offset,
124                            unsigned int byte, void *data)
125 {
126         struct ifpga_afu_info *afu_info = acc->data;
127         struct opae_reg_region *region;
128
129         if (!afu_info)
130                 return -EINVAL;
131
132         if (offset + byte <= offset)
133                 return -EINVAL;
134
135         if (region_idx >= afu_info->num_regions)
136                 return -EINVAL;
137
138         region = &afu_info->region[region_idx];
139         if (offset + byte > region->len)
140                 return -EINVAL;
141
142         /* normal mmio case */
143         switch (byte) {
144         case 8:
145                 opae_writeq(*(u64 *)data, region->addr + offset);
146                 break;
147         case 4:
148                 opae_writel(*(u32 *)data, region->addr + offset);
149                 break;
150         case 2:
151                 opae_writew(*(u16 *)data, region->addr + offset);
152                 break;
153         case 1:
154                 opae_writeb(*(u8 *)data, region->addr + offset);
155                 break;
156         default:
157                 return -EINVAL;
158         }
159
160         return 0;
161 }
162
163 struct opae_accelerator_ops ifpga_acc_ops = {
164         .read = ifpga_acc_read,
165         .write = ifpga_acc_write,
166         .set_irq = ifpga_acc_set_irq,
167         .get_info = ifpga_acc_get_info,
168         .get_region_info = ifpga_acc_get_region_info,
169         .get_uuid = ifpga_acc_get_uuid,
170 };
171
172 /* Bridge APIs */
173
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 */
186 static int ifpga_mgr_flash(struct opae_manager *mgr, int id, void *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
195 struct opae_manager_ops ifpga_mgr_ops = {
196         .flash = ifpga_mgr_flash,
197 };
198
199 /* Adapter APIs */
200 static int ifpga_adapter_enumerate(struct opae_adapter *adapter)
201 {
202         struct ifpga_hw *hw = malloc(sizeof(*hw));
203
204         if (hw) {
205                 memset(hw, 0, sizeof(*hw));
206                 hw->pci_data = adapter->data;
207                 hw->adapter = adapter;
208                 if (ifpga_bus_enumerate(hw))
209                         goto error;
210                 return ifpga_bus_init(hw);
211         }
212
213 error:
214         return -ENOMEM;
215 }
216
217 struct opae_adapter_ops ifpga_adapter_ops = {
218         .enumerate = ifpga_adapter_enumerate,
219 };
220
221 /**
222  *  ifpga_pr - do the partial reconfiguration for a given port device
223  *  @hw: pointer to the HW structure
224  *  @port_id: the port device id
225  *  @buffer: the buffer of the bitstream
226  *  @size: the size of the bitstream
227  *  @status: hardware status including PR error code if return -EIO.
228  *
229  *  @return
230  *   - 0: Success, partial reconfiguration finished.
231  *   - <0: Error code returned in partial reconfiguration.
232  **/
233 int ifpga_pr(struct ifpga_hw *hw, u32 port_id, void *buffer, u32 size,
234              u64 *status)
235 {
236         if (!is_valid_port_id(hw, port_id))
237                 return -ENODEV;
238
239         return do_pr(hw, port_id, buffer, size, status);
240 }
241
242 int ifpga_get_prop(struct ifpga_hw *hw, u32 fiu_id, u32 port_id,
243                    struct feature_prop *prop)
244 {
245         if (!hw || !prop)
246                 return -EINVAL;
247
248         switch (fiu_id) {
249         case FEATURE_FIU_ID_FME:
250                 return fme_get_prop(&hw->fme, prop);
251         case FEATURE_FIU_ID_PORT:
252                 if (!is_valid_port_id(hw, port_id))
253                         return -ENODEV;
254                 return port_get_prop(&hw->port[port_id], prop);
255         }
256
257         return -ENOENT;
258 }
259
260 int ifpga_set_prop(struct ifpga_hw *hw, u32 fiu_id, u32 port_id,
261                    struct feature_prop *prop)
262 {
263         if (!hw || !prop)
264                 return -EINVAL;
265
266         switch (fiu_id) {
267         case FEATURE_FIU_ID_FME:
268                 return fme_set_prop(&hw->fme, prop);
269         case FEATURE_FIU_ID_PORT:
270                 if (!is_valid_port_id(hw, port_id))
271                         return -ENODEV;
272                 return port_set_prop(&hw->port[port_id], prop);
273         }
274
275         return -ENOENT;
276 }
277
278 int ifpga_set_irq(struct ifpga_hw *hw, u32 fiu_id, u32 port_id,
279                   u32 feature_id, void *irq_set)
280 {
281         if (!hw || !irq_set)
282                 return -EINVAL;
283
284         switch (fiu_id) {
285         case FEATURE_FIU_ID_FME:
286                 return fme_set_irq(&hw->fme, feature_id, irq_set);
287         case FEATURE_FIU_ID_PORT:
288                 if (!is_valid_port_id(hw, port_id))
289                         return -ENODEV;
290                 return port_set_irq(&hw->port[port_id], feature_id, irq_set);
291         }
292
293         return -ENOENT;
294 }