aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/gxio
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2012-04-06 16:38:03 -0400
committerChris Metcalf <cmetcalf@tilera.com>2012-07-11 16:04:55 -0400
commit4875f69fecab08654972d6fb0d71ee2109d2538c (patch)
treea4e04bfe6c47e34a0a5309fc1c2735cd625b9ee9 /arch/tile/gxio
parent6369798037c0e915fc3e3844083f2aeecb924c9d (diff)
arch/tile: provide kernel support for the tilegx mPIPE shim
The TILE-Gx chip includes a packet-processing network engine called mPIPE ("Multicore Programmable Intelligent Packet Engine"). This change adds support for using the mPIPE engine from within the kernel. The engine has more functionality than is exposed here, but to keep the kernel code and binary simpler, this is a subset of the full API designed to enable standard Linux networking only. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Diffstat (limited to 'arch/tile/gxio')
-rw-r--r--arch/tile/gxio/Kconfig6
-rw-r--r--arch/tile/gxio/Makefile1
-rw-r--r--arch/tile/gxio/iorpc_mpipe.c529
-rw-r--r--arch/tile/gxio/iorpc_mpipe_info.c85
-rw-r--r--arch/tile/gxio/mpipe.c545
5 files changed, 1166 insertions, 0 deletions
diff --git a/arch/tile/gxio/Kconfig b/arch/tile/gxio/Kconfig
index ecd076c8cfd5..8aeebb70a3df 100644
--- a/arch/tile/gxio/Kconfig
+++ b/arch/tile/gxio/Kconfig
@@ -9,3 +9,9 @@ config TILE_GXIO
9config TILE_GXIO_DMA 9config TILE_GXIO_DMA
10 bool 10 bool
11 select TILE_GXIO 11 select TILE_GXIO
12
13# Support direct access to the TILE-Gx mPIPE hardware from kernel space.
14config TILE_GXIO_MPIPE
15 bool
16 select TILE_GXIO
17 select TILE_GXIO_DMA
diff --git a/arch/tile/gxio/Makefile b/arch/tile/gxio/Makefile
index 97ab468fb8c5..130eec48c152 100644
--- a/arch/tile/gxio/Makefile
+++ b/arch/tile/gxio/Makefile
@@ -4,3 +4,4 @@
4 4
5obj-$(CONFIG_TILE_GXIO) += iorpc_globals.o kiorpc.o 5obj-$(CONFIG_TILE_GXIO) += iorpc_globals.o kiorpc.o
6obj-$(CONFIG_TILE_GXIO_DMA) += dma_queue.o 6obj-$(CONFIG_TILE_GXIO_DMA) += dma_queue.o
7obj-$(CONFIG_TILE_GXIO_MPIPE) += mpipe.o iorpc_mpipe.o iorpc_mpipe_info.o
diff --git a/arch/tile/gxio/iorpc_mpipe.c b/arch/tile/gxio/iorpc_mpipe.c
new file mode 100644
index 000000000000..31b87bf8c027
--- /dev/null
+++ b/arch/tile/gxio/iorpc_mpipe.c
@@ -0,0 +1,529 @@
1/*
2 * Copyright 2012 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15/* This file is machine-generated; DO NOT EDIT! */
16#include "gxio/iorpc_mpipe.h"
17
18struct alloc_buffer_stacks_param {
19 unsigned int count;
20 unsigned int first;
21 unsigned int flags;
22};
23
24int gxio_mpipe_alloc_buffer_stacks(gxio_mpipe_context_t * context,
25 unsigned int count, unsigned int first,
26 unsigned int flags)
27{
28 struct alloc_buffer_stacks_param temp;
29 struct alloc_buffer_stacks_param *params = &temp;
30
31 params->count = count;
32 params->first = first;
33 params->flags = flags;
34
35 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
36 sizeof(*params),
37 GXIO_MPIPE_OP_ALLOC_BUFFER_STACKS);
38}
39
40EXPORT_SYMBOL(gxio_mpipe_alloc_buffer_stacks);
41
42struct init_buffer_stack_aux_param {
43 union iorpc_mem_buffer buffer;
44 unsigned int stack;
45 unsigned int buffer_size_enum;
46};
47
48int gxio_mpipe_init_buffer_stack_aux(gxio_mpipe_context_t * context,
49 void *mem_va, size_t mem_size,
50 unsigned int mem_flags, unsigned int stack,
51 unsigned int buffer_size_enum)
52{
53 int __result;
54 unsigned long long __cpa;
55 pte_t __pte;
56 struct init_buffer_stack_aux_param temp;
57 struct init_buffer_stack_aux_param *params = &temp;
58
59 __result = va_to_cpa_and_pte(mem_va, &__cpa, &__pte);
60 if (__result != 0)
61 return __result;
62 params->buffer.kernel.cpa = __cpa;
63 params->buffer.kernel.size = mem_size;
64 params->buffer.kernel.pte = __pte;
65 params->buffer.kernel.flags = mem_flags;
66 params->stack = stack;
67 params->buffer_size_enum = buffer_size_enum;
68
69 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
70 sizeof(*params),
71 GXIO_MPIPE_OP_INIT_BUFFER_STACK_AUX);
72}
73
74EXPORT_SYMBOL(gxio_mpipe_init_buffer_stack_aux);
75
76
77struct alloc_notif_rings_param {
78 unsigned int count;
79 unsigned int first;
80 unsigned int flags;
81};
82
83int gxio_mpipe_alloc_notif_rings(gxio_mpipe_context_t * context,
84 unsigned int count, unsigned int first,
85 unsigned int flags)
86{
87 struct alloc_notif_rings_param temp;
88 struct alloc_notif_rings_param *params = &temp;
89
90 params->count = count;
91 params->first = first;
92 params->flags = flags;
93
94 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
95 sizeof(*params), GXIO_MPIPE_OP_ALLOC_NOTIF_RINGS);
96}
97
98EXPORT_SYMBOL(gxio_mpipe_alloc_notif_rings);
99
100struct init_notif_ring_aux_param {
101 union iorpc_mem_buffer buffer;
102 unsigned int ring;
103};
104
105int gxio_mpipe_init_notif_ring_aux(gxio_mpipe_context_t * context, void *mem_va,
106 size_t mem_size, unsigned int mem_flags,
107 unsigned int ring)
108{
109 int __result;
110 unsigned long long __cpa;
111 pte_t __pte;
112 struct init_notif_ring_aux_param temp;
113 struct init_notif_ring_aux_param *params = &temp;
114
115 __result = va_to_cpa_and_pte(mem_va, &__cpa, &__pte);
116 if (__result != 0)
117 return __result;
118 params->buffer.kernel.cpa = __cpa;
119 params->buffer.kernel.size = mem_size;
120 params->buffer.kernel.pte = __pte;
121 params->buffer.kernel.flags = mem_flags;
122 params->ring = ring;
123
124 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
125 sizeof(*params),
126 GXIO_MPIPE_OP_INIT_NOTIF_RING_AUX);
127}
128
129EXPORT_SYMBOL(gxio_mpipe_init_notif_ring_aux);
130
131struct request_notif_ring_interrupt_param {
132 union iorpc_interrupt interrupt;
133 unsigned int ring;
134};
135
136int gxio_mpipe_request_notif_ring_interrupt(gxio_mpipe_context_t * context,
137 int inter_x, int inter_y,
138 int inter_ipi, int inter_event,
139 unsigned int ring)
140{
141 struct request_notif_ring_interrupt_param temp;
142 struct request_notif_ring_interrupt_param *params = &temp;
143
144 params->interrupt.kernel.x = inter_x;
145 params->interrupt.kernel.y = inter_y;
146 params->interrupt.kernel.ipi = inter_ipi;
147 params->interrupt.kernel.event = inter_event;
148 params->ring = ring;
149
150 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
151 sizeof(*params),
152 GXIO_MPIPE_OP_REQUEST_NOTIF_RING_INTERRUPT);
153}
154
155EXPORT_SYMBOL(gxio_mpipe_request_notif_ring_interrupt);
156
157struct enable_notif_ring_interrupt_param {
158 unsigned int ring;
159};
160
161int gxio_mpipe_enable_notif_ring_interrupt(gxio_mpipe_context_t * context,
162 unsigned int ring)
163{
164 struct enable_notif_ring_interrupt_param temp;
165 struct enable_notif_ring_interrupt_param *params = &temp;
166
167 params->ring = ring;
168
169 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
170 sizeof(*params),
171 GXIO_MPIPE_OP_ENABLE_NOTIF_RING_INTERRUPT);
172}
173
174EXPORT_SYMBOL(gxio_mpipe_enable_notif_ring_interrupt);
175
176struct alloc_notif_groups_param {
177 unsigned int count;
178 unsigned int first;
179 unsigned int flags;
180};
181
182int gxio_mpipe_alloc_notif_groups(gxio_mpipe_context_t * context,
183 unsigned int count, unsigned int first,
184 unsigned int flags)
185{
186 struct alloc_notif_groups_param temp;
187 struct alloc_notif_groups_param *params = &temp;
188
189 params->count = count;
190 params->first = first;
191 params->flags = flags;
192
193 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
194 sizeof(*params), GXIO_MPIPE_OP_ALLOC_NOTIF_GROUPS);
195}
196
197EXPORT_SYMBOL(gxio_mpipe_alloc_notif_groups);
198
199struct init_notif_group_param {
200 unsigned int group;
201 gxio_mpipe_notif_group_bits_t bits;
202};
203
204int gxio_mpipe_init_notif_group(gxio_mpipe_context_t * context,
205 unsigned int group,
206 gxio_mpipe_notif_group_bits_t bits)
207{
208 struct init_notif_group_param temp;
209 struct init_notif_group_param *params = &temp;
210
211 params->group = group;
212 params->bits = bits;
213
214 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
215 sizeof(*params), GXIO_MPIPE_OP_INIT_NOTIF_GROUP);
216}
217
218EXPORT_SYMBOL(gxio_mpipe_init_notif_group);
219
220struct alloc_buckets_param {
221 unsigned int count;
222 unsigned int first;
223 unsigned int flags;
224};
225
226int gxio_mpipe_alloc_buckets(gxio_mpipe_context_t * context, unsigned int count,
227 unsigned int first, unsigned int flags)
228{
229 struct alloc_buckets_param temp;
230 struct alloc_buckets_param *params = &temp;
231
232 params->count = count;
233 params->first = first;
234 params->flags = flags;
235
236 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
237 sizeof(*params), GXIO_MPIPE_OP_ALLOC_BUCKETS);
238}
239
240EXPORT_SYMBOL(gxio_mpipe_alloc_buckets);
241
242struct init_bucket_param {
243 unsigned int bucket;
244 MPIPE_LBL_INIT_DAT_BSTS_TBL_t bucket_info;
245};
246
247int gxio_mpipe_init_bucket(gxio_mpipe_context_t * context, unsigned int bucket,
248 MPIPE_LBL_INIT_DAT_BSTS_TBL_t bucket_info)
249{
250 struct init_bucket_param temp;
251 struct init_bucket_param *params = &temp;
252
253 params->bucket = bucket;
254 params->bucket_info = bucket_info;
255
256 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
257 sizeof(*params), GXIO_MPIPE_OP_INIT_BUCKET);
258}
259
260EXPORT_SYMBOL(gxio_mpipe_init_bucket);
261
262struct alloc_edma_rings_param {
263 unsigned int count;
264 unsigned int first;
265 unsigned int flags;
266};
267
268int gxio_mpipe_alloc_edma_rings(gxio_mpipe_context_t * context,
269 unsigned int count, unsigned int first,
270 unsigned int flags)
271{
272 struct alloc_edma_rings_param temp;
273 struct alloc_edma_rings_param *params = &temp;
274
275 params->count = count;
276 params->first = first;
277 params->flags = flags;
278
279 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
280 sizeof(*params), GXIO_MPIPE_OP_ALLOC_EDMA_RINGS);
281}
282
283EXPORT_SYMBOL(gxio_mpipe_alloc_edma_rings);
284
285struct init_edma_ring_aux_param {
286 union iorpc_mem_buffer buffer;
287 unsigned int ring;
288 unsigned int channel;
289};
290
291int gxio_mpipe_init_edma_ring_aux(gxio_mpipe_context_t * context, void *mem_va,
292 size_t mem_size, unsigned int mem_flags,
293 unsigned int ring, unsigned int channel)
294{
295 int __result;
296 unsigned long long __cpa;
297 pte_t __pte;
298 struct init_edma_ring_aux_param temp;
299 struct init_edma_ring_aux_param *params = &temp;
300
301 __result = va_to_cpa_and_pte(mem_va, &__cpa, &__pte);
302 if (__result != 0)
303 return __result;
304 params->buffer.kernel.cpa = __cpa;
305 params->buffer.kernel.size = mem_size;
306 params->buffer.kernel.pte = __pte;
307 params->buffer.kernel.flags = mem_flags;
308 params->ring = ring;
309 params->channel = channel;
310
311 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
312 sizeof(*params), GXIO_MPIPE_OP_INIT_EDMA_RING_AUX);
313}
314
315EXPORT_SYMBOL(gxio_mpipe_init_edma_ring_aux);
316
317
318int gxio_mpipe_commit_rules(gxio_mpipe_context_t * context, const void *blob,
319 size_t blob_size)
320{
321 const void *params = blob;
322
323 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, blob_size,
324 GXIO_MPIPE_OP_COMMIT_RULES);
325}
326
327EXPORT_SYMBOL(gxio_mpipe_commit_rules);
328
329struct register_client_memory_param {
330 unsigned int iotlb;
331 HV_PTE pte;
332 unsigned int flags;
333};
334
335int gxio_mpipe_register_client_memory(gxio_mpipe_context_t * context,
336 unsigned int iotlb, HV_PTE pte,
337 unsigned int flags)
338{
339 struct register_client_memory_param temp;
340 struct register_client_memory_param *params = &temp;
341
342 params->iotlb = iotlb;
343 params->pte = pte;
344 params->flags = flags;
345
346 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
347 sizeof(*params),
348 GXIO_MPIPE_OP_REGISTER_CLIENT_MEMORY);
349}
350
351EXPORT_SYMBOL(gxio_mpipe_register_client_memory);
352
353struct link_open_aux_param {
354 _gxio_mpipe_link_name_t name;
355 unsigned int flags;
356};
357
358int gxio_mpipe_link_open_aux(gxio_mpipe_context_t * context,
359 _gxio_mpipe_link_name_t name, unsigned int flags)
360{
361 struct link_open_aux_param temp;
362 struct link_open_aux_param *params = &temp;
363
364 params->name = name;
365 params->flags = flags;
366
367 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
368 sizeof(*params), GXIO_MPIPE_OP_LINK_OPEN_AUX);
369}
370
371EXPORT_SYMBOL(gxio_mpipe_link_open_aux);
372
373struct link_close_aux_param {
374 int mac;
375};
376
377int gxio_mpipe_link_close_aux(gxio_mpipe_context_t * context, int mac)
378{
379 struct link_close_aux_param temp;
380 struct link_close_aux_param *params = &temp;
381
382 params->mac = mac;
383
384 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
385 sizeof(*params), GXIO_MPIPE_OP_LINK_CLOSE_AUX);
386}
387
388EXPORT_SYMBOL(gxio_mpipe_link_close_aux);
389
390
391struct get_timestamp_aux_param {
392 uint64_t sec;
393 uint64_t nsec;
394 uint64_t cycles;
395};
396
397int gxio_mpipe_get_timestamp_aux(gxio_mpipe_context_t * context, uint64_t * sec,
398 uint64_t * nsec, uint64_t * cycles)
399{
400 int __result;
401 struct get_timestamp_aux_param temp;
402 struct get_timestamp_aux_param *params = &temp;
403
404 __result =
405 hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, sizeof(*params),
406 GXIO_MPIPE_OP_GET_TIMESTAMP_AUX);
407 *sec = params->sec;
408 *nsec = params->nsec;
409 *cycles = params->cycles;
410
411 return __result;
412}
413
414EXPORT_SYMBOL(gxio_mpipe_get_timestamp_aux);
415
416struct set_timestamp_aux_param {
417 uint64_t sec;
418 uint64_t nsec;
419 uint64_t cycles;
420};
421
422int gxio_mpipe_set_timestamp_aux(gxio_mpipe_context_t * context, uint64_t sec,
423 uint64_t nsec, uint64_t cycles)
424{
425 struct set_timestamp_aux_param temp;
426 struct set_timestamp_aux_param *params = &temp;
427
428 params->sec = sec;
429 params->nsec = nsec;
430 params->cycles = cycles;
431
432 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
433 sizeof(*params), GXIO_MPIPE_OP_SET_TIMESTAMP_AUX);
434}
435
436EXPORT_SYMBOL(gxio_mpipe_set_timestamp_aux);
437
438struct adjust_timestamp_aux_param {
439 int64_t nsec;
440};
441
442int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context,
443 int64_t nsec)
444{
445 struct adjust_timestamp_aux_param temp;
446 struct adjust_timestamp_aux_param *params = &temp;
447
448 params->nsec = nsec;
449
450 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
451 sizeof(*params),
452 GXIO_MPIPE_OP_ADJUST_TIMESTAMP_AUX);
453}
454
455EXPORT_SYMBOL(gxio_mpipe_adjust_timestamp_aux);
456
457struct arm_pollfd_param {
458 union iorpc_pollfd pollfd;
459};
460
461int gxio_mpipe_arm_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie)
462{
463 struct arm_pollfd_param temp;
464 struct arm_pollfd_param *params = &temp;
465
466 params->pollfd.kernel.cookie = pollfd_cookie;
467
468 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
469 sizeof(*params), GXIO_MPIPE_OP_ARM_POLLFD);
470}
471
472EXPORT_SYMBOL(gxio_mpipe_arm_pollfd);
473
474struct close_pollfd_param {
475 union iorpc_pollfd pollfd;
476};
477
478int gxio_mpipe_close_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie)
479{
480 struct close_pollfd_param temp;
481 struct close_pollfd_param *params = &temp;
482
483 params->pollfd.kernel.cookie = pollfd_cookie;
484
485 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
486 sizeof(*params), GXIO_MPIPE_OP_CLOSE_POLLFD);
487}
488
489EXPORT_SYMBOL(gxio_mpipe_close_pollfd);
490
491struct get_mmio_base_param {
492 HV_PTE base;
493};
494
495int gxio_mpipe_get_mmio_base(gxio_mpipe_context_t * context, HV_PTE *base)
496{
497 int __result;
498 struct get_mmio_base_param temp;
499 struct get_mmio_base_param *params = &temp;
500
501 __result =
502 hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, sizeof(*params),
503 GXIO_MPIPE_OP_GET_MMIO_BASE);
504 *base = params->base;
505
506 return __result;
507}
508
509EXPORT_SYMBOL(gxio_mpipe_get_mmio_base);
510
511struct check_mmio_offset_param {
512 unsigned long offset;
513 unsigned long size;
514};
515
516int gxio_mpipe_check_mmio_offset(gxio_mpipe_context_t * context,
517 unsigned long offset, unsigned long size)
518{
519 struct check_mmio_offset_param temp;
520 struct check_mmio_offset_param *params = &temp;
521
522 params->offset = offset;
523 params->size = size;
524
525 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
526 sizeof(*params), GXIO_MPIPE_OP_CHECK_MMIO_OFFSET);
527}
528
529EXPORT_SYMBOL(gxio_mpipe_check_mmio_offset);
diff --git a/arch/tile/gxio/iorpc_mpipe_info.c b/arch/tile/gxio/iorpc_mpipe_info.c
new file mode 100644
index 000000000000..d0254aa60cba
--- /dev/null
+++ b/arch/tile/gxio/iorpc_mpipe_info.c
@@ -0,0 +1,85 @@
1/*
2 * Copyright 2012 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15/* This file is machine-generated; DO NOT EDIT! */
16#include "gxio/iorpc_mpipe_info.h"
17
18
19struct enumerate_aux_param {
20 _gxio_mpipe_link_name_t name;
21 _gxio_mpipe_link_mac_t mac;
22};
23
24int gxio_mpipe_info_enumerate_aux(gxio_mpipe_info_context_t * context,
25 unsigned int idx,
26 _gxio_mpipe_link_name_t * name,
27 _gxio_mpipe_link_mac_t * mac)
28{
29 int __result;
30 struct enumerate_aux_param temp;
31 struct enumerate_aux_param *params = &temp;
32
33 __result =
34 hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, sizeof(*params),
35 (((uint64_t) idx << 32) |
36 GXIO_MPIPE_INFO_OP_ENUMERATE_AUX));
37 *name = params->name;
38 *mac = params->mac;
39
40 return __result;
41}
42
43EXPORT_SYMBOL(gxio_mpipe_info_enumerate_aux);
44
45struct get_mmio_base_param {
46 HV_PTE base;
47};
48
49int gxio_mpipe_info_get_mmio_base(gxio_mpipe_info_context_t * context,
50 HV_PTE *base)
51{
52 int __result;
53 struct get_mmio_base_param temp;
54 struct get_mmio_base_param *params = &temp;
55
56 __result =
57 hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, sizeof(*params),
58 GXIO_MPIPE_INFO_OP_GET_MMIO_BASE);
59 *base = params->base;
60
61 return __result;
62}
63
64EXPORT_SYMBOL(gxio_mpipe_info_get_mmio_base);
65
66struct check_mmio_offset_param {
67 unsigned long offset;
68 unsigned long size;
69};
70
71int gxio_mpipe_info_check_mmio_offset(gxio_mpipe_info_context_t * context,
72 unsigned long offset, unsigned long size)
73{
74 struct check_mmio_offset_param temp;
75 struct check_mmio_offset_param *params = &temp;
76
77 params->offset = offset;
78 params->size = size;
79
80 return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
81 sizeof(*params),
82 GXIO_MPIPE_INFO_OP_CHECK_MMIO_OFFSET);
83}
84
85EXPORT_SYMBOL(gxio_mpipe_info_check_mmio_offset);
diff --git a/arch/tile/gxio/mpipe.c b/arch/tile/gxio/mpipe.c
new file mode 100644
index 000000000000..e71c63390acc
--- /dev/null
+++ b/arch/tile/gxio/mpipe.c
@@ -0,0 +1,545 @@
1/*
2 * Copyright 2012 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15/*
16 * Implementation of mpipe gxio calls.
17 */
18
19#include <linux/errno.h>
20#include <linux/io.h>
21#include <linux/module.h>
22
23#include <gxio/iorpc_globals.h>
24#include <gxio/iorpc_mpipe.h>
25#include <gxio/iorpc_mpipe_info.h>
26#include <gxio/kiorpc.h>
27#include <gxio/mpipe.h>
28
29/* HACK: Avoid pointless "shadow" warnings. */
30#define link link_shadow
31
32int gxio_mpipe_init(gxio_mpipe_context_t *context, unsigned int mpipe_index)
33{
34 char file[32];
35
36 int fd;
37 int i;
38
39 snprintf(file, sizeof(file), "mpipe/%d/iorpc", mpipe_index);
40 fd = hv_dev_open((HV_VirtAddr) file, 0);
41 if (fd < 0) {
42 if (fd >= GXIO_ERR_MIN && fd <= GXIO_ERR_MAX)
43 return fd;
44 else
45 return -ENODEV;
46 }
47
48 context->fd = fd;
49
50 /* Map in the MMIO space. */
51 context->mmio_cfg_base = (void __force *)
52 iorpc_ioremap(fd, HV_MPIPE_CONFIG_MMIO_OFFSET,
53 HV_MPIPE_CONFIG_MMIO_SIZE);
54 if (context->mmio_cfg_base == NULL)
55 goto cfg_failed;
56
57 context->mmio_fast_base = (void __force *)
58 iorpc_ioremap(fd, HV_MPIPE_FAST_MMIO_OFFSET,
59 HV_MPIPE_FAST_MMIO_SIZE);
60 if (context->mmio_fast_base == NULL)
61 goto fast_failed;
62
63 /* Initialize the stacks. */
64 for (i = 0; i < 8; i++)
65 context->__stacks.stacks[i] = 255;
66
67 return 0;
68
69 fast_failed:
70 iounmap((void __force __iomem *)(context->mmio_cfg_base));
71 cfg_failed:
72 hv_dev_close(context->fd);
73 return -ENODEV;
74}
75
76EXPORT_SYMBOL_GPL(gxio_mpipe_init);
77
78int gxio_mpipe_destroy(gxio_mpipe_context_t *context)
79{
80 iounmap((void __force __iomem *)(context->mmio_cfg_base));
81 iounmap((void __force __iomem *)(context->mmio_fast_base));
82 return hv_dev_close(context->fd);
83}
84
85EXPORT_SYMBOL_GPL(gxio_mpipe_destroy);
86
87static int16_t gxio_mpipe_buffer_sizes[8] =
88 { 128, 256, 512, 1024, 1664, 4096, 10368, 16384 };
89
90gxio_mpipe_buffer_size_enum_t gxio_mpipe_buffer_size_to_buffer_size_enum(size_t
91 size)
92{
93 int i;
94 for (i = 0; i < 7; i++)
95 if (size <= gxio_mpipe_buffer_sizes[i])
96 break;
97 return i;
98}
99
100EXPORT_SYMBOL_GPL(gxio_mpipe_buffer_size_to_buffer_size_enum);
101
102size_t gxio_mpipe_buffer_size_enum_to_buffer_size(gxio_mpipe_buffer_size_enum_t
103 buffer_size_enum)
104{
105 if (buffer_size_enum > 7)
106 buffer_size_enum = 7;
107
108 return gxio_mpipe_buffer_sizes[buffer_size_enum];
109}
110
111EXPORT_SYMBOL_GPL(gxio_mpipe_buffer_size_enum_to_buffer_size);
112
113size_t gxio_mpipe_calc_buffer_stack_bytes(unsigned long buffers)
114{
115 const int BUFFERS_PER_LINE = 12;
116
117 /* Count the number of cachlines. */
118 unsigned long lines =
119 (buffers + BUFFERS_PER_LINE - 1) / BUFFERS_PER_LINE;
120
121 /* Convert to bytes. */
122 return lines * CHIP_L2_LINE_SIZE();
123}
124
125EXPORT_SYMBOL_GPL(gxio_mpipe_calc_buffer_stack_bytes);
126
127int gxio_mpipe_init_buffer_stack(gxio_mpipe_context_t *context,
128 unsigned int stack,
129 gxio_mpipe_buffer_size_enum_t
130 buffer_size_enum, void *mem, size_t mem_size,
131 unsigned int mem_flags)
132{
133 int result;
134
135 memset(mem, 0, mem_size);
136
137 result = gxio_mpipe_init_buffer_stack_aux(context, mem, mem_size,
138 mem_flags, stack,
139 buffer_size_enum);
140 if (result < 0)
141 return result;
142
143 /* Save the stack. */
144 context->__stacks.stacks[buffer_size_enum] = stack;
145
146 return 0;
147}
148
149EXPORT_SYMBOL_GPL(gxio_mpipe_init_buffer_stack);
150
151int gxio_mpipe_init_notif_ring(gxio_mpipe_context_t *context,
152 unsigned int ring,
153 void *mem, size_t mem_size,
154 unsigned int mem_flags)
155{
156 return gxio_mpipe_init_notif_ring_aux(context, mem, mem_size,
157 mem_flags, ring);
158}
159
160EXPORT_SYMBOL_GPL(gxio_mpipe_init_notif_ring);
161
162int gxio_mpipe_init_notif_group_and_buckets(gxio_mpipe_context_t *context,
163 unsigned int group,
164 unsigned int ring,
165 unsigned int num_rings,
166 unsigned int bucket,
167 unsigned int num_buckets,
168 gxio_mpipe_bucket_mode_t mode)
169{
170 int i;
171 int result;
172
173 gxio_mpipe_bucket_info_t bucket_info = { {
174 .group = group,
175 .mode = mode,
176 }
177 };
178
179 gxio_mpipe_notif_group_bits_t bits = { {0} };
180
181 for (i = 0; i < num_rings; i++)
182 gxio_mpipe_notif_group_add_ring(&bits, ring + i);
183
184 result = gxio_mpipe_init_notif_group(context, group, bits);
185 if (result != 0)
186 return result;
187
188 for (i = 0; i < num_buckets; i++) {
189 bucket_info.notifring = ring + (i % num_rings);
190
191 result = gxio_mpipe_init_bucket(context, bucket + i,
192 bucket_info);
193 if (result != 0)
194 return result;
195 }
196
197 return 0;
198}
199
200EXPORT_SYMBOL_GPL(gxio_mpipe_init_notif_group_and_buckets);
201
202int gxio_mpipe_init_edma_ring(gxio_mpipe_context_t *context,
203 unsigned int ring, unsigned int channel,
204 void *mem, size_t mem_size,
205 unsigned int mem_flags)
206{
207 memset(mem, 0, mem_size);
208
209 return gxio_mpipe_init_edma_ring_aux(context, mem, mem_size, mem_flags,
210 ring, channel);
211}
212
213EXPORT_SYMBOL_GPL(gxio_mpipe_init_edma_ring);
214
215void gxio_mpipe_rules_init(gxio_mpipe_rules_t *rules,
216 gxio_mpipe_context_t *context)
217{
218 rules->context = context;
219 memset(&rules->list, 0, sizeof(rules->list));
220}
221
222EXPORT_SYMBOL_GPL(gxio_mpipe_rules_init);
223
224int gxio_mpipe_rules_begin(gxio_mpipe_rules_t *rules,
225 unsigned int bucket, unsigned int num_buckets,
226 gxio_mpipe_rules_stacks_t *stacks)
227{
228 int i;
229 int stack = 255;
230
231 gxio_mpipe_rules_list_t *list = &rules->list;
232
233 /* Current rule. */
234 gxio_mpipe_rules_rule_t *rule =
235 (gxio_mpipe_rules_rule_t *) (list->rules + list->head);
236
237 unsigned int head = list->tail;
238
239 /*
240 * Align next rule properly.
241 *Note that "dmacs_and_vlans" will also be aligned.
242 */
243 unsigned int pad = 0;
244 while (((head + pad) % __alignof__(gxio_mpipe_rules_rule_t)) != 0)
245 pad++;
246
247 /*
248 * Verify room.
249 * ISSUE: Mark rules as broken on error?
250 */
251 if (head + pad + sizeof(*rule) >= sizeof(list->rules))
252 return GXIO_MPIPE_ERR_RULES_FULL;
253
254 /* Verify num_buckets is a power of 2. */
255 if (__builtin_popcount(num_buckets) != 1)
256 return GXIO_MPIPE_ERR_RULES_INVALID;
257
258 /* Add padding to previous rule. */
259 rule->size += pad;
260
261 /* Start a new rule. */
262 list->head = head + pad;
263
264 rule = (gxio_mpipe_rules_rule_t *) (list->rules + list->head);
265
266 /* Default some values. */
267 rule->headroom = 2;
268 rule->tailroom = 0;
269 rule->capacity = 16384;
270
271 /* Save the bucket info. */
272 rule->bucket_mask = num_buckets - 1;
273 rule->bucket_first = bucket;
274
275 for (i = 8 - 1; i >= 0; i--) {
276 int maybe =
277 stacks ? stacks->stacks[i] : rules->context->__stacks.
278 stacks[i];
279 if (maybe != 255)
280 stack = maybe;
281 rule->stacks.stacks[i] = stack;
282 }
283
284 if (stack == 255)
285 return GXIO_MPIPE_ERR_RULES_INVALID;
286
287 /* NOTE: Only entries at the end of the array can be 255. */
288 for (i = 8 - 1; i > 0; i--) {
289 if (rule->stacks.stacks[i] == 255) {
290 rule->stacks.stacks[i] = stack;
291 rule->capacity =
292 gxio_mpipe_buffer_size_enum_to_buffer_size(i -
293 1);
294 }
295 }
296
297 rule->size = sizeof(*rule);
298 list->tail = list->head + rule->size;
299
300 return 0;
301}
302
303EXPORT_SYMBOL_GPL(gxio_mpipe_rules_begin);
304
305int gxio_mpipe_rules_add_channel(gxio_mpipe_rules_t *rules,
306 unsigned int channel)
307{
308 gxio_mpipe_rules_list_t *list = &rules->list;
309
310 gxio_mpipe_rules_rule_t *rule =
311 (gxio_mpipe_rules_rule_t *) (list->rules + list->head);
312
313 /* Verify channel. */
314 if (channel >= 32)
315 return GXIO_MPIPE_ERR_RULES_INVALID;
316
317 /* Verify begun. */
318 if (list->tail == 0)
319 return GXIO_MPIPE_ERR_RULES_EMPTY;
320
321 rule->channel_bits |= (1UL << channel);
322
323 return 0;
324}
325
326EXPORT_SYMBOL_GPL(gxio_mpipe_rules_add_channel);
327
328int gxio_mpipe_rules_set_headroom(gxio_mpipe_rules_t *rules, uint8_t headroom)
329{
330 gxio_mpipe_rules_list_t *list = &rules->list;
331
332 gxio_mpipe_rules_rule_t *rule =
333 (gxio_mpipe_rules_rule_t *) (list->rules + list->head);
334
335 /* Verify begun. */
336 if (list->tail == 0)
337 return GXIO_MPIPE_ERR_RULES_EMPTY;
338
339 rule->headroom = headroom;
340
341 return 0;
342}
343
344EXPORT_SYMBOL_GPL(gxio_mpipe_rules_set_headroom);
345
346int gxio_mpipe_rules_commit(gxio_mpipe_rules_t *rules)
347{
348 gxio_mpipe_rules_list_t *list = &rules->list;
349 unsigned int size =
350 offsetof(gxio_mpipe_rules_list_t, rules) + list->tail;
351 return gxio_mpipe_commit_rules(rules->context, list, size);
352}
353
354EXPORT_SYMBOL_GPL(gxio_mpipe_rules_commit);
355
356int gxio_mpipe_iqueue_init(gxio_mpipe_iqueue_t *iqueue,
357 gxio_mpipe_context_t *context,
358 unsigned int ring,
359 void *mem, size_t mem_size, unsigned int mem_flags)
360{
361 /* The init call below will verify that "mem_size" is legal. */
362 unsigned int num_entries = mem_size / sizeof(gxio_mpipe_idesc_t);
363
364 iqueue->context = context;
365 iqueue->idescs = (gxio_mpipe_idesc_t *)mem;
366 iqueue->ring = ring;
367 iqueue->num_entries = num_entries;
368 iqueue->mask_num_entries = num_entries - 1;
369 iqueue->log2_num_entries = __builtin_ctz(num_entries);
370 iqueue->head = 1;
371#ifdef __BIG_ENDIAN__
372 iqueue->swapped = 0;
373#endif
374
375 /* Initialize the "tail". */
376 __gxio_mmio_write(mem, iqueue->head);
377
378 return gxio_mpipe_init_notif_ring(context, ring, mem, mem_size,
379 mem_flags);
380}
381
382EXPORT_SYMBOL_GPL(gxio_mpipe_iqueue_init);
383
384int gxio_mpipe_equeue_init(gxio_mpipe_equeue_t *equeue,
385 gxio_mpipe_context_t *context,
386 unsigned int edma_ring_id,
387 unsigned int channel,
388 void *mem, unsigned int mem_size,
389 unsigned int mem_flags)
390{
391 /* The init call below will verify that "mem_size" is legal. */
392 unsigned int num_entries = mem_size / sizeof(gxio_mpipe_edesc_t);
393
394 /* Offset used to read number of completed commands. */
395 MPIPE_EDMA_POST_REGION_ADDR_t offset;
396
397 int result = gxio_mpipe_init_edma_ring(context, edma_ring_id, channel,
398 mem, mem_size, mem_flags);
399 if (result < 0)
400 return result;
401
402 memset(equeue, 0, sizeof(*equeue));
403
404 offset.word = 0;
405 offset.region =
406 MPIPE_MMIO_ADDR__REGION_VAL_EDMA -
407 MPIPE_MMIO_ADDR__REGION_VAL_IDMA;
408 offset.ring = edma_ring_id;
409
410 __gxio_dma_queue_init(&equeue->dma_queue,
411 context->mmio_fast_base + offset.word,
412 num_entries);
413 equeue->edescs = mem;
414 equeue->mask_num_entries = num_entries - 1;
415 equeue->log2_num_entries = __builtin_ctz(num_entries);
416
417 return 0;
418}
419
420EXPORT_SYMBOL_GPL(gxio_mpipe_equeue_init);
421
422int gxio_mpipe_set_timestamp(gxio_mpipe_context_t *context,
423 const struct timespec *ts)
424{
425 cycles_t cycles = get_cycles();
426 return gxio_mpipe_set_timestamp_aux(context, (uint64_t)ts->tv_sec,
427 (uint64_t)ts->tv_nsec,
428 (uint64_t)cycles);
429}
430
431int gxio_mpipe_get_timestamp(gxio_mpipe_context_t *context,
432 struct timespec *ts)
433{
434 int ret;
435 cycles_t cycles_prev, cycles_now, clock_rate;
436 cycles_prev = get_cycles();
437 ret = gxio_mpipe_get_timestamp_aux(context, (uint64_t *)&ts->tv_sec,
438 (uint64_t *)&ts->tv_nsec,
439 (uint64_t *)&cycles_now);
440 if (ret < 0) {
441 return ret;
442 }
443
444 clock_rate = get_clock_rate();
445 ts->tv_nsec -= (cycles_now - cycles_prev) * 1000000000LL / clock_rate;
446 if (ts->tv_nsec < 0) {
447 ts->tv_nsec += 1000000000LL;
448 ts->tv_sec -= 1;
449 }
450 return ret;
451}
452
453int gxio_mpipe_adjust_timestamp(gxio_mpipe_context_t *context, int64_t delta)
454{
455 return gxio_mpipe_adjust_timestamp_aux(context, delta);
456}
457
458/* Get our internal context used for link name access. This context is
459 * special in that it is not associated with an mPIPE service domain.
460 */
461static gxio_mpipe_context_t *_gxio_get_link_context(void)
462{
463 static gxio_mpipe_context_t context;
464 static gxio_mpipe_context_t *contextp;
465 static int tried_open = 0;
466 static DEFINE_MUTEX(mutex);
467
468 mutex_lock(&mutex);
469
470 if (!tried_open) {
471 int i = 0;
472 tried_open = 1;
473
474 /*
475 * "4" here is the maximum possible number of mPIPE shims; it's
476 * an exaggeration but we shouldn't ever go beyond 2 anyway.
477 */
478 for (i = 0; i < 4; i++) {
479 char file[80];
480
481 snprintf(file, sizeof(file), "mpipe/%d/iorpc_info", i);
482 context.fd = hv_dev_open((HV_VirtAddr) file, 0);
483 if (context.fd < 0)
484 continue;
485
486 contextp = &context;
487 break;
488 }
489 }
490
491 mutex_unlock(&mutex);
492
493 return contextp;
494}
495
496int gxio_mpipe_link_enumerate_mac(int idx, char *link_name, uint8_t *link_mac)
497{
498 int rv;
499 _gxio_mpipe_link_name_t name;
500 _gxio_mpipe_link_mac_t mac;
501
502 gxio_mpipe_context_t *context = _gxio_get_link_context();
503 if (!context)
504 return GXIO_ERR_NO_DEVICE;
505
506 rv = gxio_mpipe_info_enumerate_aux(context, idx, &name, &mac);
507 if (rv >= 0) {
508 strncpy(link_name, name.name, sizeof(name.name));
509 memcpy(link_mac, mac.mac, sizeof(mac.mac));
510 }
511
512 return rv;
513}
514
515EXPORT_SYMBOL_GPL(gxio_mpipe_link_enumerate_mac);
516
517int gxio_mpipe_link_open(gxio_mpipe_link_t *link,
518 gxio_mpipe_context_t *context, const char *link_name,
519 unsigned int flags)
520{
521 _gxio_mpipe_link_name_t name;
522 int rv;
523
524 strncpy(name.name, link_name, sizeof(name.name));
525 name.name[GXIO_MPIPE_LINK_NAME_LEN - 1] = '\0';
526
527 rv = gxio_mpipe_link_open_aux(context, name, flags);
528 if (rv < 0)
529 return rv;
530
531 link->context = context;
532 link->channel = rv >> 8;
533 link->mac = rv & 0xFF;
534
535 return 0;
536}
537
538EXPORT_SYMBOL_GPL(gxio_mpipe_link_open);
539
540int gxio_mpipe_link_close(gxio_mpipe_link_t *link)
541{
542 return gxio_mpipe_link_close_aux(link->context, link->mac);
543}
544
545EXPORT_SYMBOL_GPL(gxio_mpipe_link_close);