DeviceQueue: small changes to solarflare backend
authorRoni Häcki <roni.haecki@inf.ethz.ch>
Mon, 16 Jan 2017 16:06:38 +0000 (17:06 +0100)
committerRoni Häcki <roni.haecki@inf.ethz.ch>
Mon, 16 Jan 2017 16:06:38 +0000 (17:06 +0100)
Signed-off-by: Roni Häcki <roni.haecki@inf.ethz.ch>

if/sfn5122f_devif.if
lib/devif/backends/net/solarflare/devif_backend_solarflare.c
lib/devif/backends/net/solarflare/hw_queue.h
usr/drivers/solarflare/sfn5122f_cdriver.c

index 39edb0c..7b0a1c5 100644 (file)
@@ -17,7 +17,7 @@ interface sfn5122f_devif "sfn5122f devif communication interface" {
     
     // create and destroy a queue. Only the device driver itself should
     // access configuration registers
-    rpc create_queue(in bool user, in cap rx, in cap tx, in cap ev, 
+    rpc create_queue(in cap frame, in bool user,
                      out uint16 qid, out cap regs, out errval err);
     rpc destroy_queue(in uint16 qid, out errval err);
 
index 0bf5840..feef042 100644 (file)
@@ -28,7 +28,7 @@
     #define DEBUG_QUEUE(x...) do {} while (0)
 #endif
 
-#define DELAY 5
+#define DELAY 1
 
 // TX Queue
 #define TX_ENTRIES 2048
@@ -223,7 +223,10 @@ static errval_t enqueue_rx_buf(struct sfn5122f_queue* q, regionid_t rid,
     uint64_t buftbl_idx = entry->buftbl_idx + (bid/BUF_SIZE);
     uint16_t offset = bid & 0x00000FFF;    
 
-    
+    // still in the same buffer table entry
+    assert(buftbl_idx == (entry->buftbl_idx + ((bid+len-1)/BUF_SIZE)));
+
+   
     DEBUG_QUEUE("RX_BUF tbl_idx=%lu offset=%d flags=%lu \n", 
                 buftbl_idx, offset, flags);
     if (q->userspace) {
@@ -265,6 +268,10 @@ static errval_t enqueue_tx_buf(struct sfn5122f_queue* q, regionid_t rid,
     uint64_t buftbl_idx = entry->buftbl_idx + (bid/BUF_SIZE);
     uint16_t offset = bid & 0x00000FFF;    
 
+
+    // still in the same buffer table entry
+    assert(buftbl_idx == (entry->buftbl_idx + ((bid+len-1)/BUF_SIZE)));
+
     DEBUG_QUEUE("TX_BUF tbl_idx=%lu offset=%d flags=%lu \n", buftbl_idx, offset,
                 flags);
     if (q->userspace) {
@@ -288,13 +295,19 @@ static errval_t sfn5122f_enqueue(struct devq* q, regionid_t rid, bufferid_t bid,
 {
     errval_t err;
 
+
     struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
     if (flags & DEVQ_BUF_FLAG_RX) {
+        /* can not enqueue receive buffer larger than 2048 bytes */
+        assert(len <= 2048);
+
         err = enqueue_rx_buf(queue, rid, bid, base, len, flags);
         if (err_is_fail(err)) {
             return err;
         }      
     } else if (flags & DEVQ_BUF_FLAG_TX) {
+        assert(len <= BASE_PAGE_SIZE);
+
         err = enqueue_tx_buf(queue, rid, bid, base, len, flags);
         if (err_is_fail(err)) {
             return err;
@@ -390,8 +403,10 @@ errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, sfn5122f_event_cb_t cb
     DEBUG_QUEUE("create called \n");
 
     errval_t err;
-    struct capref tx_frame, rx_frame, ev_frame;
-    size_t tx_size, rx_size, ev_size;
+    //struct capref tx_frame, rx_frame, ev_frame;
+    struct capref frame;
+    //size_t tx_size, rx_size, ev_size;
+    size_t total_size;
     void *tx_virt, *rx_virt, *ev_virt;
     struct sfn5122f_queue* queue;
     struct frame_identity id;
@@ -403,6 +418,17 @@ errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, sfn5122f_event_cb_t cb
    
     /* Allocate memory for descriptor rings  
        No difference for userspace networking*/
+    // TODO too large ...
+    total_size = sizeof(uint64_t)*(TX_ENTRIES + RX_ENTRIES + EV_ENTRIES);
+    tx_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, total_size, &frame);
+    if (tx_virt == NULL) {
+        return SFN_ERR_ALLOC_QUEUE;
+    }
+
+    rx_virt = tx_virt + (sizeof(uint64_t) *TX_ENTRIES);
+    ev_virt = rx_virt + (sizeof(uint64_t) *RX_ENTRIES);
+
+    /*
     tx_size = sfn5122f_q_tx_ker_desc_size * TX_ENTRIES;
     tx_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, tx_size, &tx_frame);
     if (tx_virt == NULL) {
@@ -420,13 +446,14 @@ errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, sfn5122f_event_cb_t cb
     if (ev_virt == NULL) {
         return SFN_ERR_ALLOC_QUEUE;
     }
-
+    */
 
     DEBUG_QUEUE("queue init \n");
     // Init queue
     queue = sfn5122f_queue_init(tx_virt, TX_ENTRIES, rx_virt, RX_ENTRIES,
                                 ev_virt, EV_ENTRIES, &ops, userlevel);
 
+    queue->frame = frame;
     queue->bound = false;
 
     iref_t iref;
@@ -454,14 +481,17 @@ errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, sfn5122f_event_cb_t cb
 
     errval_t err2;
     struct capref regs;
+
     // Inform card driver about new queue and get the registers/queue id
-    err = queue->rpc->vtbl.create_queue(queue->rpc, userlevel, rx_frame, tx_frame, ev_frame,
-                                        &queue->id, &regs, &err2);
+    err = queue->rpc->vtbl.create_queue(queue->rpc, frame, userlevel, &queue->id, 
+                                        &regs, &err2);
     if (err_is_fail(err) || err_is_fail(err2)) {
         err = err_is_fail(err) ? err: err2;
         return err;
     }
 
+    DEBUG_QUEUE("rpc done \n");
+    
     err = invoke_frame_identify(regs, &id);
     if (err_is_fail(err)) {
         return err;
@@ -472,7 +502,9 @@ errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, sfn5122f_event_cb_t cb
     if (err_is_fail(err)) {
         return err;
     }
-  
+      
+
+    DEBUG_QUEUE("mapped \n");
     queue->device = malloc(sizeof(sfn5122f_t));
     sfn5122f_initialize(queue->device, queue->device_va);
 
@@ -519,13 +551,13 @@ errval_t sfn5122f_queue_destroy(struct sfn5122f_queue* q)
     }
 
     free(q->event);
-
+    
     err = vspace_unmap(q->device_va);
     if (err_is_fail(err)) {
         return err;
     }
-    free(q->device);
 
+    free(q->device);
     free(q->rpc);
 
     err = devq_destroy(&(q->q));
index 94f5155..1b3f41c 100644 (file)
@@ -87,6 +87,7 @@ struct sfn5122f_queue {
 
     // Direct interface fields
     uint16_t id;
+    struct capref frame;
     sfn5122f_t *device;
     void* device_va;
     struct region_entry* regions;
@@ -153,21 +154,8 @@ static inline sfn5122f_queue_t* sfn5122f_queue_init(void* tx,
 static inline errval_t sfn5122f_queue_free(struct sfn5122f_queue* q)
 {
     errval_t err;
-    
-    err = vspace_unmap(q->ev_ring);  
-    if (err_is_fail(err)) {
-        return err;
-    }   
 
-    if (q->userspace) {
-        err = vspace_unmap(q->rx_ring.user);  
-    } else {
-        err = vspace_unmap(q->rx_ring.ker);  
-    }
-    if (err_is_fail(err)) {
-        return err;
-    } 
-  
+    // only one cap that is mapped (TX)
     if (q->userspace) {
         err = vspace_unmap(q->tx_ring.user);  
     } else {
@@ -176,7 +164,6 @@ static inline errval_t sfn5122f_queue_free(struct sfn5122f_queue* q)
     if (err_is_fail(err)) {
         return err;
     }   
-
     free(q->rx_bufs);
     free(q->tx_bufs);
     free(q);
index 0605d67..12484bd 100644 (file)
@@ -207,9 +207,9 @@ static void idc_write_queue_tails(struct sfn5122f_binding *b);
 static void device_init(void);
 static void start_all(void);
 static void probe_all(void);
-static uint32_t init_txq(uint16_t n, bool csum, bool userspace);
-static uint32_t init_rxq(uint16_t n, bool userspace);
-static uint32_t init_evq(uint16_t n);
+static uint32_t init_txq(uint16_t n, lpaddr_t phys, bool csum, bool userspace);
+static uint32_t init_rxq(uint16_t n, lpaddr_t phys, bool userspace);
+static uint32_t init_evq(uint16_t n, lpaddr_t phys);
 static void queue_hw_stop(uint16_t n);
 
 static void setup_interrupt(size_t *msix_index, uint8_t core, uint8_t vector);
@@ -928,13 +928,12 @@ static void queue_hw_stop(uint16_t n)
 
 
 
-static uint32_t init_evq(uint16_t n)
+static uint32_t init_evq(uint16_t n, lpaddr_t phys)
 {
 
-    errval_t r; 
-    struct frame_identity frameid = { .base = 0, .bytes = 0 };
-    uint64_t ev_phys, reg, buffer_offset;
-    size_t ev_size;
+    //errval_t r; 
+    //struct frame_identity frameid = { .base = 0, .bytes = 0 };
+    uint64_t reg, buffer_offset;
     reg = 0;
 
     reg = sfn5122f_timer_tbl_lo_timer_q_en_insert(reg, 1);
@@ -951,17 +950,18 @@ static uint32_t init_evq(uint16_t n)
     sfn5122f_timer_tbl_lo_wr(d, n, reg);
     sfn5122f_timer_tbl_hi_wr(d, n, sfn5122f_timer_tbl_hi_rd(d, n));
 
+    /*
     r = invoke_frame_identify(queues[n].ev_frame, &frameid);
     assert(err_is_ok(r));
     ev_phys = frameid.base;
-    ev_size = frameid.bytes;  
+    */
 
-    buffer_offset = alloc_buf_tbl_entries(ev_phys, NUM_ENT_EVQ, 0, 0, d);
+    buffer_offset = alloc_buf_tbl_entries(phys, NUM_ENT_EVQ, 0, 0, d);
     if (buffer_offset == -1) {
         return -1;
     }
 
-    DEBUG("EV_QUEUE_%d: buf_off %ld, phys 0x%lx\n",n , buffer_offset, ev_phys);
+    DEBUG("EV_QUEUE_%d: buf_off %ld, phys 0x%lx\n",n , buffer_offset, phys);
     //  setup EV queue
     reg = sfn5122f_evq_ptr_tbl_lo_rd(d, n);
     reg = sfn5122f_evq_ptr_tbl_lo_evq_en_insert(reg, 1);
@@ -987,25 +987,24 @@ static uint32_t init_evq(uint16_t n)
     return buffer_offset;
 }
 
-static uint32_t init_rxq(uint16_t n, bool userspace)
+static uint32_t init_rxq(uint16_t n, lpaddr_t phys, bool userspace)
 {
 
-    errval_t r;
-    size_t rx_size;
+    //errval_t r;
     size_t num_ent_rx;
-    struct frame_identity frameid = { .base = 0, .bytes = 0 };
-    uint64_t rx_phys, reg_lo, reg_hi,  buffer_offset;
+    //struct frame_identity frameid = { .base = 0, .bytes = 0 };
+    uint64_t reg_lo, reg_hi,  buffer_offset;
    /*
     * This will define a buffer in the buffer table, allowing
     * it to be used for event queues, descriptor rings etc.
     */
     /* Get physical addresses for rx/tx rings and event queue */
-  
+    /*
     r = invoke_frame_identify(queues[n].rx_frame, &frameid);
     assert(err_is_ok(r));
     rx_phys = frameid.base;
     rx_size = frameid.bytes;  
+    */
     if (userspace) {
         num_ent_rx = NUM_ENT_RX_USR;
     } else {
@@ -1013,14 +1012,14 @@ static uint32_t init_rxq(uint16_t n, bool userspace)
     }
 
     /* RX   */
-    buffer_offset = alloc_buf_tbl_entries(rx_phys, num_ent_rx, 0, 0, d);
+    buffer_offset = alloc_buf_tbl_entries(phys, num_ent_rx, 0, 0, d);
 
     if (buffer_offset == -1) {
        return -1;
     }
 
     DEBUG("RX_QUEUE_%d: buf_off %ld, phys %lx, size %lx \n", n, 
-          buffer_offset, rx_phys, rx_size);
+          buffer_offset, phys, rx_size);
     /* setup RX queue */
     reg_lo = sfn5122f_rx_desc_ptr_tbl_lo_rd(d, n);
     reg_hi = sfn5122f_rx_desc_ptr_tbl_hi_rd(d, n);
@@ -1060,26 +1059,22 @@ static uint32_t init_rxq(uint16_t n, bool userspace)
     return buffer_offset;
 }
 
-static uint32_t init_txq(uint16_t n, bool csum, bool userspace)
+
+static uint32_t init_txq(uint16_t n, uint64_t phys,                        
+                         bool csum, bool userspace)
 {
 
-    errval_t r;
-    size_t tx_size;
-    struct frame_identity frameid = { .base = 0, .bytes = 0 };
-    uint64_t tx_phys, reg, reg1, buffer_offset;    
-    /* Get physical addresses for rx/tx rings and event queue */
-    r = invoke_frame_identify(queues[n].tx_frame, &frameid);
-    assert(err_is_ok(r));
-    tx_phys = frameid.base;
-    tx_size = frameid.bytes;
+    //errval_t r;
+    //struct frame_identity frameid = { .base = 0, .bytes = 0 };
+    uint64_t reg, reg1, buffer_offset;    
   
-    buffer_offset = alloc_buf_tbl_entries(tx_phys, NUM_ENT_TX, 0, 0, d);
+    buffer_offset = alloc_buf_tbl_entries(phys, NUM_ENT_TX, 0, 0, d);
     
     if (buffer_offset == -1) {
        return -1;
     }
 
-    DEBUG("TX_QUEUE_%d: buf_off %ld, phys %lx\n",n , buffer_offset, tx_phys);
+    DEBUG("TX_QUEUE_%d: buf_off %ld, phys %lx\n",n , buffer_offset, phys);
     /* setup TX queue */
     reg = sfn5122f_tx_desc_ptr_tbl_lo_rd(d, n);
     reg1 = sfn5122f_tx_desc_ptr_tbl_hi_rd(d, n);
@@ -1233,6 +1228,7 @@ void cd_register_queue_memory(struct sfn5122f_binding *b,
 {
     // Save state so we can restore the configuration in case we need to do a
     // reset
+    errval_t err;    
 
     bool failed = 0;
     queues[n].enabled = false;
@@ -1250,10 +1246,20 @@ void cd_register_queue_memory(struct sfn5122f_binding *b,
     queues[n].msix_intvec = vector;
     queues[n].msix_intdest = core;
 
-    queues[n].ev_buf_tbl = init_evq(n);
+    struct frame_identity id;
+    err = invoke_frame_identify(ev_frame, &id);
+    assert(err_is_ok(err));
+    queues[n].ev_buf_tbl = init_evq(n, id.base);
+
+
     // enable checksums
-    queues[n].tx_buf_tbl = init_txq(n, csum_offload, userspace);
-    queues[n].rx_buf_tbl = init_rxq(n, userspace);
+    err = invoke_frame_identify(tx_frame, &id);
+    assert(err_is_ok(err));
+    queues[n].tx_buf_tbl = init_txq(n, id.base, csum_offload, userspace);
+
+    err = invoke_frame_identify(rx_frame, &id);
+    assert(err_is_ok(err));
+    queues[n].rx_buf_tbl = init_rxq(n, id.base, userspace);
 
     if(queues[n].ev_buf_tbl == -1 ||
        queues[n].tx_buf_tbl == -1 ||
@@ -1381,11 +1387,14 @@ static struct sfn5122f_rx_vtbl rx_vtbl = {
     .unregister_filter = idc_unregister_filter, 
 };
 
-static void cd_create_queue(struct sfn5122f_devif_binding *b, bool user, 
-                            struct capref rx, struct capref tx, struct capref ev) 
+static void cd_create_queue(struct sfn5122f_devif_binding *b, struct capref frame,
+                            bool user) 
 {
     DEBUG("cd_create_queue \n");
     errval_t err;
+    struct frame_identity id;
+
+
     int n = -1;
     for (int i = 0; i < NUM_QUEUES; i++) {
         if (queues[i].enabled == false) {
@@ -1397,13 +1406,12 @@ static void cd_create_queue(struct sfn5122f_devif_binding *b, bool user,
     if (n == -1) {
         err = SFN_ERR_ALLOC_QUEUE;
         err = b->tx_vtbl.create_queue_response(b, NOP_CONT, 0, NULL_CAP, err);
+        //err = b->tx_vtbl.create_queue_response(b, NOP_CONT, 0, err);
         assert(err_is_ok(err));
     }
     
     queues[n].enabled = false;
-    queues[n].tx_frame = tx;
-    queues[n].rx_frame = rx;
-    queues[n].ev_frame = ev;
+    queues[n].tx_frame = frame;
     queues[n].tx_head = 0;
     queues[n].rx_head = 0;
     queues[n].ev_head = 0;
@@ -1413,22 +1421,33 @@ static void cd_create_queue(struct sfn5122f_devif_binding *b, bool user,
     queues[n].userspace = user;
     queues[n].msix_index = -1;
 
-    queues[n].ev_buf_tbl = init_evq(n);
+    err = invoke_frame_identify(frame, &id);
+    assert(err_is_ok(err));
+    queues[n].ev_buf_tbl = init_evq(n, id.base+sizeof(uint64_t)*(TX_ENTRIES+RX_ENTRIES));
     // enable checksums
-    queues[n].tx_buf_tbl = init_txq(n, csum_offload, user);
-    queues[n].rx_buf_tbl = init_rxq(n, user);
+    queues[n].tx_buf_tbl = init_txq(n, id.base, csum_offload, user);
+    queues[n].rx_buf_tbl = init_rxq(n, id.base+ sizeof(uint64_t)*TX_ENTRIES, user);
 
     if(queues[n].ev_buf_tbl == -1 ||
        queues[n].tx_buf_tbl == -1 ||
        queues[n].rx_buf_tbl == -1){
         err = SFN_ERR_ALLOC_QUEUE;
+        //err = b->tx_vtbl.create_queue_response(b, NOP_CONT, 0, err);
         err = b->tx_vtbl.create_queue_response(b, NOP_CONT, 0, NULL_CAP, err);
         assert(err_is_ok(err));
     }      
 
     queues[n].enabled = true;
     DEBUG("created queue %d \n", n);
-    err = b->tx_vtbl.create_queue_response(b, NOP_CONT, n, *regframe, SYS_ERR_OK);
+    //err = b->tx_vtbl.create_queue_response(b, NOP_CONT, n, *regframe, SYS_ERR_OK);a
+
+    struct capref regs;
+    err = slot_alloc(&regs);
+    assert(err_is_ok(err));
+    err = cap_copy(regs, *regframe);
+    assert(err_is_ok(err));
+
+    err = b->tx_vtbl.create_queue_response(b, NOP_CONT, n, regs, SYS_ERR_OK);
     assert(err_is_ok(err));
     DEBUG("cd_create_queue end\n");
 }