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