cf63ead95b2bed0458ddb4b0d7d346f1be1f4d63
[barrelfish] / usr / tests / devif / queue_interface.c
1 /*
2  * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
8  */
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <time.h>
13 #include <barrelfish/barrelfish.h>
14 #include <barrelfish/waitset.h>
15 #include <barrelfish/waitset_chan.h>
16 #include <barrelfish/deferred.h>
17 #include <devif/queue_interface.h>
18 #include <devif/backends/net/sfn5122f_devif.h>
19 #include <devif/backends/descq.h>
20 #include <bench/bench.h>
21
22
23 #define BUF_SIZE 2048
24 #define NUM_ENQ 512
25 #define NUM_RX_BUF 1024
26 #define NUM_ROUNDS_TX 16384
27 #define NUM_ROUNDS_RX 128
28 #define MEMORY_SIZE BASE_PAGE_SIZE*512
29
30 static struct capref memory_rx;
31 static struct capref memory_tx;
32 static regionid_t regid_rx;
33 static regionid_t regid_tx;
34 static struct frame_identity id;
35 static lpaddr_t phys_rx;
36 static lpaddr_t phys_tx;
37
38 static volatile uint32_t num_tx = 0;
39 static volatile uint32_t num_rx = 0;
40
41 static void* va_rx;
42 static void* va_tx;
43
44 struct direct_state {
45     struct list_ele* first;
46     struct list_ele* last;
47 };
48
49 struct list_ele{
50     regionid_t rid;
51     bufferid_t bid;
52     lpaddr_t addr;
53     size_t len;
54     uint64_t flags;
55    
56     struct list_ele* next;
57 };
58
59
60 static struct waitset_chanstate *chan = NULL;
61 static struct waitset card_ws;
62
63
64 static uint8_t udp_header[8] = {
65     0x07, 0xD0, 0x07, 0xD0,
66     0x00, 0x80, 0x00, 0x00,
67 };
68
69 /*
70 static void print_buffer(size_t len, bufferid_t bid)
71 {
72     uint8_t* buf = (uint8_t*) va_rx+bid;
73     printf("Packet in region %p at address %p len %zu \n", 
74             va_rx, buf, len);
75     for (int i = 0; i < len; i++) {
76         if (((i % 10) == 0) && i > 0) {
77             printf("\n");
78         }
79         printf("%2X ", buf[i]);   
80     }
81     printf("\n");
82 }
83 */
84
85 static void wait_for_interrupt(void)
86 {
87     errval_t err = event_dispatch(&card_ws);
88     if (err_is_fail(err)) {
89         USER_PANIC_ERR(err, "error in event_dispatch for wait_for_interrupt");
90     }
91 }
92
93 static void sfn5122f_event_cb(void* queue)
94 {
95     struct devq* q = (struct devq*) queue;
96
97     errval_t err;
98
99     regionid_t rid;
100     bufferid_t bid;
101     lpaddr_t addr;
102     size_t len;
103     uint64_t flags;
104
105     err = SYS_ERR_OK;
106
107     while (err == SYS_ERR_OK) {    
108         err = devq_dequeue(q, &rid, &addr, &len, &bid, &flags);
109         if (err_is_fail(err)) {
110             break;
111         }
112
113         switch (flags) {
114             case DEVQ_BUF_FLAG_TX:
115                 num_tx++;
116                 break;
117             case DEVQ_BUF_FLAG_RX:
118                 num_rx++;
119                 //print_buffer(len, bid);
120                 break;
121             case DEVQ_BUF_FLAG_TX + DEVQ_BUF_FLAG_TX_LAST:
122                 num_tx++;
123                 break;
124             default:
125                 printf("Unknown flags \n");
126         }    
127     }
128
129     // MSIX is not working on sfn5122f yet so we have to "simulate interrupts"
130     err = waitset_chan_register(&card_ws, chan, 
131                                 MKCLOSURE(sfn5122f_event_cb, queue));
132     if (err_is_fail(err) && err_no(err) == LIB_ERR_CHAN_ALREADY_REGISTERED) {
133         printf("Got actual interrupt?\n");
134     }
135     else if (err_is_fail(err)) {
136         USER_PANIC_ERR(err, "Can't register our dummy channel.");
137     }
138     err = waitset_chan_trigger(chan);
139     if (err_is_fail(err)) {
140         USER_PANIC_ERR(err, "trigger failed.");
141     }
142 }
143
144 static void test_sfn5122f_tx(void) 
145 {
146     num_tx = 0;
147     num_rx = 0;
148
149     errval_t err;
150     struct devq* q;   
151     struct sfn5122f_queue* queue;
152
153     printf("SFN5122F direct device test started \n");
154     err = sfn5122f_queue_create(&queue, sfn5122f_event_cb, true, false);
155     if (err_is_fail(err)){
156         USER_PANIC("Allocating devq failed \n");
157     }    
158     
159     q = (struct devq*) queue;    
160     
161
162     waitset_init(&card_ws);
163
164     // MSIX is not working on sfn5122f yet so we have to "simulate interrupts"
165     chan = malloc(sizeof(struct waitset_chanstate));
166     waitset_chanstate_init(chan, CHANTYPE_AHCI);
167
168     err = waitset_chan_register(&card_ws, chan, MKCLOSURE(sfn5122f_event_cb, q));
169     if (err_is_fail(err)) {
170         USER_PANIC_ERR(err, "waitset_chan_regster failed.");
171     }
172
173     err = waitset_chan_trigger(chan);
174     if (err_is_fail(err)) {
175         USER_PANIC_ERR(err, "trigger failed.");
176     }
177
178     err = devq_register(q, memory_tx, &regid_tx);
179     if (err_is_fail(err)){
180         USER_PANIC("Registering memory to devq failed \n");
181     }
182     
183     lpaddr_t addr;  
184     bufferid_t bid;
185
186     // write something into the buffers
187     char* write = NULL;
188     uint16_t rest = 4096 -BUF_SIZE;
189
190     for (int i = 0; i < NUM_ENQ; i++) {
191         write = va_tx + i*(BUF_SIZE+rest);
192         for (int j = 0; j < 8; j++) {
193             write[j] = udp_header[j];
194         }
195         for (int j = 8; j < BUF_SIZE; j++) {
196             write[j] = 'a';
197         }
198     }
199
200     // Send something
201     cycles_t t1 = bench_tsc();   
202
203     for (int z = 0; z < NUM_ROUNDS_TX; z++) {
204         for (int i = 0; i < NUM_ENQ; i++) {
205             addr = phys_tx+(i*(BUF_SIZE));
206
207             err = devq_enqueue(q, regid_tx, addr, BUF_SIZE, 
208                                DEVQ_BUF_FLAG_TX | DEVQ_BUF_FLAG_TX_LAST, &bid);
209             if (err_is_fail(err)){
210                 USER_PANIC("Devq enqueue failed \n");
211             }    
212         }
213
214         while(true) {
215             if ((num_tx < NUM_ENQ)) {
216                 wait_for_interrupt();
217             } else {
218                 break;
219             }
220         }
221         num_tx = 0;
222     }
223
224     cycles_t t2 = bench_tsc();
225     cycles_t result = (t2 -t1 - bench_tscoverhead());
226  
227     uint64_t sent_bytes = (uint64_t) BUF_SIZE*NUM_ENQ*NUM_ROUNDS_TX;
228     double result_ms = (double) bench_tsc_to_ms(result);
229     double bw = sent_bytes / result_ms / 1000;
230     
231     printf("Write throughput %.2f [MB/s] for %.2f ms \n", bw, result_ms);  
232
233     err = devq_control(q, 1, 1);
234     if (err_is_fail(err)){
235         printf("%s \n", err_getstring(err));
236         USER_PANIC("Devq control failed \n");
237     }
238
239     err = devq_deregister(q, regid_tx, &memory_tx);
240     if (err_is_fail(err)){
241         printf("%s \n", err_getstring(err));
242         USER_PANIC("Devq deregister tx failed \n");
243     }
244     
245     err = sfn5122f_queue_destroy((struct sfn5122f_queue*) q);
246
247     printf("SUCCESS: SFN5122F tx test ended\n");
248 }
249
250
251 static void test_sfn5122f_rx(void) 
252 {
253     num_tx = 0;
254     num_rx = 0;
255
256     errval_t err;
257     struct devq* q;   
258     struct sfn5122f_queue* queue;
259
260     printf("SFN5122F direct device test started \n");
261     err = sfn5122f_queue_create(&queue, sfn5122f_event_cb, /* userlevel*/ true, 
262                                 /*MSIX interrupts*/ false);
263     if (err_is_fail(err)){
264         USER_PANIC("Allocating devq failed \n");
265     }    
266     
267     q = (struct devq*) queue;    
268     
269
270     waitset_init(&card_ws);
271
272     // MSIX is not working on sfn5122f yet so we have to "simulate interrupts"
273     chan = malloc(sizeof(struct waitset_chanstate));
274     waitset_chanstate_init(chan, CHANTYPE_AHCI);
275
276     err = waitset_chan_register(&card_ws, chan, MKCLOSURE(sfn5122f_event_cb, q));
277     if (err_is_fail(err)) {
278         USER_PANIC_ERR(err, "waitset_chan_regster failed.");
279     }
280
281     err = waitset_chan_trigger(chan);
282     if (err_is_fail(err)) {
283         USER_PANIC_ERR(err, "trigger failed.");
284     }
285
286     err = devq_register(q, memory_rx, &regid_rx);
287     if (err_is_fail(err)){
288         USER_PANIC("Registering memory to devq failed \n");
289     }
290     
291     lpaddr_t addr;  
292     bufferid_t bid;
293
294     // Enqueue RX buffers to receive into
295     for (int i = 0; i < NUM_ROUNDS_RX; i++){
296         addr = phys_rx+(i*2048);
297         err = devq_enqueue(q, regid_rx, addr, 2048, 
298                            DEVQ_BUF_FLAG_RX, &bid);
299         if (err_is_fail(err)){
300             USER_PANIC("Devq enqueue failed: %s\n", err_getstring(err));
301         }    
302
303     }
304
305     while (true) {
306         if ((num_rx < NUM_ROUNDS_RX)) {
307             wait_for_interrupt();
308         } else {
309             break;
310         }
311     }
312
313
314     err = devq_control(q, 1, 1);
315     if (err_is_fail(err)){
316         printf("%s \n", err_getstring(err));
317         USER_PANIC("Devq control failed \n");
318     }
319
320     err = devq_deregister(q, regid_rx, &memory_rx);
321     if (err_is_fail(err)){
322         printf("%s \n", err_getstring(err));
323         USER_PANIC("Devq deregister rx failed \n");
324     }
325    
326     err = sfn5122f_queue_destroy((struct sfn5122f_queue*) q);
327
328     printf("SUCCESS: SFN5122F rx test ended\n");
329 }
330
331
332 static errval_t descq_notify(struct descq* q) 
333 {   
334     errval_t err = SYS_ERR_OK;
335     struct devq* queue = (struct devq*) q;
336     
337     regionid_t rid;
338     bufferid_t bid;
339     lpaddr_t addr;
340     uint64_t flags;
341     size_t len;
342
343     while(err_is_ok(err)) {
344         err = devq_dequeue(queue, &rid, &addr, &len, &bid, &flags);
345         if (err_is_ok(err)){
346             num_rx++;
347         }
348     }
349     return SYS_ERR_OK;
350 }
351
352 static void test_idc_queue(void)
353 {
354     num_tx = 0;
355     num_rx = 0;
356
357     errval_t err;
358     struct devq* q;   
359     struct descq* queue;
360     struct descq_func_pointer* f;
361     f = malloc(sizeof(struct descq_func_pointer));
362     f->notify = descq_notify;
363
364     printf("Descriptor queue test started \n");
365     err = descq_create(&queue, DESCQ_DEFAULT_SIZE, "test_queue",
366                        false, f);
367     if (err_is_fail(err)){
368         USER_PANIC("Allocating devq failed \n");
369     }    
370    
371     q = (struct devq*) queue;    
372
373     err = devq_register(q, memory_rx, &regid_rx);
374     if (err_is_fail(err)){
375         USER_PANIC("Registering memory to devq failed \n");
376     }
377   
378     err = devq_register(q, memory_tx, &regid_tx);
379     if (err_is_fail(err)){
380         USER_PANIC("Registering memory to devq failed \n");
381     }
382  
383     lpaddr_t addr;
384     bufferid_t bid;
385     // Enqueue RX buffers to receive into
386     for (int j = 0; j < 1000000; j++){
387         for (int i = 0; i < 32; i++){
388             addr = phys_rx+(i*2048);
389             err = devq_enqueue(q, regid_rx, addr, 2048, 
390                                0, &bid);
391             if (err_is_fail(err)){
392                 // retry
393                 i--;
394             } else {
395                 num_tx++;
396             }
397         }
398
399         err = devq_notify(q);
400         if (err_is_fail(err)) {
401                 USER_PANIC("Devq notify failed: %s\n", err_getstring(err));
402         }
403         event_dispatch(get_default_waitset());
404     }    
405
406     while(num_tx != num_rx) {
407         event_dispatch(get_default_waitset());
408     }
409
410     err = devq_control(q, 1, 1);
411     if (err_is_fail(err)){
412         printf("%s \n", err_getstring(err));
413         USER_PANIC("Devq control failed \n");
414     }
415
416     err = devq_deregister(q, regid_rx, &memory_rx);
417     if (err_is_fail(err)){
418         printf("%s \n", err_getstring(err));
419         USER_PANIC("Devq deregister rx failed \n");
420     }
421
422     err = devq_deregister(q, regid_tx, &memory_tx);
423     if (err_is_fail(err)){
424         printf("%s \n", err_getstring(err));
425         USER_PANIC("Devq deregister tx failed \n");
426     }
427
428     printf("SUCCESS: IDC queue\n");
429 }
430
431 int main(int argc, char *argv[])
432 {
433     errval_t err;
434     // Allocate memory
435     err = frame_alloc(&memory_rx, MEMORY_SIZE, NULL);
436     if (err_is_fail(err)){
437         USER_PANIC("Allocating cap failed \n");
438     }    
439
440     err = frame_alloc(&memory_tx, MEMORY_SIZE, NULL);
441     if (err_is_fail(err)){
442         USER_PANIC("Allocating cap failed \n");
443     }    
444     
445     // RX frame
446     err = invoke_frame_identify(memory_rx, &id);
447     if (err_is_fail(err)) {
448         USER_PANIC("Frame identify failed \n");
449     }
450
451     err = vspace_map_one_frame_attr(&va_rx, MEMORY_SIZE, memory_rx,
452                                     VREGION_FLAGS_READ, NULL, NULL); 
453     if (err_is_fail(err)) {
454         USER_PANIC("Frame mapping failed \n");
455     }
456
457     phys_rx = id.base;
458
459     // TX Frame
460     err = invoke_frame_identify(memory_tx, &id);
461     if (err_is_fail(err)) {
462         USER_PANIC("Frame identify failed \n");
463     }
464    
465     err = vspace_map_one_frame_attr(&va_tx, MEMORY_SIZE, memory_tx,
466                                     VREGION_FLAGS_WRITE, NULL, NULL); 
467     if (err_is_fail(err)) {
468         USER_PANIC("Frame mapping failed \n");
469     }
470
471     phys_tx = id.base;
472
473     if (strcmp(argv[1], "net_tx") == 0) {
474         test_sfn5122f_tx();
475     }
476
477     if (strcmp(argv[1], "net_rx") == 0) {
478         test_sfn5122f_rx();
479     }
480
481     if (strcmp(argv[1], "idc") == 0) {
482         test_idc_queue();
483     }
484
485
486     barrelfish_usleep(1000*1000*5);
487 }
488