DeviceQueue: added descriptor queues
authorRoni Häcki <roni.haecki@inf.ethz.ch>
Tue, 19 Jul 2016 12:13:52 +0000 (14:13 +0200)
committerRoni Häcki <roni.haecki@inf.ethz.ch>
Tue, 19 Jul 2016 12:13:52 +0000 (14:13 +0200)
Signed-off-by: Roni Häcki <roni.haecki@inf.ethz.ch>

include/devif/queue_interface.h
lib/devif/queue_interface.c
lib/devif/region.c
lib/devif/region_pool.c
lib/devif/region_pool.h

index c2980f9..5605a71 100644 (file)
 
 #define MAX_DEVICE_NAME 256
 
+
+#define DEVICE_TYPE_BLOCK 0x1
+#define DEVICE_TYPE_NET 0x2
+
+
 typedef uint32_t regionid_t;
 typedef uint32_t bufferid_t;
 
@@ -26,14 +31,14 @@ struct devq;
  * ===========================================================================
  */
 
-
  /**
   * @brief creates a queue 
   *
   * @param q             Return pointer to the devq (handle)
   * @param device_name   Device name of the device to which this queue belongs
   *                      (Driver itself is running in a separate process)
-  * @param misc          Anything you can think of that makes sense for the device
+  * @param device_type   The type of the device
+  * @param flags         Anything you can think of that makes sense for the device
   *                      and its driver?
   *
   * @returns error on failure or SYS_ERR_OK on success
@@ -41,9 +46,9 @@ struct devq;
 
 errval_t devq_create(struct devq **q,
                      char* device_name,
+                     uint8_t device_type,
                      uint64_t flags);
 
-
  /**
   * @brief destroys the device queue
   *
@@ -156,7 +161,18 @@ errval_t devq_deregister(struct devq *q,
  * @returns error on failure or SYS_ERR_OK on success
  *
  */
-errval_t devq_sync(struct devq *q);
+errval_t devq_notify(struct devq *q);
+
+/**
+ * @brief Enforce coherency between of the buffers in the queue
+ *        by either flushing the cache or invalidating it
+ *
+ * @param q      The device queue to call the operation on
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ *
+ */
+errval_t devq_enforce_cc(struct devq *q);
 
 /**
  * @brief Send a control message to the device queue
index cf6b9b8..1184f06 100644 (file)
 #include "region_pool.h"
 #include "dqi_debug.h"
 
+#define DESCQ_SIZE 64
+#define DESCQ_ALIGNMENT 64
+
+struct __attribute__((aligned(DESCQ_ALIGNMENT))) descriptor {
+    regionid_t region_id; // 4
+    bufferid_t buffer_id; // 8
+    lpaddr_t base; // 16
+    size_t length; // 24
+    uint64_t misc_flags; // 32
+    uint8_t pad[32];
+};
+
 /**
  * Represent the device queue itself
  */
 struct devq {
-
-    uint32_t queue_id;
-
     // device type
     uint8_t device_type;
 
@@ -28,6 +37,18 @@ struct devq {
     void* q;
     // Region management
     struct region_pool* pool;
+
+    // queue state 
+    uint16_t tx_head;
+    uint16_t tx_tail;
+
+    uint16_t rx_head;
+    uint16_t rx_tail;
+
+    // Queues themselves
+    struct descriptor rx[DESCQ_SIZE];
+    struct descriptor tx[DESCQ_SIZE];
+
     //TODO Other state needed ...
 };
 
@@ -44,7 +65,8 @@ struct devq {
   * @param q             Return pointer to the devq (handle)
   * @param device_name   Device name of the device to which this queue belongs
   *                      (Driver itself is running in a separate process)
-  * @param flags          Anything you can think of that makes sense for the device
+  * @param device_type   The type of the device
+  * @param flags         Anything you can think of that makes sense for the device
   *                      and its driver?
   *
   * @returns error on failure or SYS_ERR_OK on success
@@ -52,62 +74,35 @@ struct devq {
 
 errval_t devq_create(struct devq **q,
                      char* device_name,
+                     uint8_t device_type,
                      uint64_t flags)
 {
-    /*
-    struct region_pool* pool;
-    region_pool_init(&pool);
-    struct capref cap;
-    uint32_t region_ids[100];
-
-    for (int i = 0; i < 100; i++) {
-        region_ids[i] = -1;
-    }
+    errval_t err;
+    struct devq* tmp = malloc(sizeof(struct devq));
+    strncpy(device_name, tmp->device_name, MAX_DEVICE_NAME);
 
-    srand(rdtsc());
-
-    errval_t err = frame_alloc(&cap, 131072, NULL);
-    assert(err_is_ok(err));
+    tmp->rx_head = 0;
+    tmp->tx_head = 0;
+    tmp->rx_tail = 0;
+    tmp->tx_tail = 0;
     
-    void* va;
-    err = vspace_map_one_frame_attr(&va, 131072, cap, 
-                                    VREGION_FLAGS_READ_WRITE, NULL, NULL);
-
-    for (int i = 0; i < 100; i++) {
-        int id = rand() % 100;
-        if (region_ids[id] == -1) {
-            region_pool_add_region(pool, cap, 0x1222222, &region_ids[id]);
-        } else {
-            region_pool_remove_region(pool, region_ids[id], &cap);
-            region_ids[id] = -1;
-        }
+    err = region_pool_init(&(tmp->pool));
+    if (err_is_fail(err)) {
+        free(tmp);
+        return err;
     }
 
-    // Buffer ids are from 0 to 16
-    for (int i = 0; i < 100; i++) {
-        if (region_ids[i] == -1) {      
-            region_pool_add_region(pool, cap, 0x1222222, &region_ids[i]);
-        }
-    }
+    switch (device_type) {
+        case DEVICE_TYPE_BLOCK:
+            break;
+        case DEVICE_TYPE_NET:
+            break;
+        default:
+            USER_PANIC("Devq: unknown device type \n");
 
-    for (int i = 0; i < 100; i++) {
-        lpaddr_t addr;
-        uint32_t buffer_id;
-        for (int j = 0; j < 32; j++) {
-            region_pool_get_buffer_from_region(pool, region_ids[i], &buffer_id, &addr);
-        }
-    
-        for (int j = 0; j < 100; j++) {
-            uint32_t index = rand() % 32;
-            if (region_pool_buffer_of_region_in_use(pool, region_ids[i], index)) {
-                region_pool_return_buffer_to_region(pool, region_ids[i], index);
-            } else {
-                region_pool_get_buffer_from_region(pool, region_ids[i], &index, &addr);
-            }
-        }
     }
-    */   
-    USER_PANIC("NIY\n");
+    // TODO initalize device 
+    // TODO initalize device state
     return SYS_ERR_OK;
 }
 
@@ -120,9 +115,16 @@ errval_t devq_create(struct devq **q,
   *
   * @returns error on failure or SYS_ERR_OK on success
   */
-errval_t devq_destroy(struct devq *qp)
+errval_t devq_destroy(struct devq *q)
 {
-    USER_PANIC("NIY\n");
+    errval_t err;
+
+    err = region_pool_destroy(q->pool);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    free(q);
     return SYS_ERR_OK;
 }
 
@@ -166,7 +168,25 @@ errval_t devq_enqueue(struct devq *q,
                       bufferid_t buffer_id,
                       uint64_t misc_flags) 
 {
-    USER_PANIC("NIY\n");
+    size_t num_free = 0;
+    if (q->tx_head >= q->tx_tail) {
+       num_free = DESCQ_SIZE - (q->tx_head - q->tx_tail);
+    } else {
+       num_free = DESCQ_SIZE - (q->tx_head + DESCQ_SIZE - q->tx_tail);
+    }
+
+    if (num_free == 0) {
+        // TODO reasonable error
+        return -1;
+    }
+
+    q->tx[q->tx_head].region_id = region_id;
+    q->tx[q->tx_head].base = base;
+    q->tx[q->tx_head].length = length;
+    q->tx[q->tx_head].buffer_id = buffer_id;
+    q->tx[q->tx_head].misc_flags = misc_flags;
+    q->tx_head = q->tx_head + 1 % DESCQ_SIZE;    
+
     return SYS_ERR_OK;
 }
 /**
@@ -190,9 +210,27 @@ errval_t devq_dequeue(struct devq *q,
                       size_t* length,
                       bufferid_t* buffer_id)
 {
-    USER_PANIC("NIY\n");
+    size_t num_used = 0;
+    if (q->rx_head >= q->rx_tail) {
+       num_used = (q->rx_head - q->rx_tail);
+    } else {
+       num_used = (q->rx_head + DESCQ_SIZE - q->rx_tail);
+    }
+
+    if (num_used == 0) {
+        // TODO reasonable error
+        return -1;
+    }
+
+    *region_id = q->rx[q->rx_head].region_id;
+    *base = q->rx[q->rx_head].base;
+    *length = q->rx[q->rx_head].length;
+    *buffer_id = q->rx[q->rx_head].buffer_id;
+
+    q->rx_head = q->rx_head + 1 % DESCQ_SIZE;
     return SYS_ERR_OK;
 }
+
 /*
  * ===========================================================================
  * Control Path
@@ -215,8 +253,9 @@ errval_t devq_register(struct devq *q,
                        struct capref cap,
                        regionid_t* region_id)
 {
-    USER_PANIC("NIY\n");
-    return SYS_ERR_OK;
+    errval_t err;
+    err = region_pool_add_region(q->pool, cap, region_id); 
+    return err;
 }
 
 /**
@@ -234,19 +273,35 @@ errval_t devq_deregister(struct devq *q,
                          regionid_t region_id,
                          struct capref* cap)
 {
+    errval_t err;
+    err = region_pool_remove_region(q->pool, region_id, cap); 
+    return err;
+}
+
+/**
+ * @brief Send a notification about new buffers on the queue
+ *
+ * @param q      The device queue to call the operation on
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ *
+ */
+errval_t devq_notify(struct devq *q)
+{
     USER_PANIC("NIY\n");
     return SYS_ERR_OK;
 }
 
 /**
- * @brief Send a notification about new buffers on the queue
+ * @brief Enforce coherency between of the buffers in the queue
+ *        by either flushing the cache or invalidating it
  *
  * @param q      The device queue to call the operation on
  *
  * @returns error on failure or SYS_ERR_OK on success
  *
  */
-errval_t devq_sync(struct devq *q)
+errval_t devq_enforce_cc(struct devq *q)
 {
     USER_PANIC("NIY\n");
     return SYS_ERR_OK;
@@ -269,3 +324,4 @@ errval_t devq_control(struct devq *q,
     USER_PANIC("NIY\n");
     return SYS_ERR_OK;
 }
+
index e4f2b72..20311d2 100644 (file)
@@ -49,13 +49,12 @@ errval_t region_init(struct region** region,
     struct frame_identity id;
 
     struct region* tmp = malloc(sizeof(struct region));
-    if (region == NULL) {
+    if (tmp == NULL) {
         return LIB_ERR_MALLOC_FAIL;
     }
 
     tmp->region_id = region_id;
     tmp->cap = cap;
-    tmp->buf_len = len;
 
     err = invoke_frame_identify(*cap, &id);
     if (err_is_fail(err)) {
@@ -66,14 +65,15 @@ errval_t region_init(struct region** region,
     tmp->len = id.bytes;
 
     // Init state for fixed buffer region
-    tmp->num_buf = id.bytes/len;
     tmp->fixed_size = true;
+    tmp->next_buf = 0;  
+    tmp->num_buf = id.bytes/len;
     tmp->in_use = calloc(sizeof(bool)*tmp->num_buf, 1);
-    if (tmp->in_use == NULL) {
+    if (region == NULL) {
+        free(tmp);
         return LIB_ERR_MALLOC_FAIL;
     }
 
-    tmp->next_buf = 0;  
     *region = tmp;   
     
     DQI_DEBUG("Initialize Region size=%ld addr=%16lx num_bufs=%ld \n",
index db01e85..d38e966 100644 (file)
@@ -56,7 +56,8 @@ errval_t region_pool_init(struct region_pool** pool)
     (*pool)->size = INIT_POOL_SIZE;    
 
     (*pool)->pool = calloc(sizeof(struct region*)*INIT_POOL_SIZE, 1);
-    if (*pool == NULL) {
+    if ((*pool)->pool == NULL) {
+        free(*pool);
         DQI_DEBUG("Allocationg inital pool failed \n");
         return LIB_ERR_MALLOC_FAIL;
     }
@@ -66,6 +67,43 @@ errval_t region_pool_init(struct region_pool** pool)
 }
 
 /**
+
+ * @brief freeing region pool
+ *
+ * @param pool          The region pool to free
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+errval_t region_pool_destroy(struct region_pool* pool)
+{
+    errval_t err;
+    struct capref cap;
+    // Check if there are any regions left
+    if (pool->num_regions == 0) {
+        free(pool->pool);
+        free(pool);
+        return SYS_ERR_OK;
+    } else {
+        // There are regions left -> remove them
+        for (int i = 0; i < pool->size; i++) {
+            if ((void*) pool->pool[i] != NULL) {
+                err = region_pool_remove_region(pool, pool->pool[i]->region_id,
+                                                &cap);
+                if (err_is_fail(err)){
+                    printf("Region pool has regions that are still used,"
+                           " can not free them \n");
+                    return err;
+                }
+            }
+        }
+        free(pool->pool);
+        free(pool);
+    }
+   
+    return SYS_ERR_OK;
+}
+
+/**
  * @brief increase the region pool size by a factor of 2
  *
  * @param pool       the regin pool that has not enough region slots
@@ -112,7 +150,6 @@ static errval_t region_pool_grow(struct region_pool* pool)
  *
  * @param pool          The pool to add the region to
  * @param cap           The cap of the region
- * @param base_addr     The physical base address of the region
  * @param region_id     Return pointer to the region id 
  *                      that is assigned by the pool
  *
@@ -120,7 +157,6 @@ static errval_t region_pool_grow(struct region_pool* pool)
  */
 errval_t region_pool_add_region(struct region_pool* pool, 
                                 struct capref cap,
-                                lpaddr_t base_addr,
                                 uint32_t* region_id)
 {
     errval_t err;
index d34e777..6dd01b8 100644 (file)
@@ -23,12 +23,21 @@ struct region;
  */
 errval_t region_pool_init(struct region_pool** pool);
 
+
+/**
+ * @brief freeing region pool
+ *
+ * @param pool          The region pool to free
+ *
+ * @returns error on failure or SYS_ERR_OK on success
+ */
+errval_t region_pool_destroy(struct region_pool* pool);
+
 /**
  * @brief add a memory region to the region pool
  *
  * @param pool          The pool to add the region to
  * @param cap           The cap of the region
- * @param base_addr     The physical base address of the region
  * @param region_id     Return pointer to the region id 
  *                      that is assigned by the pool
  *
@@ -36,7 +45,6 @@ errval_t region_pool_init(struct region_pool** pool);
  */
 errval_t region_pool_add_region(struct region_pool* pool, 
                                 struct capref cap,
-                                lpaddr_t base_addr,
                                 uint32_t* region_id);
 
 /**