DeviceQueue: solarflare: alloc slot on cap receive
[barrelfish] / lib / devif / backends / net / solarflare / devif_backend_solarflare.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 <barrelfish/barrelfish.h>
13 #include <barrelfish/waitset.h>
14 #include <barrelfish/deferred.h>
15 #include <barrelfish/nameservice_client.h>
16 #include <devif/queue_interface.h>
17 #include <pci/pci.h>
18 #include <if/sfn5122f_devif_defs.h>
19 #include <if/sfn5122f_devif_rpcclient_defs.h>
20 #include <devif/backends/net/sfn5122f_devif.h>
21 #include "../../../queue_interface_internal.h"
22 #include "hw_queue.h"
23 #include "helper.h"
24
25 //#define DEBUG_SFN
26 #ifdef DEBUG_SFN
27     #define DEBUG_QUEUE(x...) printf("sfn5122f_q : " x)
28 #else
29     #define DEBUG_QUEUE(x...) do {} while (0)
30 #endif
31
32 //#define DELAY 1
33
34 // TX Queue
35 #define TX_ENTRIES 2048
36 #define RX_ENTRIES 2048
37 // Event Queue
38 #define EV_CODE_RX 0
39 #define EV_CODE_TX 2
40 #define EV_CODE_DRV 5
41 #define EV_CODE_DRV_GEN 7
42 #define EV_CODE_USER 8
43 #define EV_CODE_MCDI 12
44 #define EV_CODE_GLOBAL 6
45 #define EV_CODE_NONE 15
46
47 #define BUF_SIZE 4096
48
49 /* for each TX/RX entry one entry plus an additonal 2 for mcdi completion
50 and link state events */
51 #define EV_ENTRIES 4096
52
53 /**  Misc             */
54 static errval_t update_rxtail(struct sfn5122f_queue* q, size_t tail)
55 {
56     assert(q->device != NULL);
57     uint64_t reg = 0;
58
59     reg = sfn5122f_rx_desc_upd_reg_hi_rx_desc_wptr_insert(reg, tail);
60     /* don't want to push an additional rx descriptor with the write pointer */
61     reg = sfn5122f_rx_desc_upd_reg_hi_rx_desc_push_cmd_insert(reg, 0);
62     /* the lower register will be ignored   */
63     sfn5122f_rx_desc_upd_reg_lo_wr(q->device, q->id, 0);
64     sfn5122f_rx_desc_upd_reg_hi_wr(q->device, q->id, reg);
65
66     return SYS_ERR_OK;
67 }
68
69 static errval_t update_txtail(struct sfn5122f_queue* q, size_t tail)
70 {
71     assert(q->device != NULL);
72     uint64_t reg = 0;
73     reg = sfn5122f_tx_desc_upd_reg_hi_tx_desc_wptr_insert(reg, tail);
74     /* don't want to push an additional tx descriptor with the write pointer */
75     reg = sfn5122f_tx_desc_upd_reg_hi_tx_desc_push_cmd_insert(reg, 0);
76     reg = sfn5122f_tx_desc_upd_reg_hi_tx_desc_insert(reg, 0);
77
78     /*  the lower register will be ignored  */
79     sfn5122f_tx_desc_upd_reg_lo_wr(q->device, q->id, 0);
80     sfn5122f_tx_desc_upd_reg_hi_wr(q->device, q->id, reg);
81     return SYS_ERR_OK;
82 }
83
84 static void bind_cb(void *st, errval_t err, struct sfn5122f_devif_binding *b)
85 {
86     
87     DEBUG_QUEUE("binding CB  \n");
88     struct sfn5122f_queue* queue = (struct sfn5122f_queue*) st;
89     b->st = queue;
90     // Initi RPC client
91     
92     queue->b = b;
93     queue->rpc = malloc(sizeof(struct sfn5122f_devif_rpc_client));
94     assert(queue->rpc != NULL);
95
96     err = sfn5122f_devif_rpc_client_init(queue->rpc, b);
97     if (err_is_fail(err)) {
98        free(queue->rpc);
99     }   
100  
101     queue->bound = true;   
102 }
103
104
105 static errval_t sfn5122f_register(struct devq* q, struct capref cap,
106                                   regionid_t rid) 
107 {
108     uint64_t buftbl_idx = 0;
109     errval_t err, err2;
110     struct frame_identity id;
111
112     struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
113
114     if (queue->userspace) {
115         err = queue->rpc->vtbl.register_region(queue->rpc, queue->id, cap, 
116                                                &buftbl_idx, &err2);
117         if (err_is_fail(err) || err_is_fail(err2)) {
118             err = err_is_fail(err) ? err: err2;
119             return err;
120         }
121     }
122
123     err = invoke_frame_identify(cap, &id);
124     if (err_is_fail(err)) {
125         return err;
126     }
127
128     // Setup datastructure for translating region ID to buffer table entry id
129     // Currently only a linked list
130     struct region_entry* entry = malloc(sizeof(struct region_entry));
131     entry->rid = rid;
132     entry->phys = id.base;
133     entry->size = id.bytes;
134     entry->cap = cap;
135     entry->buftbl_idx = buftbl_idx;
136     entry->next = NULL;
137     
138     struct region_entry* cur = queue->regions;
139
140     if (cur == NULL) {
141         queue->regions = entry;
142         return SYS_ERR_OK;
143     }
144
145     while (cur->next != NULL) {
146         cur = cur->next;
147     }  
148     
149     cur->next = entry;
150     
151     return SYS_ERR_OK;
152 }
153
154 static errval_t sfn5122f_deregister(struct devq* q, regionid_t rid) 
155 {
156     errval_t err, err2;
157     
158     struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
159
160     // find region and translate to buftlb entry 
161     struct region_entry* cur = queue->regions;
162
163     if (cur == NULL) {
164         return SFN_ERR_DEREGISTER_REGION;
165     }
166
167     while (cur->next != NULL && cur->rid != rid) {
168         cur = cur->next;
169     }  
170    
171     // do rpc do inform carddriver to remove buftbl entries
172     if (queue->userspace) {
173         err = queue->rpc->vtbl.deregister_region(queue->rpc, cur->buftbl_idx, cur->size,
174                                                  &err2);
175         if (err_is_fail(err) || err_is_fail(err2)) {
176             err = err_is_fail(err) ? err: err2;
177             return err;
178         }
179     }
180
181     return SYS_ERR_OK;
182 }
183
184
185 static errval_t sfn5122f_control(struct devq* q, uint64_t cmd, uint64_t value)
186 {
187
188     DEBUG_QUEUE("Control cmd=%lu value=%lu \n", cmd, value);
189     return SYS_ERR_OK;
190 }
191
192
193 static errval_t sfn5122f_notify(struct devq* q)
194 {
195     DEBUG_QUEUE("Notify \n");
196     return SYS_ERR_OK;
197 }
198
199 static errval_t enqueue_rx_buf(struct sfn5122f_queue* q, regionid_t rid,
200                                bufferid_t bid, lpaddr_t base, size_t len, 
201                                uint64_t flags)
202 {
203
204     DEBUG_QUEUE("Enqueueing RX buf \n");
205     // check if there is space
206     if (sfn5122f_queue_free_rxslots(q) == 0) {
207         printf("SFN5122F_%d: Not enough space in RX ring, not adding buffer\n", 
208                 q->id);
209         return SFN_ERR_ENQUEUE;
210     }
211
212     // find region
213     struct region_entry* entry = q->regions;
214     
215     while((entry->next != NULL) && (entry->rid != rid)) {
216         entry = entry->next;
217     }
218     
219     if (entry == NULL) {
220         return SFN_ERR_ENQUEUE;
221     }
222     
223     // compute buffer table entry of the rx buffer and the within it offset
224     uint64_t buftbl_idx = entry->buftbl_idx + (bid/BUF_SIZE);
225     uint16_t offset = bid & 0x00000FFF;    
226
227     // still in the same buffer table entry
228     assert(buftbl_idx == (entry->buftbl_idx + ((bid+len-1)/BUF_SIZE)));
229
230    
231     DEBUG_QUEUE("RX_BUF tbl_idx=%lu offset=%d flags=%lu \n", 
232                 buftbl_idx, offset, flags);
233     if (q->userspace) {
234         sfn5122f_queue_add_user_rxbuf_devif(q, buftbl_idx, offset,
235                                             rid, bid, base, len, flags);
236     } else {
237         sfn5122f_queue_add_rxbuf_devif(q, rid, bid, base, 
238                                        len, flags);
239     }
240     sfn5122f_queue_bump_rxtail(q);
241     return SYS_ERR_OK;
242 }
243
244
245 static errval_t enqueue_tx_buf(struct sfn5122f_queue* q, regionid_t rid,
246                                bufferid_t bid, lpaddr_t base, size_t len, 
247                                uint64_t flags)
248 {
249     DEBUG_QUEUE("Enqueueing TX buf \n");
250     // check if there is space
251     if (sfn5122f_queue_free_txslots(q) == 0) {
252         printf("SFN5122F_%d: Not enough space in TX ring, not adding buffer\n", 
253                 q->id);
254         return SFN_ERR_ENQUEUE;
255     }
256
257     // find region
258     struct region_entry* entry = q->regions;
259     
260     while((entry->next != NULL) && (entry->rid != rid)) {
261         entry = entry->next;
262     }
263     
264     if (entry == NULL) {
265         return SFN_ERR_ENQUEUE;
266     }
267     
268     // compute buffer table entry of the rx buffer and the within it offset
269     uint64_t buftbl_idx = entry->buftbl_idx + (bid/BUF_SIZE);
270     uint16_t offset = bid & 0x00000FFF;    
271
272
273     // still in the same buffer table entry
274     assert(buftbl_idx == (entry->buftbl_idx + ((bid+len-1)/BUF_SIZE)));
275
276     DEBUG_QUEUE("TX_BUF tbl_idx=%lu offset=%d flags=%lu \n", buftbl_idx, offset,
277                 flags);
278     if (q->userspace) {
279
280         DEBUG_QUEUE("TX_BUF tbl_idx=%lu offset=%d flags=%lu \n", buftbl_idx, offset,
281                     flags);
282         sfn5122f_queue_add_user_txbuf_devif(q, buftbl_idx, offset,
283                                             rid, bid, base, len, flags);
284     } else {
285
286         DEBUG_QUEUE("TX_BUF flags=%lu \n", flags);
287         sfn5122f_queue_add_txbuf_devif(q, rid, bid, base, 
288                                        len, flags);
289     }
290     sfn5122f_queue_bump_txtail(q);
291     return SYS_ERR_OK;
292 }
293
294 static errval_t sfn5122f_enqueue(struct devq* q, regionid_t rid, bufferid_t bid, 
295                                  lpaddr_t base, size_t len, uint64_t flags)
296 {
297     errval_t err;
298
299
300     struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
301     if (flags & DEVQ_BUF_FLAG_RX) {
302         /* can not enqueue receive buffer larger than 2048 bytes */
303         assert(len <= 2048);
304
305         err = enqueue_rx_buf(queue, rid, bid, base, len, flags);
306         if (err_is_fail(err)) {
307             return err;
308         }      
309     } else if (flags & DEVQ_BUF_FLAG_TX) {
310         assert(len <= BASE_PAGE_SIZE);
311
312         err = enqueue_tx_buf(queue, rid, bid, base, len, flags);
313         if (err_is_fail(err)) {
314             return err;
315         } 
316     }
317
318     return SYS_ERR_OK;
319 }
320
321 static errval_t sfn5122f_dequeue(struct devq* q, regionid_t* rid, bufferid_t* bid, 
322                                  lpaddr_t* base, size_t* len, uint64_t* flags)
323 {
324     uint8_t ev_code;
325     errval_t err = DEVQ_ERR_RX_EMPTY;    
326     
327     struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
328
329     sfn5122f_evq_rptr_reg_wr(queue->device, queue->id, queue->ev_head);
330     //__sync_synchronize();
331
332     if (queue->num_left > 0) {
333         *rid = queue->bufs[queue->last_deq].rid;
334         *bid = queue->bufs[queue->last_deq].bid;
335         *flags = queue->bufs[queue->last_deq].flags;
336         *base = queue->bufs[queue->last_deq].addr;
337         *len = queue->bufs[queue->last_deq].len;
338         queue->num_left--;
339         queue->last_deq++;
340         return SYS_ERR_OK;   
341     }    
342
343     while(true) {
344         ev_code = sfn5122f_get_event_code(queue);
345         switch(ev_code){
346         case EV_CODE_RX:
347             // TODO multiple packets
348             err = sfn5122f_queue_handle_rx_ev_devif(queue, rid, bid, base,
349                                                     len, flags);  
350             if (err_is_ok(err)) {
351                 DEBUG_QUEUE(" RX_EV Q_ID: %d len %ld \n", queue->id, *len);
352             }
353             sfn5122f_queue_bump_evhead(queue);
354             return SYS_ERR_OK;
355         case EV_CODE_TX:
356             err = sfn5122f_queue_handle_tx_ev_devif(queue, rid, bid, base, 
357                                                     len, flags);
358             if (err_is_ok(err)) {
359                 DEBUG_QUEUE("TX EVENT OK %d \n", queue->id);               
360             } else {
361                 DEBUG_QUEUE("TX EVENT ERR %d \n", queue->id);
362             }
363
364             sfn5122f_queue_bump_evhead(queue);
365             return SYS_ERR_OK;
366         case EV_CODE_DRV:
367             //DEBUG_QUEUE("DRIVER EVENT %d\n", qi);
368             sfn5122f_handle_drv_ev(queue, queue->id);
369             sfn5122f_queue_bump_evhead(queue);
370             break;
371         case EV_CODE_DRV_GEN:
372             DEBUG_QUEUE("DRIVER GENERATED EVENT \n");
373             sfn5122f_queue_bump_evhead(queue);
374             break;
375         case EV_CODE_USER:
376             DEBUG_QUEUE("USER EVENT \n");
377             sfn5122f_queue_bump_evhead(queue);
378             break;
379         case EV_CODE_MCDI:
380             //DEBUG_QUEUE("MCDI EVENT \n");
381             sfn5122f_queue_handle_mcdi_event(queue);
382             sfn5122f_queue_bump_evhead(queue);
383             break;
384         case EV_CODE_GLOBAL:
385             DEBUG_QUEUE("GLOBAL EVENT \n");
386             sfn5122f_queue_bump_evhead(queue);
387             break;
388         case EV_CODE_NONE:
389             sfn5122f_evq_rptr_reg_wr(queue->device, queue->id, 
390                                      queue->ev_head);
391             return err;
392         }
393     }
394
395     return err;
396 }
397
398 static void interrupt_handler(void* arg)
399 {
400     printf("WTF \n");
401     struct sfn5122f_queue* queue = (struct sfn5122f_queue*) arg;
402     // TODO check fata interrupts
403
404     queue->cb(queue);
405 }
406
407 /**
408  * Public functions
409  *
410  */
411
412 errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, sfn5122f_event_cb_t cb, 
413                                bool userlevel, bool interrupts)
414 {
415     DEBUG_QUEUE("create called \n");
416
417     errval_t err;
418     //struct capref tx_frame, rx_frame, ev_frame;
419     struct capref frame;
420     //size_t tx_size, rx_size, ev_size;
421     size_t total_size;
422     void *tx_virt, *rx_virt, *ev_virt;
423     struct sfn5122f_queue* queue;
424     struct frame_identity id;
425
426     struct sfn5122f_queue_ops ops = {
427         .update_txtail = update_txtail,
428         .update_rxtail = update_rxtail
429      };
430    
431     /* Allocate memory for descriptor rings  
432        No difference for userspace networking*/
433     // TODO too large ...
434     total_size = sizeof(uint64_t)*(TX_ENTRIES + RX_ENTRIES + EV_ENTRIES);
435     tx_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, total_size, &frame);
436     if (tx_virt == NULL) {
437         return SFN_ERR_ALLOC_QUEUE;
438     }
439
440     rx_virt = tx_virt + (sizeof(uint64_t) *TX_ENTRIES);
441     ev_virt = rx_virt + (sizeof(uint64_t) *RX_ENTRIES);
442
443     DEBUG_QUEUE("queue init \n");
444     // Init queue
445     queue = sfn5122f_queue_init(tx_virt, TX_ENTRIES, rx_virt, RX_ENTRIES,
446                                 ev_virt, EV_ENTRIES, &ops, userlevel);
447
448     queue->frame = frame;
449     queue->bound = false;
450     queue->cb = cb;
451
452     
453     iref_t iref;
454     const char *name = "sfn5122f_sfn5122fmng_devif";
455
456     // Connect to solarflare card driver
457     err = nameservice_blocking_lookup(name, &iref);
458     if (err_is_fail(err)) {
459         return err;
460     }
461
462     DEBUG_QUEUE("binding \n");
463     err = sfn5122f_devif_bind(iref, bind_cb, queue, get_default_waitset(),
464                               1);
465     if (err_is_fail(err)) {
466         return err;
467     }
468
469     // wait until bound
470     while(!queue->bound) {
471         event_dispatch(get_default_waitset());
472     }
473
474     DEBUG_QUEUE("bound \n");
475
476     errval_t err2;
477     struct capref regs;
478
479     // Inform card driver about new queue and get the registers/queue id
480     err = slot_alloc(&regs);
481     if (err_is_fail(err)) {
482         return err;
483     }
484
485     if (!interrupts) {
486         printf("Solarflare queue used in polling mode \n");
487         err = queue->rpc->vtbl.create_queue(queue->rpc, frame, userlevel, interrupts, 
488                                             0, 0, &queue->id, &regs, &err2);
489         if (err_is_fail(err) || err_is_fail(err2)) {
490             err = err_is_fail(err) ? err: err2;
491             return err;
492         }
493     } else {
494         printf("Solarflare queue used in interrupt mode mode \n");
495         err = pci_setup_inthandler(interrupt_handler, queue, &queue->vector);
496         assert(err_is_ok(err));
497
498         queue->core = disp_get_core_id();
499         
500         err = queue->rpc->vtbl.create_queue(queue->rpc, frame, userlevel, 
501                                             interrupts, queue->core,
502                                             queue->vector, &queue->id, 
503                                             &regs, &err2);
504         if (err_is_fail(err) || err_is_fail(err2)) {
505             err = err_is_fail(err) ? err: err2;
506             printf("Registering interrupt failed, continueing in polling mode \n");
507         }
508     }
509
510     DEBUG_QUEUE("rpc done \n");
511     
512     err = invoke_frame_identify(regs, &id);
513     if (err_is_fail(err)) {
514         return err;
515     }
516
517     err = vspace_map_one_frame_attr(&queue->device_va, id.bytes, regs, 
518                                     VREGION_FLAGS_READ_WRITE, NULL, NULL);
519     if (err_is_fail(err)) {
520         return err;
521     }
522       
523
524     DEBUG_QUEUE("mapped \n");
525     queue->device = malloc(sizeof(sfn5122f_t));
526     sfn5122f_initialize(queue->device, queue->device_va);
527
528     err = devq_init(&queue->q, false);
529     if (err_is_fail(err)) {
530         return err;
531     }
532     
533     queue->q.f.enq = sfn5122f_enqueue;
534     queue->q.f.deq = sfn5122f_dequeue;
535     queue->q.f.reg = sfn5122f_register;
536     queue->q.f.dereg = sfn5122f_deregister;
537     queue->q.f.ctrl = sfn5122f_control;
538     queue->q.f.notify = sfn5122f_notify;
539     
540     *q = queue;
541
542     return SYS_ERR_OK;
543 }
544
545 errval_t sfn5122f_queue_destroy(struct sfn5122f_queue* q)
546 {
547     errval_t err, err2;
548     err = q->rpc->vtbl.destroy_queue(q->rpc, q->id, &err2);
549     if (err_is_fail(err) || err_is_fail(err2)) {
550         err = err_is_fail(err) ? err: err2;
551         return err;
552     }
553
554     err = vspace_unmap(q->device_va);
555     if (err_is_fail(err)) {
556         return err;
557     }
558
559     free(q->device);
560     free(q->rpc);
561
562     err = devq_destroy(&(q->q));
563     if (err_is_fail(err)){
564         return err;
565     }
566
567     err = sfn5122f_queue_free(q);
568     if (err_is_fail(err)) {
569         return err;
570     }
571
572     return SYS_ERR_OK;
573 }
574