e10k: driver working using legacy descriptors
[barrelfish] / lib / devif / backends / net / e10k / devif_backend_e10k.c
1 /*
2  * Copyright (c) 2007-2011, 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 <barrelfish/barrelfish.h>
11 #include <barrelfish/nameservice_client.h>
12 #include <devif/backends/net/e10k_devif.h>
13 #include <devif/queue_interface.h>
14 #include <dev/e10k_q_dev.h>
15 #include <dev/e10k_dev.h>
16 #include <dev/e10k_vf_dev.h>
17 #include <skb/skb.h>
18
19
20 #include <if/e10k_vf_defs.h>
21 #include <if/e10k_vf_rpcclient_defs.h>
22
23 #include "e10k_devif_vf.h"
24 #include "helper.h"
25 #include "e10k_queue.h"
26 #include "debug.h"
27
28 #define NUM_TX_DESC 2048
29 #define NUM_RX_DESC 2048
30
31 #define ETHHDR_LEN 14
32 #define IPHDR_LEN 20
33 #define UDPHDR_LEN 8
34
35
36 // for debugging
37 static e10k_t* d;
38
39 /*
40 static void queue_debug(const char* fmt, ...)
41 {
42     va_list va;
43     va_start(va, fmt);
44     printf("e10k.queue_handle%d: ", 0);
45     vprintf(fmt, va);
46     va_end(va);
47 }
48
49 #define prnonz(x) uint32_t x = e10k_##x##_rd(d); if (x) snprintf(str[cnt++], 32, #x "=%x", x)
50 #define prnonzary(x, n)                       \
51   for(int i = 0; i < n; i++) {                \
52     uint32_t reg = e10k_##x##_rd(d, i);       \
53     if (reg) snprintf(str[cnt++], 32, #x ".%d=%x", i, reg);     \
54   }
55 static void stats_dump(void)
56 {
57   char str[256][32];
58   int cnt = 0;
59   memset(str, 0, 256 * 32);
60
61   prnonzary(pfvfte, 2);
62   prnonz(picause);
63   prnonz(rttdcs);
64
65   prnonz(fwsm);
66   prnonz(eicr);
67
68   prnonz(dmatxctl);
69   prnonzary(tdbal, 128);
70   prnonzary(tdbah, 128);
71   prnonzary(tdlen, 128);
72   prnonzary(tdh, 128);
73   prnonzary(tdt, 128);
74   prnonzary(txdctl, 128);
75   prnonzary(tdwbal, 128);
76   prnonzary(tdwbah, 128);
77   prnonz(mtqc);
78
79     prnonz(crcerrs);
80     prnonz(illerrc);
81     prnonz(errbc);
82     prnonzary(rxmpc, 8);
83     prnonz(mlfc);
84     prnonz(mrfc);
85     prnonz(rlec);
86     prnonz(ssvpc);
87     // ...
88     prnonz(gprc);
89     prnonz(gorcl);
90     prnonz(gorch);
91     prnonz(rxnfgpc);
92     // ...
93     prnonz(rxdgpc);
94     // ...
95     prnonz(gptc);
96     prnonz(gotcl);
97     prnonz(gotch);
98     prnonz(txdgpc);
99     // ...
100     prnonz(ruc);
101     prnonz(rfc);
102     prnonz(roc);
103     prnonz(rjc);
104     prnonz(mngprc);
105     prnonz(mngpdc);
106     prnonz(torl);
107     prnonz(torh);
108     prnonz(tpr);
109     prnonz(tpt);
110     // ...
111     prnonz(mspdc);
112     // ...
113     prnonzary(qprc, 16);
114     prnonzary(qprdc, 16);
115     // ...
116
117     if(cnt > 0) {
118       queue_debug("");
119       for(int i = 0; i < cnt; i++) {
120         printf("%s ", str[i]);
121       }
122       printf("\n");
123     }
124 }
125 */
126 /******************************************************************************/
127 /* Misc functions */
128
129
130 static inline bool buf_use_tcpxsm(uint64_t flags)
131 {
132     return (flags & NETIF_TXFLAG_TCPCHECKSUM);
133 }
134
135 static inline bool buf_use_udpxsm(uint64_t flags)
136 {
137     return (flags & NETIF_TXFLAG_UDPCHECKSUM);
138 }
139
140 static inline bool buf_use_ipxsm(uint64_t flags)
141 {
142     return (flags & NETIF_TXFLAG_IPCHECKSUM) ||
143         buf_use_tcpxsm(flags) || buf_use_udpxsm(flags);
144 }
145
146 static inline uint8_t buf_tcphdrlen(uint64_t flags)
147 {
148     return ((flags & NETIF_TXFLAG_TCPHDRLEN_MASK) >>
149         NETIF_TXFLAG_TCPHDRLEN_SHIFT) * 4;
150 }
151
152 static errval_t update_txtail(struct e10k_queue* q, size_t tail)
153 {
154     assert(q->d != NULL);
155
156     if (q->use_vf) {
157         e10k_vf_vftdt_wr(q->d, q->id, tail);
158     } else {
159         e10k_tdt_wr(q->d, q->id, tail);
160     }
161     return SYS_ERR_OK;
162 }
163
164 static errval_t update_rxtail(struct e10k_queue* q, size_t tail)
165 {
166     assert(q->d != NULL);
167
168     if (q->use_vf) {
169         e10k_vf_vfrdt_wr(q->d, q->id, tail);
170     } else {
171         e10k_rdt_1_wr(q->d, q->id, tail);
172     }
173     return SYS_ERR_OK;
174 }
175
176
177 static struct region_entry* get_region(struct e10k_queue* q, regionid_t rid)
178 {
179     struct region_entry* entry = q->regions;
180     while (entry != NULL) {
181         if (entry->rid == rid) {
182             return entry;
183         }
184         entry = entry->next;
185     }
186     return NULL;
187 }
188
189 /*
190 static void print_packet(lvaddr_t addr, genoffset_t length)
191 {
192     uint8_t* buf = (uint8_t*) addr;
193     for (int i = 0; i < length; i++) {
194         
195         if ((i % 8) == 0) {
196             printf(" \n");
197         }
198         printf("%2X ", buf[i]);
199     }
200     printf(" \n");
201 }
202 */
203
204 static errval_t enqueue_tx_buf(struct e10k_queue* q, regionid_t rid,
205                                genoffset_t offset,
206                                genoffset_t length,
207                                genoffset_t valid_data,
208                                genoffset_t valid_length,
209                                uint64_t flags)
210 {
211     DEBUG_QUEUE("Enqueueing TX buf \n");
212
213     if (e10k_queue_free_txslots(q) == 0) {
214         DEBUG_QUEUE("e10k_%d: Not enough space in TX ring, not adding buffer\n",
215                 q->id);
216         // TODO better error
217         return NIC_ERR_ENQUEUE;
218     }
219
220     bool last = flags & NETIF_TXFLAG_LAST;
221     bool first = flags & NETIF_TXFLAG_FIRST;
222     // Prepare checksum offload
223
224     if (buf_use_ipxsm(flags)) {
225         e10k_q_l4_type_t l4t = 0;
226         uint8_t l4len = 0;
227
228         if (buf_use_tcpxsm(flags)) {
229             l4t = e10k_q_tcp;
230             l4len = buf_tcphdrlen(flags);
231         } else if (buf_use_udpxsm(flags)) {
232             l4t = e10k_q_udp;
233             l4len = UDPHDR_LEN;
234         }
235
236         e10k_queue_add_txcontext(q, 0, ETHHDR_LEN, IPHDR_LEN, l4len, l4t);
237
238             if (q->use_vtd) {
239             // get virtual address of buffer
240             struct region_entry* entry = get_region(q, rid);
241             assert(entry != NULL);
242
243             lpaddr_t addr = 0;
244             addr = (lpaddr_t) entry->virt + offset + valid_data;
245             e10k_queue_add_txbuf_ctx(q, addr, rid, offset, length,
246                                      valid_data, valid_length, flags,
247                                      first, last, valid_length, 0, true, l4len !=0);
248             } else {
249
250             // get virtual address of buffer
251             struct region_entry* entry = get_region(q, rid);
252             assert(entry != NULL);
253
254             lpaddr_t addr = 0;
255             addr = (lpaddr_t) entry->phys + offset + valid_data;
256             e10k_queue_add_txbuf_ctx(q, addr, rid, offset, length,
257                                      valid_data, valid_length, flags,
258                                      first, last, valid_length, 0, true, l4len != 0);
259         }
260     } else {
261         if (q->use_vtd) {
262             // get virtual address of buffer
263             struct region_entry* entry = get_region(q, rid);
264             assert(entry != NULL);
265
266             lpaddr_t addr = 0;
267             addr = (lpaddr_t) entry->virt + offset + valid_data;
268             e10k_queue_add_txbuf(q, addr, rid, offset, length, valid_data,
269                                  valid_length, flags,
270                                  first, last, valid_length);
271         } else {
272             struct region_entry* entry = get_region(q, rid);
273             assert(entry != NULL);
274
275             lpaddr_t addr;
276             addr = (lpaddr_t) entry->phys + offset + valid_data;
277             e10k_queue_add_txbuf(q, addr, rid, offset, length, valid_data,
278                                  valid_length, flags, first, last, valid_length);
279         }
280     }
281     e10k_queue_bump_txtail(q);
282     return SYS_ERR_OK;
283 }
284
285
286 static errval_t enqueue_rx_buf(struct e10k_queue* q, regionid_t rid,
287                                genoffset_t offset,
288                                genoffset_t length,
289                                genoffset_t valid_data,
290                                genoffset_t valid_length,
291                                uint64_t flags)
292 {
293     DEBUG_QUEUE("Enqueueing RX buf \n");
294     // check if there is space
295     if (e10k_queue_free_rxslots(q) == 0) {
296         DEBUG_QUEUE("e10k_%d: Not enough space in RX ring, not adding buffer\n",
297                 q->id);
298         // TODO better error
299         return NIC_ERR_ENQUEUE;
300     }
301
302     if (q->use_vtd) {
303         // get virtual address of buffer
304         struct region_entry* entry = get_region(q, rid);
305         assert(entry != NULL);
306
307         lpaddr_t addr = 0;
308         addr = (lpaddr_t) entry->virt + offset;
309         e10k_queue_add_rxbuf(q, addr, rid, offset, length, valid_data,
310                              valid_length, flags);
311     } else {
312         // get virtual address of buffer
313         struct region_entry* entry = get_region(q, rid);
314         assert(entry != NULL);
315
316         lpaddr_t addr = 0;
317         addr = (lpaddr_t) entry->phys + offset;
318         e10k_queue_add_rxbuf(q, addr, rid, offset, length, valid_data,
319                              valid_length, flags);
320     }
321
322     DEBUG_QUEUE("before bump tail\n");
323     e10k_queue_bump_rxtail(q);
324     DEBUG_QUEUE("Enqueueing RX buf: terminated\n");
325     return SYS_ERR_OK;
326 }
327
328 /******************************************************************************/
329 /* Queue functions */
330
331 static errval_t e10k_enqueue(struct devq* q, regionid_t rid, genoffset_t offset,
332                              genoffset_t length, genoffset_t valid_data,
333                              genoffset_t valid_length, uint64_t flags)
334 {
335     errval_t err;
336
337
338     struct e10k_queue* queue = (struct e10k_queue*) q;
339     if (flags & NETIF_RXFLAG) {
340         /* can not enqueue receive buffer larger than 2048 bytes */
341         assert(length <= 2048);
342
343         err = enqueue_rx_buf(queue, rid, offset, length, valid_data,
344                              valid_length, flags);
345         if (err_is_fail(err)) {
346             return err;
347         }
348     } else if (flags & NETIF_TXFLAG) {
349
350         assert(length <= 2048);
351         
352         DEBUG_QUEUE("Enqueuing offset=%lu valid_data=%lu txhwb=%d tx_tail=%zu tx_head=%zu \n", 
353                offset, valid_data, *((uint32_t*)queue->tx_hwb), queue->tx_tail,
354                queue->tx_head);
355
356         err = enqueue_tx_buf(queue, rid, offset, length, valid_data,
357                              valid_length, flags);
358         if (err_is_fail(err)) {
359             return err;
360         }
361     }
362
363     return SYS_ERR_OK;
364 }
365
366
367 static errval_t e10k_dequeue(struct devq* q, regionid_t* rid,
368                              genoffset_t* offset, genoffset_t* length,
369                              genoffset_t* valid_data,
370                              genoffset_t* valid_length, uint64_t* flags)
371 {
372     struct e10k_queue* que = (struct e10k_queue*) q;
373     int last;
374     errval_t err = SYS_ERR_OK;
375
376     if (!e10k_queue_get_txbuf(que, rid, offset, length, valid_data,
377                               valid_length, flags)) {
378         err = DEVQ_ERR_QUEUE_EMPTY;
379     }  else {
380         DEBUG_QUEUE("Sent offset=%lu valid_data=%lu \n", *offset, *valid_data);
381         return SYS_ERR_OK;
382     }
383
384     if (!e10k_queue_get_rxbuf(que, rid, offset, length, valid_data,
385                              valid_length, flags, &last)) {
386         err = DEVQ_ERR_QUEUE_EMPTY;
387     } else {
388         DEBUG_QUEUE("Received offset=%lu valid_data=%lu \n", *offset, *valid_data);
389         return SYS_ERR_OK;
390     }
391      
392
393     return err;
394 }
395
396 static errval_t e10k_register(struct devq* q, struct capref cap, regionid_t rid)
397 {
398     errval_t err;
399     struct e10k_queue* queue = (struct e10k_queue*) q;
400
401     struct frame_identity id;
402     err = invoke_frame_identify(cap, &id);
403     if (err_is_fail(err)) {
404         return err;
405     }
406
407     struct capref cr;
408     err = slot_alloc(&cr);
409     if (err_is_fail(err)) {
410         return err;
411     }
412
413     err = cap_copy(cr, cap);
414     if (err_is_fail(err)) {
415         return err;
416     }
417
418     void* va;
419     err = vspace_map_one_frame_attr(&va, id.bytes, cr,
420                                     VREGION_FLAGS_READ_WRITE,
421                                     NULL, NULL);
422     if (err_is_fail(err)) {
423         return err;
424     }
425
426     // keep track of regions since we need the virtual address ...
427     struct region_entry* entry = malloc(sizeof(struct region_entry));
428     entry->rid = rid;
429     entry->cap = cap;
430     entry->phys = id.base;
431     entry->virt = (lvaddr_t)va;
432     entry->size = id.bytes;
433     entry->next = NULL;
434
435     // linked list of regions
436     struct region_entry* cur = queue->regions;
437     if (cur == NULL) {
438         queue->regions = entry;
439         return SYS_ERR_OK;
440     }
441
442     while (cur->next != NULL) {
443         cur = cur->next;
444     }
445     
446     cur->next = entry;
447
448     return SYS_ERR_OK;
449 }
450
451 static errval_t e10k_deregister(struct devq* q, regionid_t rid)
452 {
453     return SYS_ERR_OK;
454 }
455
456 static errval_t e10k_control(struct devq* q, uint64_t cmd, uint64_t value, uint64_t *result)
457 {
458     struct e10k_queue* queue = (struct e10k_queue*) q;
459     *result = queue->mac;
460     DEBUG_QUEUE("Control cmd=%lu value=%lu \n", cmd, value);
461     return SYS_ERR_OK;
462 }
463
464
465 static errval_t e10k_notify(struct devq* q)
466 {
467     return SYS_ERR_OK;
468 }
469
470 /******************************************************************
471  * Management functions
472  *
473  */
474
475 static void bind_cb(void *st, errval_t err, struct e10k_vf_binding *b)
476 {
477     struct e10k_queue* q = (struct e10k_queue*) st;
478     assert(err_is_ok(err));
479
480     DEBUG_QUEUE("Sucessfully connected to management interface\n");
481
482     b->st = q;
483     q->binding = b;
484     e10k_vf_rpc_client_init(q->binding);
485     q->bound = true;
486 }
487
488 /** Connect to the management interface */
489 static void connect_to_mngif(struct e10k_queue* q)
490 {
491     errval_t r;
492     iref_t iref;
493
494     q->bound = false;
495     char name[strlen("e10k_vf") + 2];
496
497     // Build label for interal management service
498     sprintf(name, "%s%u", "e10k_vf", q->pci_function);
499
500     // Connect to service
501     DEBUG_QUEUE("Looking up management interface (%s)\n", name);
502     r = nameservice_blocking_lookup(name, &iref);
503     assert(err_is_ok(r));
504
505     DEBUG_QUEUE("Binding to management interface\n");
506     r = e10k_vf_bind(iref, bind_cb, q, get_default_waitset(),
507                      IDC_BIND_FLAGS_DEFAULT);
508     assert(err_is_ok(r));
509
510     while (!q->bound) {
511         event_dispatch(get_default_waitset());
512     }
513 }
514
515 /*********************************************************
516  * Queue creation and destruction
517  */
518
519
520 errval_t e10k_queue_destroy(struct e10k_queue* queue)
521 {
522     //TODO: do the cleanup
523     return SYS_ERR_OK;
524 }
525
526 static errval_t map_device_memory(struct e10k_queue* q,
527                                   struct capref regs)
528 {
529
530     struct frame_identity id = {.base = 0, .bytes = 0};
531     errval_t err;
532
533     err = invoke_frame_identify(regs, &id);
534     if (err_is_fail(err)) {
535         return err;
536     }
537
538     void* va;
539     err = vspace_map_one_frame_attr(&va, id.bytes, regs,
540                                     VREGION_FLAGS_READ_WRITE_NOCACHE,
541                                     NULL, NULL);
542     if (err_is_fail(err)) {
543         return err;
544     }
545       
546
547     DEBUG_QUEUE("mapped %zu bytes at address %p\n", id.bytes, va);
548     q->d = malloc(sizeof(e10k_t));
549     assert(q->d != NULL);
550     e10k_initialize(q->d, va);
551     d = q->d;
552     return SYS_ERR_OK;
553 }
554 // TODO mostly cleanup when fail
555 errval_t e10k_queue_create(struct e10k_queue** queue, e10k_event_cb_t cb,
556                            bool use_vf, bool interrupts)
557 {
558
559     errval_t err;
560     struct e10k_queue* q;
561     // start VF driver
562     
563     q = malloc(sizeof(struct e10k_queue));
564     q->pci_function = 0; // TODO allow also function 1
565
566     // txhwb
567     q->use_txhwb = true;
568
569     if (use_vf) {
570         USER_PANIC("NOT YET WORKING \n");
571         // Start VF
572         if (!e10k_vf_started()) {
573             err = e10k_init_vf_driver(q->pci_function, interrupts);
574             if (err_is_fail(err)) {
575                 return err;
576             }
577         }
578
579         // If i can not create any more queues -> start new VF
580         if (!e10k_vf_can_create_queue()) {
581             err = e10k_init_vf_driver(q->pci_function, interrupts);
582             if (err_is_fail(err)) {
583                 return err;
584             }
585         }
586
587         err = skb_client_connect();
588         assert(err_is_ok(err));
589         err = skb_execute_query("vtd_enabled(0,_).");
590         if (err_is_fail(err)) {
591             DEBUG_QUEUE("Assume disabled VT-d \n");
592             //q->use_vtd = false;
593         } else {
594             DEBUG_QUEUE("Assume enabled VT-d \n");
595             //q->use_vtd = true;
596         }
597
598     } else {
599         q->use_vtd = false;
600         // need to set up communicaton to PF
601         connect_to_mngif(q);
602     }
603
604     // allocate memory for RX/TX rings
605     struct capref tx_frame;
606     size_t tx_size = e10k_q_tdesc_adv_wb_size*NUM_TX_DESC;
607     void* tx_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, tx_size, &tx_frame);
608     if (tx_virt == NULL) {
609         return DEVQ_ERR_INIT_QUEUE;
610     }
611
612     struct capref rx_frame;
613     size_t rx_size = e10k_q_rdesc_adv_wb_size*NUM_RX_DESC;
614     void* rx_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, rx_size, &rx_frame);
615     if (rx_virt == NULL) {
616         return DEVQ_ERR_INIT_QUEUE;
617     }
618
619     struct e10k_queue_ops ops = {
620         .update_txtail = update_txtail,
621         .update_rxtail = update_rxtail,
622     };
623
624     struct capref txhwb_frame;
625     void* txhwb_virt = NULL;
626
627     if (q->use_txhwb) {
628         txhwb_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, BASE_PAGE_SIZE,
629         &txhwb_frame);
630         if (txhwb_virt == NULL) {   
631             return DEVQ_ERR_INIT_QUEUE;
632         }
633         memset(txhwb_virt, 0, sizeof(uint32_t));
634     }
635
636     e10k_queue_init(q, tx_virt, NUM_TX_DESC, txhwb_virt,
637                     rx_virt, NUM_RX_DESC, &ops);
638
639     DEBUG_QUEUE("Local queue init done\n");
640
641     q->use_vf = use_vf;
642     q->rx_frame = rx_frame;
643     q->tx_frame = tx_frame;
644     q->txhwb_frame = txhwb_frame;
645     q->use_irq = interrupts;
646
647     // XXX:disable by default for now
648     q->use_rsc = false;
649
650     if (q->use_vf) {
651         err = e10k_vf_init_queue_hw(q);
652         if (err_is_fail(err)) {
653             return err;
654         }
655     } else {
656
657         int qid;
658         errval_t err2;
659         struct capref regs;
660
661         if (q->use_irq) {
662             /*
663             err = pci_setup_inthandler(interrupt_handler, NULL, &vector);
664             assert(err_is_ok(err));
665             core = disp_get_core_id();
666             */
667             // TODO setup MSI-X interrupts
668         }
669
670         // Inform card driver about new queue and get the registers/queue id
671         err = slot_alloc(&regs);
672         if (err_is_fail(err)) {
673             return err;
674         }
675
676         err = q->binding->rpc_tx_vtbl.create_queue(q->binding, tx_frame, txhwb_frame,
677                                             rx_frame, 2048, q->msix_intvec,
678                                             q->msix_intdest, false, false, 
679                                             &q->mac, &qid,
680                                             &regs, &err2);
681         if (err_is_fail(err) || err_is_fail(err2)) {
682             DEBUG_QUEUE("e10k rpc error\n");
683             return err_is_fail(err)? err: err2;
684         }
685
686         assert(qid >= 0);
687         q->id = (uint16_t)qid;
688
689         err = map_device_memory(q, regs);
690         if (err_is_fail(err)) {
691             DEBUG_QUEUE("e10k map device error\n");
692             return err;
693         }
694             
695         update_txtail(q, 0);
696         update_rxtail(q, 0);
697         
698     }
699
700     err = devq_init(&q->q, false);
701     if (err_is_fail(err)) {
702         DEBUG_QUEUE("e10k devq_init error\n");
703         return err;
704     }
705     
706     q->q.f.enq = e10k_enqueue;
707     q->q.f.deq = e10k_dequeue;
708     q->q.f.reg = e10k_register;
709     q->q.f.dereg = e10k_deregister;
710     q->q.f.ctrl = e10k_control;
711     q->q.f.notify = e10k_notify;
712
713
714     *queue = q;
715
716     DEBUG_QUEUE("e10k queue init done\n");
717     return SYS_ERR_OK;
718 }
719
720 uint64_t e10k_queue_get_id(struct e10k_queue* q)
721 {
722     return q->id;
723 }