c812861f2c4eb384527d94352bd7e190f49ed42b
[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 /* Misc functions */
37
38
39 static inline bool buf_use_tcpxsm(uint64_t flags)
40 {
41     return (flags & NETIF_TXFLAG_TCPCHECKSUM);
42 }
43
44 static inline bool buf_use_udpxsm(uint64_t flags)
45 {
46     return (flags & NETIF_TXFLAG_UDPCHECKSUM);
47 }
48
49 static inline bool buf_use_ipxsm(uint64_t flags)
50 {
51     return (flags & NETIF_TXFLAG_IPCHECKSUM) ||
52         buf_use_tcpxsm(flags) || buf_use_udpxsm(flags);
53 }
54
55 static inline uint8_t buf_tcphdrlen(uint64_t flags)
56 {
57     return ((flags & NETIF_TXFLAG_TCPHDRLEN_MASK) >>
58         NETIF_TXFLAG_TCPHDRLEN_SHIFT) * 4;
59 }
60
61 static errval_t update_txtail(struct e10k_queue* q, size_t tail)
62 {
63     assert(q->d != NULL);
64
65     if (q->use_vf) {
66         e10k_vf_vftdt_wr(q->d, q->id, tail);
67     } else {
68         e10k_tdt_wr(q->d, q->id, tail);
69     }
70     return SYS_ERR_OK;
71 }
72
73 static errval_t update_rxtail(struct e10k_queue* q, size_t tail)
74 {
75     assert(q->d != NULL);
76
77     if (q->use_vf) {
78         e10k_vf_vfrdt_wr(q->d, q->id, tail);
79     } else {
80         e10k_rdt_1_wr(q->d, q->id, tail);
81     }
82     return SYS_ERR_OK;
83 }
84
85
86 static struct region_entry* get_region(struct e10k_queue* q, regionid_t rid)
87 {
88     struct region_entry* entry = q->regions;
89     while (entry != NULL) {
90         if (entry->rid == rid) {
91             return entry;
92         }
93         entry = entry->next;
94     }
95     return NULL;
96 }
97
98
99 static errval_t enqueue_tx_buf(struct e10k_queue* q, regionid_t rid,
100                                genoffset_t offset,
101                                genoffset_t length,
102                                genoffset_t valid_data,
103                                genoffset_t valid_length,
104                                uint64_t flags)
105 {
106     DEBUG_QUEUE("Enqueueing TX buf \n");
107
108     if (e10k_queue_free_txslots(q) == 0) {
109         DEBUG_QUEUE("e10k_%d: Not enough space in TX ring, not adding buffer\n",
110                 q->id);
111         // TODO better error
112         return NIC_ERR_ENQUEUE;
113     }
114
115     bool last = flags & NETIF_TXFLAG_LAST;
116     bool first = flags & NETIF_TXFLAG_FIRST;
117     // Prepare checksum offload
118
119     if (buf_use_ipxsm(flags)) {
120         e10k_q_l4_type_t l4t = 0;
121         uint8_t l4len = 0;
122
123         if (buf_use_tcpxsm(flags)) {
124             l4t = e10k_q_tcp;
125             l4len = buf_tcphdrlen(flags);
126         } else if (buf_use_udpxsm(flags)) {
127             l4t = e10k_q_udp;
128             l4len = UDPHDR_LEN;
129         }
130         e10k_queue_add_txcontext(q, 0, ETHHDR_LEN, IPHDR_LEN, l4len, l4t);
131
132             if (q->use_vtd) {
133             // get virtual address of buffer
134             struct region_entry* entry = get_region(q, rid);
135             assert(entry != NULL);
136
137             lpaddr_t addr = 0;
138             addr = (lpaddr_t) entry->virt + offset + valid_data;
139             e10k_queue_add_txbuf_ctx(q, addr, rid, offset, length,
140                                      valid_data, valid_length, flags,
141                                      first, last, length, 0, true, l4len !=0);
142             } else {
143
144             // get virtual address of buffer
145             struct region_entry* entry = get_region(q, rid);
146             assert(entry != NULL);
147
148             lpaddr_t addr = 0;
149             addr = (lpaddr_t) entry->phys + offset + valid_data;
150             e10k_queue_add_txbuf_ctx(q, addr, rid, offset, length,
151                                      valid_data, valid_length, flags,
152                                      first, last, length, 0, true, l4len != 0);
153         }
154     } else {
155         if (q->use_vtd) {
156             // get virtual address of buffer
157             struct region_entry* entry = get_region(q, rid);
158             assert(entry != NULL);
159
160             lpaddr_t addr = 0;
161             addr = (lpaddr_t) entry->virt + offset + valid_data;
162             e10k_queue_add_txbuf(q, addr, rid, offset, length, valid_data,
163                                  valid_length, flags,
164                                  first, last, length);
165         } else {
166             struct region_entry* entry = get_region(q, rid);
167             assert(entry != NULL);
168
169             lpaddr_t addr = 0;
170             addr = (lpaddr_t) entry->phys + offset + valid_data;
171             e10k_queue_add_txbuf(q, addr, rid, offset, length, valid_data,
172                                  valid_length, flags, first, last, length);
173         }
174     }
175     e10k_queue_bump_txtail(q);
176     return SYS_ERR_OK;
177 }
178
179
180 static errval_t enqueue_rx_buf(struct e10k_queue* q, regionid_t rid,
181                                genoffset_t offset,
182                                genoffset_t length,
183                                genoffset_t valid_data,
184                                genoffset_t valid_length,
185                                uint64_t flags)
186 {
187     DEBUG_QUEUE("Enqueueing RX buf \n");
188     // check if there is space
189     if (e10k_queue_free_rxslots(q) == 0) {
190         DEBUG_QUEUE("e10k_%d: Not enough space in RX ring, not adding buffer\n",
191                 q->id);
192         // TODO better error
193         return NIC_ERR_ENQUEUE;
194     }
195
196     if (q->use_vtd) {
197         // get virtual address of buffer
198         struct region_entry* entry = get_region(q, rid);
199         assert(entry != NULL);
200
201         lpaddr_t addr = 0;
202         addr = (lpaddr_t) entry->virt + offset;
203         e10k_queue_add_rxbuf(q, addr, rid, offset, length, valid_data,
204                              valid_length, flags);
205     } else {
206         // get virtual address of buffer
207         struct region_entry* entry = get_region(q, rid);
208         assert(entry != NULL);
209
210         lpaddr_t addr = 0;
211         addr = (lpaddr_t) entry->phys + offset;
212         e10k_queue_add_rxbuf(q, addr, rid, offset, length, valid_data,
213                              valid_length, flags);
214     }
215
216     DEBUG_QUEUE("before bump tail\n");
217     e10k_queue_bump_rxtail(q);
218     DEBUG_QUEUE("Enqueueing RX buf: terminated\n");
219     return SYS_ERR_OK;
220 }
221
222 /******************************************************************************/
223 /* Queue functions */
224
225 static errval_t e10k_enqueue(struct devq* q, regionid_t rid, genoffset_t offset,
226                              genoffset_t length, genoffset_t valid_data,
227                              genoffset_t valid_length, uint64_t flags)
228 {
229     errval_t err;
230
231
232     struct e10k_queue* queue = (struct e10k_queue*) q;
233     if (flags & NETIF_RXFLAG) {
234         /* can not enqueue receive buffer larger than 2048 bytes */
235         assert(length <= 2048);
236
237         err = enqueue_rx_buf(queue, rid, offset, length, valid_data,
238                              valid_length, flags);
239         if (err_is_fail(err)) {
240             return err;
241         }
242     } else if (flags & NETIF_TXFLAG) {
243
244         assert(length <= 2048);
245         
246         DEBUG_QUEUE("Enqueuing offset=%lu valid_data=%lu \n", offset, valid_data);
247         err = enqueue_tx_buf(queue, rid, offset, length, valid_data,
248                              valid_length, flags);
249         if (err_is_fail(err)) {
250             return err;
251         }
252     }
253
254     return SYS_ERR_OK;
255 }
256
257
258 static errval_t e10k_dequeue(struct devq* q, regionid_t* rid,
259                              genoffset_t* offset, genoffset_t* length,
260                              genoffset_t* valid_data,
261                              genoffset_t* valid_length, uint64_t* flags)
262 {
263     struct e10k_queue* que = (struct e10k_queue*) q;
264     int last;
265     errval_t err = SYS_ERR_OK;
266
267     if (!e10k_queue_get_rxbuf(que, rid, offset, length, valid_data,
268                              valid_length, flags, &last)) {
269         err = DEVQ_ERR_QUEUE_EMPTY;
270     } else {
271         DEBUG_QUEUE("Received offset=%lu valid_data=%lu \n", *offset, *valid_data);
272         return SYS_ERR_OK;
273     }
274      
275     if (!e10k_queue_get_txbuf(que, rid, offset, length, valid_data,
276                               valid_length, flags)) {
277         err = DEVQ_ERR_QUEUE_EMPTY;
278     }  else {
279         DEBUG_QUEUE("Sent offset=%lu valid_data=%lu \n", *offset, *valid_data);
280         return SYS_ERR_OK;
281     }
282
283     return err;
284 }
285
286 static errval_t e10k_register(struct devq* q, struct capref cap, regionid_t rid)
287 {
288     errval_t err;
289     struct e10k_queue* queue = (struct e10k_queue*) q;
290
291     struct frame_identity id;
292     err = invoke_frame_identify(cap, &id);
293     if (err_is_fail(err)) {
294         return err;
295     }
296
297     struct capref cr;
298     err = slot_alloc(&cr);
299     if (err_is_fail(err)) {
300         return err;
301     }
302
303     err = cap_copy(cr, cap);
304     if (err_is_fail(err)) {
305         return err;
306     }
307
308     void* va;
309     err = vspace_map_one_frame_attr(&va, id.bytes, cr,
310                                     VREGION_FLAGS_READ_WRITE_NOCACHE,
311                                     NULL, NULL);
312     if (err_is_fail(err)) {
313         return err;
314     }
315
316     // keep track of regions since we need the virtual address ...
317     struct region_entry* entry = malloc(sizeof(struct region_entry));
318     entry->rid = rid;
319     entry->cap = cap;
320     entry->phys = id.base;
321     entry->virt = (lvaddr_t)va;
322     entry->size = id.bytes;
323     entry->next = NULL;
324
325     // linked list of regions
326     struct region_entry* cur = queue->regions;
327     if (cur == NULL) {
328         queue->regions = entry;
329         return SYS_ERR_OK;
330     }
331
332     while (cur->next != NULL) {
333         cur = cur->next;
334     }
335     
336     cur->next = entry;
337
338     return SYS_ERR_OK;
339 }
340
341 static errval_t e10k_deregister(struct devq* q, regionid_t rid)
342 {
343     return SYS_ERR_OK;
344 }
345
346 static errval_t e10k_control(struct devq* q, uint64_t cmd, uint64_t value, uint64_t *result)
347 {
348     struct e10k_queue* queue = (struct e10k_queue*) q;
349     *result = queue->mac;
350     DEBUG_QUEUE("Control cmd=%lu value=%lu \n", cmd, value);
351     return SYS_ERR_OK;
352 }
353
354
355 static errval_t e10k_notify(struct devq* q)
356 {
357     return SYS_ERR_OK;
358 }
359
360 /******************************************************************
361  * Management functions
362  *
363  */
364
365 static void bind_cb(void *st, errval_t err, struct e10k_vf_binding *b)
366 {
367     struct e10k_queue* q = (struct e10k_queue*) st;
368     assert(err_is_ok(err));
369
370     DEBUG_QUEUE("Sucessfully connected to management interface\n");
371
372     b->st = q;
373     q->binding = b;
374     e10k_vf_rpc_client_init(q->binding);
375     q->bound = true;
376 }
377
378 /** Connect to the management interface */
379 static void connect_to_mngif(struct e10k_queue* q)
380 {
381     errval_t r;
382     iref_t iref;
383
384     q->bound = false;
385     char name[strlen("e10k_vf") + 2];
386
387     // Build label for interal management service
388     sprintf(name, "%s%u", "e10k_vf", q->pci_function);
389
390     // Connect to service
391     DEBUG_QUEUE("Looking up management interface (%s)\n", name);
392     r = nameservice_blocking_lookup(name, &iref);
393     assert(err_is_ok(r));
394
395     DEBUG_QUEUE("Binding to management interface\n");
396     r = e10k_vf_bind(iref, bind_cb, q, get_default_waitset(),
397                      IDC_BIND_FLAGS_DEFAULT);
398     assert(err_is_ok(r));
399
400     while (!q->bound) {
401         event_dispatch(get_default_waitset());
402     }
403 }
404
405 /*********************************************************
406  * Queue creation and destruction
407  */
408
409
410 errval_t e10k_queue_destroy(struct e10k_queue* queue)
411 {
412     //TODO: do the cleanup
413     return SYS_ERR_OK;
414 }
415
416 static errval_t map_device_memory(struct e10k_queue* q,
417                                   struct capref regs)
418 {
419
420     struct frame_identity id = {.base = 0, .bytes = 0};
421     errval_t err;
422
423     err = invoke_frame_identify(regs, &id);
424     if (err_is_fail(err)) {
425         return err;
426     }
427
428     void* va;
429     err = vspace_map_one_frame_attr(&va, id.bytes, regs,
430                                     VREGION_FLAGS_READ_WRITE_NOCACHE,
431                                     NULL, NULL);
432     if (err_is_fail(err)) {
433         return err;
434     }
435       
436
437     DEBUG_QUEUE("mapped %zu bytes at address %p\n", id.bytes, va);
438     q->d = malloc(sizeof(e10k_t));
439     assert(q->d != NULL);
440     e10k_initialize(q->d, va);
441     return SYS_ERR_OK;
442 }
443 // TODO mostly cleanup when fail
444 errval_t e10k_queue_create(struct e10k_queue** queue, e10k_event_cb_t cb,
445                            bool use_vf, bool interrupts)
446 {
447
448     errval_t err;
449     struct e10k_queue* q;
450     // start VF driver
451     
452     q = malloc(sizeof(struct e10k_queue));
453     q->pci_function = 0; // TODO allow also function 1
454
455     if (use_vf) {
456         USER_PANIC("NOT YET WORKING \n");
457         // Start VF
458         if (!e10k_vf_started()) {
459             err = e10k_init_vf_driver(q->pci_function, interrupts);
460             if (err_is_fail(err)) {
461                 return err;
462             }
463         }
464
465         // If i can not create any more queues -> start new VF
466         if (!e10k_vf_can_create_queue()) {
467             err = e10k_init_vf_driver(q->pci_function, interrupts);
468             if (err_is_fail(err)) {
469                 return err;
470             }
471         }
472
473         // TODO: VF queues only work with VT-d enabled?
474         err = skb_client_connect();
475         assert(err_is_ok(err));
476         err = skb_execute_query("vtd_enabled(0,_).");
477         if (err_is_fail(err)) {
478             DEBUG_QUEUE("Assume disabled VT-d \n");
479             //q->use_vtd = false;
480         } else {
481             DEBUG_QUEUE("Assume enabled VT-d \n");
482             //q->use_vtd = true;
483         }
484
485     } else {
486         q->use_vtd = false;
487         // need to set up communicaton to PF
488         connect_to_mngif(q);
489     }
490
491     // allocate memory for RX/TX rings
492     struct capref tx_frame;
493     size_t tx_size = e10k_q_tdesc_adv_ctx_size*NUM_TX_DESC;
494     void* tx_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, tx_size, &tx_frame);
495     if (tx_virt == NULL) {
496         return DEVQ_ERR_INIT_QUEUE;
497     }
498
499
500     struct capref rx_frame;
501     size_t rx_size = e10k_q_tdesc_adv_ctx_size*NUM_RX_DESC;
502     void* rx_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, rx_size, &rx_frame);
503     if (rx_virt == NULL) {
504         return DEVQ_ERR_INIT_QUEUE;
505     }
506
507     struct e10k_queue_ops ops = {
508         .update_txtail = update_txtail,
509         .update_rxtail = update_rxtail,
510     };
511
512     struct capref txhwb_frame = NULL_CAP;
513     void* txhwb_virt = NULL;
514 #if 0
515     if (use_txhwb) {
516         txhwb_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, BASE_PAGE_SIZE,
517         &txhwb_frame);
518         if (txhwb_virt == NULL) {
519             return DEVQ_ERR_INIT_QUEUE;
520         }
521         memset(txhwb_virt, 0, sizeof(uint32_t));
522     }
523 #endif
524     e10k_queue_init(q, tx_virt, NUM_TX_DESC, txhwb_virt,
525                     rx_virt, NUM_RX_DESC, &ops);
526
527     DEBUG_QUEUE("Local queue init done\n");
528
529     q->use_vf = use_vf;
530     q->rx_frame = rx_frame;
531     q->tx_frame = tx_frame;
532     q->txhwb_frame = txhwb_frame;
533     q->use_irq = interrupts;
534
535     // XXX:disable by default for now
536     q->use_txhwb = false;
537     q->use_rsc = false;
538
539     if (q->use_vf) {
540         err = e10k_vf_init_queue_hw(q);
541         if (err_is_fail(err)) {
542             return err;
543         }
544     } else {
545
546         int qid;
547         errval_t err2;
548         struct capref regs;
549
550         if (q->use_irq) {
551             /*
552             err = pci_setup_inthandler(interrupt_handler, NULL, &vector);
553             assert(err_is_ok(err));
554             core = disp_get_core_id();
555             */
556             // TODO setup MSI-X interrupts
557         }
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         err = q->binding->rpc_tx_vtbl.create_queue(q->binding, tx_frame, txhwb_frame,
566                                             rx_frame, 2048, q->msix_intvec,
567                                             q->msix_intdest, false, false, 
568                                             &q->mac, &qid,
569                                             &regs, &err2);
570         if (err_is_fail(err) || err_is_fail(err2)) {
571             DEBUG_QUEUE("e10k rpc error\n");
572             return err_is_fail(err)? err: err2;
573         }
574
575         assert(qid >= 0);
576         q->id = (uint16_t)qid;
577
578         err = map_device_memory(q, regs);
579         if (err_is_fail(err)) {
580             DEBUG_QUEUE("e10k map device error\n");
581             return err;
582         }
583     }
584
585     err = devq_init(&q->q, false);
586     if (err_is_fail(err)) {
587         DEBUG_QUEUE("e10k devq_init error\n");
588         return err;
589     }
590     
591     q->q.f.enq = e10k_enqueue;
592     q->q.f.deq = e10k_dequeue;
593     q->q.f.reg = e10k_register;
594     q->q.f.dereg = e10k_deregister;
595     q->q.f.ctrl = e10k_control;
596     q->q.f.notify = e10k_notify;
597
598
599     *queue = q;
600
601     DEBUG_QUEUE("e10k queue init done\n");
602     return SYS_ERR_OK;
603 }
604
605 uint64_t e10k_queue_get_id(struct e10k_queue* q)
606 {
607     return q->id;
608 }