New upstream version 17.11-rc3
[deb_dpdk.git] / drivers / bus / dpaa / base / qbman / process.c
1 /*-
2  * This file is provided under a dual BSD/GPLv2 license. When using or
3  * redistributing this file, you may do so under either license.
4  *
5  *   BSD LICENSE
6  *
7  * Copyright 2011-2016 Freescale Semiconductor Inc.
8  * Copyright 2017 NXP.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * * Neither the name of the above-listed copyright holders nor the
18  * names of any contributors may be used to endorse or promote products
19  * derived from this software without specific prior written permission.
20  *
21  *   GPL LICENSE SUMMARY
22  *
23  * ALTERNATIVELY, this software may be distributed under the terms of the
24  * GNU General Public License ("GPL") as published by the Free Software
25  * Foundation, either version 2 of that License or (at your option) any
26  * later version.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
32  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40 #include <assert.h>
41 #include <fcntl.h>
42 #include <unistd.h>
43 #include <sys/ioctl.h>
44
45 #include "process.h"
46
47 #include <fsl_usd.h>
48
49 /* As higher-level drivers will be built on top of this (dma_mem, qbman, ...),
50  * it's preferable that the process driver itself not provide any exported API.
51  * As such, combined with the fact that none of these operations are
52  * performance critical, it is justified to use lazy initialisation, so that's
53  * what the lock is for.
54  */
55 static int fd = -1;
56 static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER;
57
58 static int check_fd(void)
59 {
60         int ret;
61
62         if (fd >= 0)
63                 return 0;
64         ret = pthread_mutex_lock(&fd_init_lock);
65         assert(!ret);
66         /* check again with the lock held */
67         if (fd < 0)
68                 fd = open(PROCESS_PATH, O_RDWR);
69         ret = pthread_mutex_unlock(&fd_init_lock);
70         assert(!ret);
71         return (fd >= 0) ? 0 : -ENODEV;
72 }
73
74 #define DPAA_IOCTL_MAGIC 'u'
75 struct dpaa_ioctl_id_alloc {
76         uint32_t base; /* Return value, the start of the allocated range */
77         enum dpaa_id_type id_type; /* what kind of resource(s) to allocate */
78         uint32_t num; /* how many IDs to allocate (and return value) */
79         uint32_t align; /* must be a power of 2, 0 is treated like 1 */
80         int partial; /* whether to allow less than 'num' */
81 };
82
83 struct dpaa_ioctl_id_release {
84         /* Input; */
85         enum dpaa_id_type id_type;
86         uint32_t base;
87         uint32_t num;
88 };
89
90 struct dpaa_ioctl_id_reserve {
91         enum dpaa_id_type id_type;
92         uint32_t base;
93         uint32_t num;
94 };
95
96 #define DPAA_IOCTL_ID_ALLOC \
97         _IOWR(DPAA_IOCTL_MAGIC, 0x01, struct dpaa_ioctl_id_alloc)
98 #define DPAA_IOCTL_ID_RELEASE \
99         _IOW(DPAA_IOCTL_MAGIC, 0x02, struct dpaa_ioctl_id_release)
100 #define DPAA_IOCTL_ID_RESERVE \
101         _IOW(DPAA_IOCTL_MAGIC, 0x0A, struct dpaa_ioctl_id_reserve)
102
103 int process_alloc(enum dpaa_id_type id_type, uint32_t *base, uint32_t num,
104                   uint32_t align, int partial)
105 {
106         struct dpaa_ioctl_id_alloc id = {
107                 .id_type = id_type,
108                 .num = num,
109                 .align = align,
110                 .partial = partial
111         };
112         int ret = check_fd();
113
114         if (ret)
115                 return ret;
116         ret = ioctl(fd, DPAA_IOCTL_ID_ALLOC, &id);
117         if (ret)
118                 return ret;
119         for (ret = 0; ret < (int)id.num; ret++)
120                 base[ret] = id.base + ret;
121         return id.num;
122 }
123
124 void process_release(enum dpaa_id_type id_type, uint32_t base, uint32_t num)
125 {
126         struct dpaa_ioctl_id_release id = {
127                 .id_type = id_type,
128                 .base = base,
129                 .num = num
130         };
131         int ret = check_fd();
132
133         if (ret) {
134                 fprintf(stderr, "Process FD failure\n");
135                 return;
136         }
137         ret = ioctl(fd, DPAA_IOCTL_ID_RELEASE, &id);
138         if (ret)
139                 fprintf(stderr, "Process FD ioctl failure type %d base 0x%x num %d\n",
140                         id_type, base, num);
141 }
142
143 int process_reserve(enum dpaa_id_type id_type, uint32_t base, uint32_t num)
144 {
145         struct dpaa_ioctl_id_reserve id = {
146                 .id_type = id_type,
147                 .base = base,
148                 .num = num
149         };
150         int ret = check_fd();
151
152         if (ret)
153                 return ret;
154         return ioctl(fd, DPAA_IOCTL_ID_RESERVE, &id);
155 }
156
157 /***************************************/
158 /* Mapping and using QMan/BMan portals */
159 /***************************************/
160
161 #define DPAA_IOCTL_PORTAL_MAP \
162         _IOWR(DPAA_IOCTL_MAGIC, 0x07, struct dpaa_ioctl_portal_map)
163 #define DPAA_IOCTL_PORTAL_UNMAP \
164         _IOW(DPAA_IOCTL_MAGIC, 0x08, struct dpaa_portal_map)
165
166 int process_portal_map(struct dpaa_ioctl_portal_map *params)
167 {
168         int ret = check_fd();
169
170         if (ret)
171                 return ret;
172
173         ret = ioctl(fd, DPAA_IOCTL_PORTAL_MAP, params);
174         if (ret) {
175                 perror("ioctl(DPAA_IOCTL_PORTAL_MAP)");
176                 return ret;
177         }
178         return 0;
179 }
180
181 int process_portal_unmap(struct dpaa_portal_map *map)
182 {
183         int ret = check_fd();
184
185         if (ret)
186                 return ret;
187
188         ret = ioctl(fd, DPAA_IOCTL_PORTAL_UNMAP, map);
189         if (ret) {
190                 perror("ioctl(DPAA_IOCTL_PORTAL_UNMAP)");
191                 return ret;
192         }
193         return 0;
194 }
195
196 #define DPAA_IOCTL_PORTAL_IRQ_MAP \
197         _IOW(DPAA_IOCTL_MAGIC, 0x09, struct dpaa_ioctl_irq_map)
198
199 int process_portal_irq_map(int ifd, struct dpaa_ioctl_irq_map *map)
200 {
201         map->fd = fd;
202         return ioctl(ifd, DPAA_IOCTL_PORTAL_IRQ_MAP, map);
203 }
204
205 int process_portal_irq_unmap(int ifd)
206 {
207         return close(ifd);
208 }
209
210 struct dpaa_ioctl_raw_portal {
211         /* inputs */
212         enum dpaa_portal_type type; /* Type of portal to allocate */
213
214         uint8_t enable_stash; /* set to non zero to turn on stashing */
215         /* Stashing attributes for the portal */
216         uint32_t cpu;
217         uint32_t cache;
218         uint32_t window;
219         /* Specifies the stash request queue this portal should use */
220         uint8_t sdest;
221
222         /* Specifes a specific portal index to map or QBMAN_ANY_PORTAL_IDX
223          * for don't care.  The portal index will be populated by the
224          * driver when the ioctl() successfully completes.
225          */
226         uint32_t index;
227
228         /* outputs */
229         uint64_t cinh;
230         uint64_t cena;
231 };
232
233 #define DPAA_IOCTL_ALLOC_RAW_PORTAL \
234         _IOWR(DPAA_IOCTL_MAGIC, 0x0C, struct dpaa_ioctl_raw_portal)
235
236 #define DPAA_IOCTL_FREE_RAW_PORTAL \
237         _IOR(DPAA_IOCTL_MAGIC, 0x0D, struct dpaa_ioctl_raw_portal)
238
239 static int process_portal_allocate(struct dpaa_ioctl_raw_portal *portal)
240 {
241         int ret = check_fd();
242
243         if (ret)
244                 return ret;
245
246         ret = ioctl(fd, DPAA_IOCTL_ALLOC_RAW_PORTAL, portal);
247         if (ret) {
248                 perror("ioctl(DPAA_IOCTL_ALLOC_RAW_PORTAL)");
249                 return ret;
250         }
251         return 0;
252 }
253
254 static int process_portal_free(struct dpaa_ioctl_raw_portal *portal)
255 {
256         int ret = check_fd();
257
258         if (ret)
259                 return ret;
260
261         ret = ioctl(fd, DPAA_IOCTL_FREE_RAW_PORTAL, portal);
262         if (ret) {
263                 perror("ioctl(DPAA_IOCTL_FREE_RAW_PORTAL)");
264                 return ret;
265         }
266         return 0;
267 }
268
269 int qman_allocate_raw_portal(struct dpaa_raw_portal *portal)
270 {
271         struct dpaa_ioctl_raw_portal input;
272         int ret;
273
274         input.type = dpaa_portal_qman;
275         input.index = portal->index;
276         input.enable_stash = portal->enable_stash;
277         input.cpu = portal->cpu;
278         input.cache = portal->cache;
279         input.window = portal->window;
280         input.sdest = portal->sdest;
281
282         ret =  process_portal_allocate(&input);
283         if (ret)
284                 return ret;
285         portal->index = input.index;
286         portal->cinh = input.cinh;
287         portal->cena  = input.cena;
288         return 0;
289 }
290
291 int qman_free_raw_portal(struct dpaa_raw_portal *portal)
292 {
293         struct dpaa_ioctl_raw_portal input;
294
295         input.type = dpaa_portal_qman;
296         input.index = portal->index;
297         input.cinh = portal->cinh;
298         input.cena = portal->cena;
299
300         return process_portal_free(&input);
301 }
302
303 int bman_allocate_raw_portal(struct dpaa_raw_portal *portal)
304 {
305         struct dpaa_ioctl_raw_portal input;
306         int ret;
307
308         input.type = dpaa_portal_bman;
309         input.index = portal->index;
310         input.enable_stash = 0;
311
312         ret =  process_portal_allocate(&input);
313         if (ret)
314                 return ret;
315         portal->index = input.index;
316         portal->cinh = input.cinh;
317         portal->cena  = input.cena;
318         return 0;
319 }
320
321 int bman_free_raw_portal(struct dpaa_raw_portal *portal)
322 {
323         struct dpaa_ioctl_raw_portal input;
324
325         input.type = dpaa_portal_bman;
326         input.index = portal->index;
327         input.cinh = portal->cinh;
328         input.cena = portal->cena;
329
330         return process_portal_free(&input);
331 }