DeviceQueue: towards MSIX support for solarflare card
authorRoni Häcki <roni.haecki@inf.ethz.ch>
Tue, 17 Jan 2017 16:17:19 +0000 (17:17 +0100)
committerRoni Häcki <roni.haecki@inf.ethz.ch>
Tue, 17 Jan 2017 16:17:19 +0000 (17:17 +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/Hakefile
usr/drivers/solarflare/sfn5122f_cdriver.c
usr/tests/devif/queue_interface.c

index 7b0a1c5..ea28736 100644 (file)
@@ -17,7 +17,8 @@ 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 cap frame, in bool user,
+    rpc create_queue(in cap frame, in bool user, in bool interrupt,
+                     in uint8 core, in uint8 vector,
                      out uint16 qid, out cap regs, out errval err);
     rpc destroy_queue(in uint16 qid, out errval err);
 
index feef042..0c4947e 100644 (file)
@@ -14,6 +14,7 @@
 #include <barrelfish/deferred.h>
 #include <barrelfish/nameservice_client.h>
 #include <devif/queue_interface.h>
+#include <pci/pci.h>
 #include <if/sfn5122f_devif_defs.h>
 #include <if/sfn5122f_devif_rpcclient_defs.h>
 #include <devif/backends/net/sfn5122f_devif.h>
@@ -28,7 +29,7 @@
     #define DEBUG_QUEUE(x...) do {} while (0)
 #endif
 
-#define DELAY 1
+//#define DELAY 1
 
 // TX Queue
 #define TX_ENTRIES 2048
@@ -325,6 +326,9 @@ static errval_t sfn5122f_dequeue(struct devq* q, regionid_t* rid, bufferid_t* bi
     
     struct sfn5122f_queue* queue = (struct sfn5122f_queue*) q;
 
+    sfn5122f_evq_rptr_reg_wr(queue->device, queue->id, queue->ev_head);
+    //__sync_synchronize();
+
     if (queue->num_left > 0) {
         *rid = queue->bufs[queue->last_deq].rid;
         *bid = queue->bufs[queue->last_deq].bid;
@@ -391,14 +395,22 @@ static errval_t sfn5122f_dequeue(struct devq* q, regionid_t* rid, bufferid_t* bi
     return err;
 }
 
+static void interrupt_handler(void* arg)
+{
+    printf("WTF \n");
+    struct sfn5122f_queue* queue = (struct sfn5122f_queue*) arg;
+    // TODO check fata interrupts
+
+    queue->cb(queue);
+}
+
 /**
  * Public functions
  *
  */
 
 errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, sfn5122f_event_cb_t cb, 
-                               bool userlevel, 
-                               bool interrupts)
+                               bool userlevel, bool interrupts)
 {
     DEBUG_QUEUE("create called \n");
 
@@ -428,26 +440,6 @@ errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, sfn5122f_event_cb_t cb
     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) {
-        return SFN_ERR_ALLOC_QUEUE;
-    }
-
-    rx_size = sfn5122f_q_rx_user_desc_size * RX_ENTRIES;
-    rx_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, rx_size, &rx_frame);
-    if (rx_virt == NULL) {
-        return SFN_ERR_ALLOC_QUEUE;
-    }
-
-    ev_size = sfn5122f_q_event_entry_size * EV_ENTRIES;
-    ev_virt = alloc_map_frame(VREGION_FLAGS_READ_WRITE, ev_size, &ev_frame);
-    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,
@@ -455,7 +447,9 @@ errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, sfn5122f_event_cb_t cb
 
     queue->frame = frame;
     queue->bound = false;
+    queue->cb = cb;
 
+    
     iref_t iref;
     const char *name = "sfn5122f_sfn5122fmng_devif";
 
@@ -483,11 +477,29 @@ errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, sfn5122f_event_cb_t cb
     struct capref regs;
 
     // Inform card driver about new queue and get the registers/queue id
-    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;
+
+    if (!interrupts) {
+        printf("Solarflare queue used in polling mode \n");
+        err = queue->rpc->vtbl.create_queue(queue->rpc, frame, userlevel, interrupts, 
+                                            0, 0, &queue->id, &regs, &err2);
+        if (err_is_fail(err) || err_is_fail(err2)) {
+            err = err_is_fail(err) ? err: err2;
+            return err;
+        }
+    } else {
+        printf("Solarflare queue used in interrupt mode mode \n");
+        err = pci_setup_inthandler(interrupt_handler, queue, &queue->vector);
+        assert(err_is_ok(err));
+
+        queue->core = disp_get_core_id();
+        
+        err = queue->rpc->vtbl.create_queue(queue->rpc, frame, userlevel, interrupts, queue->core,
+                                            queue->vector, &queue->id, 
+                                            &regs, &err2);
+        if (err_is_fail(err) || err_is_fail(err2)) {
+            err = err_is_fail(err) ? err: err2;
+            printf("Registering interrupt failed, continueing in polling mode \n");
+        }
     }
 
     DEBUG_QUEUE("rpc done \n");
@@ -520,17 +532,6 @@ errval_t sfn5122f_queue_create(struct sfn5122f_queue** q, sfn5122f_event_cb_t cb
     queue->q.f.ctrl = sfn5122f_control;
     queue->q.f.notify = sfn5122f_notify;
     
-    if (!interrupts) {
-        queue->event = malloc(sizeof(struct periodic_event));
-
-        err = periodic_event_create(queue->event, get_default_waitset(),
-                                    DELAY, MKCLOSURE(cb, queue));
-        if (err_is_fail(err)) {
-            return err;
-        }
-    } else {
-        USER_PANIC("Interrupts NIY \n");
-    }
     *q = queue;
 
     return SYS_ERR_OK;
@@ -545,13 +546,6 @@ errval_t sfn5122f_queue_destroy(struct sfn5122f_queue* q)
         return err;
     }
 
-    err = periodic_event_cancel(q->event);
-    if (err_is_fail(err)) {
-        return err;
-    }
-
-    free(q->event);
-    
     err = vspace_unmap(q->device_va);
     if (err_is_fail(err)) {
         return err;
index 1b3f41c..3d9572a 100644 (file)
@@ -82,8 +82,13 @@ struct sfn5122f_queue {
     struct sfn5122f_devif_rpc_client* rpc;
     volatile bool bound;
 
+
+    // interrupts
+    uint8_t core;
+    uint8_t vector;
+
     // callback 
-    struct periodic_event* event;
+    sfn5122f_event_cb_t cb;
 
     // Direct interface fields
     uint16_t id;
index 388c0b4..1870339 100644 (file)
@@ -1,5 +1,5 @@
 --------------------------------------------------------------------------
--- Copyright (c) 2007-2009, 2011, ETH Zurich.
+-- Copyright (c) 2007-2009, 2011, 2016-2017 ETH Zurich.
 -- All rights reserved.
 --
 -- This file is distributed under the terms in the attached LICENSE file.
index 12484bd..004d5c2 100644 (file)
@@ -14,6 +14,7 @@
 #include <net_queue_manager/net_queue_manager.h>
 #include <barrelfish/nameservice_client.h>
 #include <barrelfish/spawn_client.h>
+#include <barrelfish/deferred.h>
 #include <pci/pci.h>
 #include <ipv4/lwip/inet.h>
 #include <barrelfish/debug.h>
@@ -213,7 +214,7 @@ 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);
-static void interrupt_handler(void* arg);
+static void global_interrupt_handler(void* arg);
 
 static void bind_arp(struct waitset *ws);
 static errval_t arp_ip_info(void);
@@ -769,7 +770,7 @@ static void device_init(void)
     if (use_msix) {
         reg = sfn5122f_int_adr_reg_ker_hi_norm_int_vec_dis_ker_insert(reg, 1);
         if (cdriver_msix == -1) {
-            r = pci_setup_inthandler(interrupt_handler, NULL, &cdriver_vector);
+            r = pci_setup_inthandler(global_interrupt_handler, NULL, &cdriver_vector);
             assert(err_is_ok(r));
             setup_interrupt(&cdriver_msix, disp_get_core_id(), cdriver_vector);
         }
@@ -862,7 +863,6 @@ static void start_all(void)
     in[CMD_MAC_STATS_IN_DMA_LEN_OFFSET+1] = 3;
     errval_t err = mcdi_rpc(CMD_MAC_STATS, in, CMD_MAC_STATS_IN_LEN, 
                             NULL, 0, NULL, pci_function, d); 
-
     assert(err_is_ok(err));
 }
 
@@ -980,8 +980,10 @@ static uint32_t init_evq(uint16_t n, lpaddr_t phys)
     } else {
         reg = sfn5122f_timer_command_reg_lo_tc_timer_mode_insert(reg, 0); 
     }
+
     sfn5122f_timer_command_reg_lo_wr(d, n, reg);
 
+
     sfn5122f_evq_rptr_reg_wr(d, n, queues[n].ev_head);
 
     return buffer_offset;
@@ -989,7 +991,6 @@ static uint32_t init_evq(uint16_t n, lpaddr_t phys)
 
 static uint32_t init_rxq(uint16_t n, lpaddr_t phys, bool userspace)
 {
-
     //errval_t r;
     size_t num_ent_rx;
     //struct frame_identity frameid = { .base = 0, .bytes = 0 };
@@ -1137,7 +1138,7 @@ static void setup_interrupt(size_t *msix_index, uint8_t core, uint8_t vector)
 }
 
 /** Here are the global interrupts handled. */
-static void interrupt_handler(void* arg)
+static void global_interrupt_handler(void* arg)
 {
     //uint64_t reg;
     uint32_t queue;
@@ -1261,6 +1262,7 @@ void cd_register_queue_memory(struct sfn5122f_binding *b,
     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 ||
        queues[n].rx_buf_tbl == -1){
@@ -1269,6 +1271,8 @@ void cd_register_queue_memory(struct sfn5122f_binding *b,
        return;
     }      
 
+    queues[n].enabled = true;
+
     if (queues[n].use_irq) {
         if (queues[n].msix_intvec != 0) {
             if (queues[n].msix_index == -1) {
@@ -1278,8 +1282,6 @@ void cd_register_queue_memory(struct sfn5122f_binding *b,
         } 
     }
 
-    queues[n].enabled = true;
-
     idc_write_queue_tails(queues[n].binding);     
 
     if (b == NULL) {
@@ -1388,13 +1390,12 @@ static struct sfn5122f_rx_vtbl rx_vtbl = {
 };
 
 static void cd_create_queue(struct sfn5122f_devif_binding *b, struct capref frame,
-                            bool user) 
+                            bool user, bool interrupt, uint8_t core, uint8_t msix_vector) 
 {
     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) {
@@ -1410,6 +1411,7 @@ static void cd_create_queue(struct sfn5122f_devif_binding *b, struct capref fram
         assert(err_is_ok(err));
     }
     
+    queues[n].use_irq = interrupt;
     queues[n].enabled = false;
     queues[n].tx_frame = frame;
     queues[n].tx_head = 0;
@@ -1417,9 +1419,19 @@ static void cd_create_queue(struct sfn5122f_devif_binding *b, struct capref fram
     queues[n].ev_head = 0;
     queues[n].rxbufsz = MTU_MAX;
     queues[n].devif = b;
-    queues[n].use_irq = false;
     queues[n].userspace = user;
     queues[n].msix_index = -1;
+    queues[n].msix_intdest = core;
+    queues[n].msix_intvec = msix_vector;
+
+    if (queues[n].use_irq) {
+        if (queues[n].msix_intvec != 0) {
+            if (queues[n].msix_index == -1) {
+                setup_interrupt(&queues[n].msix_index, queues[n].msix_intdest,
+                                queues[n].msix_intvec);
+            }
+        } 
+    }
 
     err = invoke_frame_identify(frame, &id);
     assert(err_is_ok(err));
@@ -1672,6 +1684,11 @@ static void pci_init_card(struct device_mem* bar_info, int bar_count)
     /* initalize managemnt interface   */
     initialize_mngif();  
     initialized = true;
+
+    if (first){
+       start_all();
+       first = 0;
+    }
 }
 
 static void parse_cmdline(int argc, char **argv)
@@ -1730,7 +1747,7 @@ int main(int argc, char** argv)
                                 PCI_DONT_CARE, PCI_DONT_CARE, 
                                 PCI_VENDOR_SOLARFLARE, DEVICE_ID,
                                 pci_bus, pci_device, pci_function, 
-                                interrupt_handler, NULL);
+                                global_interrupt_handler, NULL);
 
     while (!initialized) {
         event_dispatch(get_default_waitset());
index 95830e2..cf63ead 100644 (file)
@@ -258,7 +258,8 @@ static void test_sfn5122f_rx(void)
     struct sfn5122f_queue* queue;
 
     printf("SFN5122F direct device test started \n");
-    err = sfn5122f_queue_create(&queue, sfn5122f_event_cb, true, false);
+    err = sfn5122f_queue_create(&queue, sfn5122f_event_cb, /* userlevel*/ true, 
+                                /*MSIX interrupts*/ false);
     if (err_is_fail(err)){
         USER_PANIC("Allocating devq failed \n");
     }