2 * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich.
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.
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>
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"
28 #define DEBUG_QUEUE(x...) printf("sfn5122f_q : " x)
30 #define DEBUG_QUEUE(x...) do {} while (0)
36 #define TX_ENTRIES 4096
37 #define RX_ENTRIES 4096
38 #define EV_ENTRIES 32768
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");
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
57 /* for each TX/RX entry one entry plus an additonal 2 for mcdi completion
58 and link state events */
60 struct sfn5122f_queue* queues[1024];
64 static errval_t update_rxtail(struct sfn5122f_queue* q, size_t tail)
66 assert(q->device != NULL);
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);
86 static errval_t update_txtail(struct sfn5122f_queue* q, size_t tail)
88 assert(q->device != NULL);
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);
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);
101 static void interrupt_cb(struct sfn5122f_devif_binding *b, uint16_t qid)
103 struct sfn5122f_queue* q = queues[qid];
106 debug_printf("STATE MISMATCH!\n %p %p\n", q, b->st);
113 static struct sfn5122f_devif_rx_vtbl rx_vtbl = {
114 .interrupt = interrupt_cb,
117 static void bind_cb(void *st, errval_t err, struct sfn5122f_devif_binding *b)
120 DEBUG_QUEUE("binding CB \n");
121 struct sfn5122f_queue* queue = (struct sfn5122f_queue*) st;
123 b->rx_vtbl = rx_vtbl;
127 sfn5122f_devif_rpc_client_init(queue->b);
132 static errval_t sfn5122f_register(struct devq* q, struct capref cap,
135 uint64_t buftbl_idx = 0;
137 struct frame_identity id;
139 struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
141 if (queue->userspace) {
142 err = queue->b->rpc_tx_vtbl.register_region(queue->b, queue->id, cap,
144 if (err_is_fail(err) || err_is_fail(err2)) {
145 err = err_is_fail(err) ? err: err2;
150 err = invoke_frame_identify(cap, &id);
151 if (err_is_fail(err)) {
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));
159 entry->phys = id.base;
160 entry->size = id.bytes;
162 entry->buftbl_idx = buftbl_idx;
165 struct region_entry* cur = queue->regions;
168 queue->regions = entry;
172 while (cur->next != NULL) {
178 DEBUG_QUEUE("Region %d registered \n", rid);
182 static errval_t sfn5122f_deregister(struct devq* q, regionid_t rid)
186 struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
188 // find region and translate to buftlb entry
189 struct region_entry* cur = queue->regions;
192 return DEVQ_ERR_INVALID_REGION_ARGS;
195 while (cur->next != NULL && cur->rid != rid) {
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,
203 if (err_is_fail(err) || err_is_fail(err2)) {
204 err = err_is_fail(err) ? err: err2;
213 static errval_t sfn5122f_control(struct devq* q, uint64_t cmd, uint64_t value,
216 struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
217 *result = queue->mac;
218 DEBUG_QUEUE("Control cmd=%lu value=%lu \n", cmd, value);
223 static errval_t sfn5122f_notify(struct devq* q)
225 DEBUG_QUEUE("Notify \n");
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,
234 DEBUG_QUEUE("Enqueueing RX buf \n");
235 // check if there is space
237 if (sfn5122f_queue_free_rxslots(q) == 0) {
238 DEBUG_QUEUE("SFN5122F_%d: Not enough space in RX ring, not adding buffer\n",
240 return DEVQ_ERR_QUEUE_FULL;
245 struct region_entry* entry = q->regions;
247 // If regions already empty -> return error
249 return DEVQ_ERR_INVALID_REGION_ARGS;
252 while((entry->next != NULL) && (entry->rid != rid)) {
257 return DEVQ_ERR_INVALID_REGION_ARGS;
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;
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);
273 sfn5122f_queue_add_rxbuf_devif(q, entry->phys + offset, rid, offset, length,
274 valid_data, valid_length, flags);
278 update_rxtail(q, q->rx_tail);
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,
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",
292 return DEVQ_ERR_QUEUE_FULL;
296 struct region_entry* entry = q->regions;
299 return DEVQ_ERR_INVALID_REGION_ARGS;
302 while((entry->next != NULL) && (entry->rid != rid)) {
307 return DEVQ_ERR_INVALID_REGION_ARGS;
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;
317 DEBUG_QUEUE("TX_BUF tbl_idx=%lu offset=%d flags=%lx \n", buftbl_idx, b_off,
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);
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,
332 update_txtail(q, q->tx_tail);
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,
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);
349 err = enqueue_rx_buf(queue, rid, offset, length, valid_data, valid_length,
351 if (err_is_fail(err)) {
354 } else if (flags & NETIF_TXFLAG) {
355 assert(length <= BASE_PAGE_SIZE);
357 err = enqueue_tx_buf(queue, rid, offset, length, valid_data, valid_length,
359 if (err_is_fail(err)) {
363 printf("Unknown buffer flags \n");
364 return NIC_ERR_ENQUEUE;
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)
375 errval_t err = DEVQ_ERR_QUEUE_EMPTY;
377 struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
379 //sfn5122f_evq_rptr_reg_wr(queue->device, queue->id, queue->ev_head);
380 //__sync_synchronize();
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;
395 ev_code = sfn5122f_get_event_code(queue);
398 // TODO multiple packets
399 err = sfn5122f_queue_handle_rx_ev_devif(queue, rid, offset, length,
400 valid_data, valid_length,
403 DEBUG_QUEUE("RX_EV Q_ID: %d len %ld OK %s \n", queue->id, *valid_length,
406 sfn5122f_queue_bump_evhead(queue);
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,
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
420 /* the packet has been discarded and enqueued successfully,
421 * return emtpy queue */
422 err = DEVQ_ERR_QUEUE_EMPTY;
424 assert(*valid_length > 0);
429 err = sfn5122f_queue_handle_tx_ev_devif(queue, rid, offset, length,
430 valid_data, valid_length,
432 if (*flags & NETIF_RXFLAG) {
433 printf("HUH: reiceived rx buffer in tx event???\n");
436 if (err_is_ok(err)) {
437 DEBUG_QUEUE("TX EVENT OK %d \n", queue->id);
439 DEBUG_QUEUE("TX EVENT ERR %d \n", queue->id);
442 sfn5122f_queue_bump_evhead(queue);
445 DEBUG_QUEUE("DRIVER EVENT %d\n", queue->id);
446 sfn5122f_handle_drv_ev(queue, queue->id);
447 sfn5122f_queue_bump_evhead(queue);
449 case EV_CODE_DRV_GEN:
450 DEBUG_QUEUE("DRIVER GENERATED EVENT \n");
451 sfn5122f_queue_bump_evhead(queue);
454 DEBUG_QUEUE("USER EVENT \n");
455 sfn5122f_queue_bump_evhead(queue);
458 DEBUG_QUEUE("MCDI EVENT \n");
459 sfn5122f_queue_handle_mcdi_event(queue);
460 sfn5122f_queue_bump_evhead(queue);
463 DEBUG_QUEUE("GLOBAL EVENT \n");
464 sfn5122f_queue_bump_evhead(queue);
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);
478 static void interrupt_handler(void* arg)
480 struct sfn5122f_queue* queue = (struct sfn5122f_queue*) arg;
492 errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, sfn5122f_event_cb_t cb,
493 bool userlevel, bool interrupts, bool qzero)
495 DEBUG_QUEUE("create called \n");
498 //struct capref tx_frame, rx_frame, ev_frame;
500 //size_t tx_size, rx_size, ev_size;
502 void *tx_virt, *rx_virt, *ev_virt;
503 struct sfn5122f_queue* queue;
504 struct frame_identity id;
506 struct sfn5122f_queue_ops ops = {
507 .update_txtail = update_txtail,
508 .update_rxtail = update_rxtail
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;
519 rx_virt = tx_virt + (sizeof(uint64_t) *TX_ENTRIES);
520 ev_virt = rx_virt + (sizeof(uint64_t) *RX_ENTRIES);
522 DEBUG_QUEUE("queue init \n");
524 queue = sfn5122f_queue_init(tx_virt, TX_ENTRIES, rx_virt, RX_ENTRIES,
525 ev_virt, EV_ENTRIES, &ops, userlevel);
527 queue->frame = frame;
528 queue->bound = false;
530 queue->use_interrupts = interrupts;
534 const char *name = "sfn5122f_sfn5122fmng_devif";
536 // Connect to solarflare card driver
537 err = nameservice_blocking_lookup(name, &iref);
538 if (err_is_fail(err)) {
542 DEBUG_QUEUE("binding \n");
543 err = sfn5122f_devif_bind(iref, bind_cb, queue, get_default_waitset(),
545 if (err_is_fail(err)) {
550 while(!queue->bound) {
551 event_dispatch(get_default_waitset());
554 DEBUG_QUEUE("bound \n");
559 // Inform card driver about new queue and get the registers/queue id
560 err = slot_alloc(®s);
561 if (err_is_fail(err)) {
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,
569 0, 0, &queue->mac ,&queue->id,
571 if (err_is_fail(err) || err_is_fail(err2)) {
572 err = err_is_fail(err) ? err: err2;
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));
580 queue->core = disp_get_core_id();
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, ®s, &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");
592 DEBUG_QUEUE("rpc done \n");
594 err = invoke_frame_identify(regs, &id);
595 if (err_is_fail(err)) {
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)) {
606 DEBUG_QUEUE("mapped \n");
607 queue->device = malloc(sizeof(sfn5122f_t));
608 sfn5122f_initialize(queue->device, queue->device_va);
610 err = devq_init(&queue->q, false);
611 if (err_is_fail(err)) {
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;
624 queues[queue->id] = queue;
629 errval_t sfn5122f_queue_destroy(struct sfn5122f_queue* q)
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;
638 err = vspace_unmap(q->device_va);
639 if (err_is_fail(err)) {
646 err = devq_destroy(&(q->q));
647 if (err_is_fail(err)){
651 err = sfn5122f_queue_free(q);
652 if (err_is_fail(err)) {
660 uint64_t sfn5122f_queue_get_id(struct sfn5122f_queue* q)