Print this page
3644 Add virtio-net support into the Illumos
Reviewed by: Alexey Zaytsev, alexey.zaytsev@gmail.com
Reviewed by: Yuri Pankov, yuri.pankov@nexenta.com
Reviewed by: David Hoppner, 0xffea@gmail.com

@@ -69,10 +69,11 @@
 #include <sys/sysmacros.h>
 #include <sys/pci.h>
 
 #include "virtiovar.h"
 #include "virtioreg.h"
+
 #define NDEVNAMES       (sizeof (virtio_device_name) / sizeof (char *))
 #define MINSEG_INDIRECT 2       /* use indirect if nsegs >= this value */
 #define VIRTQUEUE_ALIGN(n) (((n)+(VIRTIO_PAGE_SIZE-1)) & \
             ~(VIRTIO_PAGE_SIZE-1))
 

@@ -79,18 +80,17 @@
 void
 virtio_set_status(struct virtio_softc *sc, unsigned int status)
 {
         int old = 0;
 
-        if (status != 0)
-                old = ddi_get8(sc->sc_ioh,
-                    (uint8_t *)(sc->sc_io_addr +
+        if (status != 0) {
+                old = ddi_get8(sc->sc_ioh, (uint8_t *)(sc->sc_io_addr +
                     VIRTIO_CONFIG_DEVICE_STATUS));
+        }
 
-        ddi_put8(sc->sc_ioh,
-            (uint8_t *)(sc->sc_io_addr + VIRTIO_CONFIG_DEVICE_STATUS),
-            status | old);
+        ddi_put8(sc->sc_ioh, (uint8_t *)(sc->sc_io_addr +
+            VIRTIO_CONFIG_DEVICE_STATUS), status | old);
 }
 
 /*
  * Negotiate features, save the result in sc->sc_features
  */

@@ -102,12 +102,11 @@
 
         host_features = ddi_get32(sc->sc_ioh,
             /* LINTED E_BAD_PTR_CAST_ALIGN */
             (uint32_t *)(sc->sc_io_addr + VIRTIO_CONFIG_DEVICE_FEATURES));
 
-        dev_debug(sc->sc_dev, CE_NOTE,
-            "host features: %x, guest features: %x",
+        dev_debug(sc->sc_dev, CE_NOTE, "host features: %x, guest features: %x",
             host_features, guest_features);
 
         features = host_features & guest_features;
         ddi_put32(sc->sc_ioh,
             /* LINTED E_BAD_PTR_CAST_ALIGN */

@@ -118,12 +117,11 @@
 
         return (host_features);
 }
 
 size_t
-virtio_show_features(uint32_t features,
-    char *buf, size_t len)
+virtio_show_features(uint32_t features, char *buf, size_t len)
 {
         char *orig_buf = buf;
         char *bufend = buf + len;
 
         /* LINTED E_PTRDIFF_OVERFLOW */

@@ -192,41 +190,41 @@
             (uint32_t *)(sc->sc_io_addr + sc->sc_config_offset + index));
         return (r);
 }
 
 void
-virtio_write_device_config_1(struct virtio_softc *sc,
-    unsigned int index, uint8_t value)
+virtio_write_device_config_1(struct virtio_softc *sc, unsigned int index,
+    uint8_t value)
 {
         ASSERT(sc->sc_config_offset);
         ddi_put8(sc->sc_ioh,
             (uint8_t *)(sc->sc_io_addr + sc->sc_config_offset + index), value);
 }
 
 void
-virtio_write_device_config_2(struct virtio_softc *sc,
-    unsigned int index, uint16_t value)
+virtio_write_device_config_2(struct virtio_softc *sc, unsigned int index,
+    uint16_t value)
 {
         ASSERT(sc->sc_config_offset);
         ddi_put16(sc->sc_ioh,
             /* LINTED E_BAD_PTR_CAST_ALIGN */
             (uint16_t *)(sc->sc_io_addr + sc->sc_config_offset + index), value);
 }
 
 void
-virtio_write_device_config_4(struct virtio_softc *sc,
-    unsigned int index, uint32_t value)
+virtio_write_device_config_4(struct virtio_softc *sc, unsigned int index,
+    uint32_t value)
 {
         ASSERT(sc->sc_config_offset);
         ddi_put32(sc->sc_ioh,
             /* LINTED E_BAD_PTR_CAST_ALIGN */
             (uint32_t *)(sc->sc_io_addr + sc->sc_config_offset + index), value);
 }
 
 void
-virtio_write_device_config_8(struct virtio_softc *sc,
-    unsigned int index, uint64_t value)
+virtio_write_device_config_8(struct virtio_softc *sc, unsigned int index,
+    uint64_t value)
 {
         ASSERT(sc->sc_config_offset);
         ddi_put32(sc->sc_ioh,
             /* LINTED E_BAD_PTR_CAST_ALIGN */
             (uint32_t *)(sc->sc_io_addr + sc->sc_config_offset + index),

@@ -253,15 +251,12 @@
 }
 
 static ddi_dma_attr_t virtio_vq_dma_attr = {
         DMA_ATTR_V0,    /* Version number */
         0,              /* low address */
-        /*
-         * high address. Has to fit into 32 bits
-         * after page-shifting
-         */
-        0x00000FFFFFFFFFFF,
+        0x00000FFFFFFFFFFF,     /* high address. Has to fit into 32 bits */
+                                /* after page-shifting */
         0xFFFFFFFF,     /* counter register max */
         VIRTIO_PAGE_SIZE, /* page alignment required */
         0x3F,           /* burst sizes: 1 - 32 */
         0x1,            /* minimum transfer size */
         0xFFFFFFFF,     /* max transfer size */

@@ -321,38 +316,37 @@
 
         ret = ddi_dma_alloc_handle(sc->sc_dev, &virtio_vq_indirect_dma_attr,
             DDI_DMA_SLEEP, NULL, &entry->qe_indirect_dma_handle);
         if (ret != DDI_SUCCESS) {
                 dev_err(sc->sc_dev, CE_WARN,
-                    "Failed to allocate dma handle for indirect descriptors,"
-                    " entry %d, vq %d", entry->qe_index,
+                    "Failed to allocate dma handle for indirect descriptors, "
+                    "entry %d, vq %d", entry->qe_index,
                     entry->qe_queue->vq_index);
                 goto out_alloc_handle;
         }
 
-        ret = ddi_dma_mem_alloc(entry->qe_indirect_dma_handle,
-            allocsize, &virtio_vq_devattr,
-            DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
+        ret = ddi_dma_mem_alloc(entry->qe_indirect_dma_handle, allocsize,
+            &virtio_vq_devattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
             (caddr_t *)&entry->qe_indirect_descs, &len,
             &entry->qe_indirect_dma_acch);
         if (ret != DDI_SUCCESS) {
                 dev_err(sc->sc_dev, CE_WARN,
-                    "Failed to alocate dma memory for indirect descriptors,"
-                    " entry %d, vq %d,", entry->qe_index,
+                    "Failed to allocate dma memory for indirect descriptors, "
+                    "entry %d, vq %d,", entry->qe_index,
                     entry->qe_queue->vq_index);
                 goto out_alloc;
         }
 
         (void) memset(entry->qe_indirect_descs, 0xff, allocsize);
 
         ret = ddi_dma_addr_bind_handle(entry->qe_indirect_dma_handle, NULL,
             (caddr_t)entry->qe_indirect_descs, len,
-            DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
-            DDI_DMA_SLEEP, NULL, &entry->qe_indirect_dma_cookie, &ncookies);
+            DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
+            &entry->qe_indirect_dma_cookie, &ncookies);
         if (ret != DDI_DMA_MAPPED) {
                 dev_err(sc->sc_dev, CE_WARN,
-                    "Failed to bind dma memory for indirect descriptors,"
+                    "Failed to bind dma memory for indirect descriptors, "
                     "entry %d, vq %d", entry->qe_index,
                     entry->qe_queue->vq_index);
                 goto out_bind;
         }
 

@@ -397,16 +391,16 @@
                         if (ret)
                                 goto out_indirect;
                 }
         }
 
-        mutex_init(&vq->vq_freelist_lock, "virtio-freelist",
-            MUTEX_DRIVER, DDI_INTR_PRI(sc->sc_intr_prio));
-        mutex_init(&vq->vq_avail_lock, "virtio-avail",
-            MUTEX_DRIVER, DDI_INTR_PRI(sc->sc_intr_prio));
-        mutex_init(&vq->vq_used_lock, "virtio-used",
-            MUTEX_DRIVER, DDI_INTR_PRI(sc->sc_intr_prio));
+        mutex_init(&vq->vq_freelist_lock, "virtio-freelist", MUTEX_DRIVER,
+            DDI_INTR_PRI(sc->sc_intr_prio));
+        mutex_init(&vq->vq_avail_lock, "virtio-avail", MUTEX_DRIVER,
+            DDI_INTR_PRI(sc->sc_intr_prio));
+        mutex_init(&vq->vq_used_lock, "virtio-used", MUTEX_DRIVER,
+            DDI_INTR_PRI(sc->sc_intr_prio));
 
         return (0);
 
 out_indirect:
         for (i = 0; i < vq_size; i++) {

@@ -416,29 +410,23 @@
         }
 
         return (ret);
 }
 
-
-
 /*
  * Allocate/free a vq.
  */
 struct virtqueue *
-virtio_alloc_vq(struct virtio_softc *sc,
-    unsigned int index,
-    unsigned int size,
-    unsigned int indirect_num,
-    const char *name)
+virtio_alloc_vq(struct virtio_softc *sc, unsigned int index, unsigned int size,
+    unsigned int indirect_num, const char *name)
 {
         int vq_size, allocsize1, allocsize2, allocsize = 0;
         int ret;
         unsigned int ncookies;
         size_t len;
         struct virtqueue *vq;
 
-
         ddi_put16(sc->sc_ioh,
             /* LINTED E_BAD_PTR_CAST_ALIGN */
             (uint16_t *)(sc->sc_io_addr + VIRTIO_CONFIG_QUEUE_SELECT), index);
         vq_size = ddi_get16(sc->sc_ioh,
             /* LINTED E_BAD_PTR_CAST_ALIGN */

@@ -455,15 +443,14 @@
         if (size)
                 vq_size = MIN(vq_size, size);
 
         /* allocsize1: descriptor table + avail ring + pad */
         allocsize1 = VIRTQUEUE_ALIGN(sizeof (struct vring_desc) * vq_size +
-            sizeof (struct vring_avail) +
-            sizeof (uint16_t) * vq_size);
+            sizeof (struct vring_avail) + sizeof (uint16_t) * vq_size);
         /* allocsize2: used ring + pad */
-        allocsize2 = VIRTQUEUE_ALIGN(sizeof (struct vring_used)
-            + sizeof (struct vring_used_elem) * vq_size);
+        allocsize2 = VIRTQUEUE_ALIGN(sizeof (struct vring_used) +
+            sizeof (struct vring_used_elem) * vq_size);
 
         allocsize = allocsize1 + allocsize2;
 
         ret = ddi_dma_alloc_handle(sc->sc_dev, &virtio_vq_dma_attr,
             DDI_DMA_SLEEP, NULL, &vq->vq_dma_handle);

@@ -476,18 +463,16 @@
         ret = ddi_dma_mem_alloc(vq->vq_dma_handle, allocsize,
             &virtio_vq_devattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
             (caddr_t *)&vq->vq_vaddr, &len, &vq->vq_dma_acch);
         if (ret != DDI_SUCCESS) {
                 dev_err(sc->sc_dev, CE_WARN,
-                    "Failed to alocate dma memory for vq %d", index);
+                    "Failed to allocate dma memory for vq %d", index);
                 goto out_alloc;
         }
 
-
         ret = ddi_dma_addr_bind_handle(vq->vq_dma_handle, NULL,
-            (caddr_t)vq->vq_vaddr, len,
-            DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
+            (caddr_t)vq->vq_vaddr, len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
             DDI_DMA_SLEEP, NULL, &vq->vq_dma_cookie, &ncookies);
         if (ret != DDI_DMA_MAPPED) {
                 dev_err(sc->sc_dev, CE_WARN,
                     "Failed to bind dma memory for vq %d", index);
                 goto out_bind;

@@ -530,11 +515,11 @@
         ret = virtio_init_vq(sc, vq);
         if (ret)
                 goto out_init;
 
         dev_debug(sc->sc_dev, CE_NOTE,
-            "Allocated %d entries for vq %d:%s (%d incdirect descs)",
+            "Allocated %d entries for vq %d:%s (%d indirect descs)",
             vq_size, index, name, indirect_num * vq_size);
 
         return (vq);
 
 out_init:

@@ -548,11 +533,10 @@
         kmem_free(vq, sizeof (struct virtqueue));
 out:
         return (NULL);
 }
 
-
 void
 virtio_free_vq(struct virtqueue *vq)
 {
         struct virtio_softc *sc = vq->vq_owner;
         int i;

@@ -646,21 +630,25 @@
         desc->flags = 0;
 
         /* 'write' - from the driver's point of view */
         if (!write)
                 desc->flags = VRING_DESC_F_WRITE;
-
-
 }
 
 void
 virtio_ve_set(struct vq_entry *qe, uint64_t paddr, uint32_t len,
     boolean_t write)
 {
         virtio_ve_set_desc(qe->qe_desc, paddr, len, write);
 }
 
+unsigned int
+virtio_ve_indirect_available(struct vq_entry *qe)
+{
+        return (qe->qe_queue->vq_indirect_num - (qe->qe_indirect_next - 1));
+}
+
 void
 virtio_ve_add_indirect_buf(struct vq_entry *qe, uint64_t paddr, uint32_t len,
     boolean_t write)
 {
         struct vring_desc *indirect_desc;

@@ -700,16 +688,17 @@
         membar_producer();
 
         /* Make sure we see the flags update */
         membar_consumer();
 
-        if (!(vq->vq_used->flags & VRING_USED_F_NO_NOTIFY))
+        if (!(vq->vq_used->flags & VRING_USED_F_NO_NOTIFY)) {
                 ddi_put16(vsc->sc_ioh,
                     /* LINTED E_BAD_PTR_CAST_ALIGN */
                     (uint16_t *)(vsc->sc_io_addr +
                     VIRTIO_CONFIG_QUEUE_NOTIFY),
                     vq->vq_index);
+        }
 }
 
 void
 virtio_push_chain(struct vq_entry *qe, boolean_t sync)
 {

@@ -771,11 +760,13 @@
                 virtio_sync_vq(vq);
 
         mutex_exit(&vq->vq_avail_lock);
 }
 
-/* Get a chain of descriptors from the used ring, if one is available. */
+/*
+ * Get a chain of descriptors from the used ring, if one is available.
+ */
 struct vq_entry *
 virtio_pull_chain(struct virtqueue *vq, uint32_t *len)
 {
         struct vq_entry *head;
         int slot;

@@ -817,11 +808,11 @@
         do {
                 ASSERT(qe->qe_queue == vq);
                 tmp = qe->qe_next;
                 vq_free_entry(vq, qe);
                 qe = tmp;
-        } while (tmp);
+        } while (tmp != NULL);
 }
 
 void
 virtio_ventry_stick(struct vq_entry *first, struct vq_entry *second)
 {

@@ -829,12 +820,11 @@
 }
 
 static int
 virtio_register_msi(struct virtio_softc *sc,
     struct virtio_int_handler *config_handler,
-    struct virtio_int_handler vq_handlers[],
-    int intr_types)
+    struct virtio_int_handler vq_handlers[], int intr_types)
 {
         int count, actual;
         int int_type;
         int i;
         int handler_count;

@@ -850,11 +840,11 @@
             vq_handlers && vq_handlers[handler_count].vh_func;
             handler_count++)
                 ;
 
         /* +1 if there is a config change handler. */
-        if (config_handler)
+        if (config_handler != NULL)
                 handler_count++;
 
         /* Number of MSIs supported by the device. */
         ret = ddi_intr_get_nintrs(sc->sc_dev, int_type, &count);
         if (ret != DDI_SUCCESS) {

@@ -866,12 +856,12 @@
          * Those who try to register more handlers then the device
          * supports shall suffer.
          */
         ASSERT(handler_count <= count);
 
-        sc->sc_intr_htable = kmem_zalloc(
-            sizeof (ddi_intr_handle_t) * handler_count, KM_SLEEP);
+        sc->sc_intr_htable = kmem_zalloc(sizeof (ddi_intr_handle_t) *
+            handler_count, KM_SLEEP);
 
         ret = ddi_intr_alloc(sc->sc_dev, sc->sc_intr_htable, int_type, 0,
             handler_count, &actual, DDI_INTR_ALLOC_NORMAL);
         if (ret != DDI_SUCCESS) {
                 dev_err(sc->sc_dev, CE_WARN, "Failed to allocate MSI: %d", ret);

@@ -885,11 +875,11 @@
                 goto out_msi_available;
         }
 
         sc->sc_intr_num = handler_count;
         sc->sc_intr_config = B_FALSE;
-        if (config_handler) {
+        if (config_handler != NULL) {
                 sc->sc_intr_config = B_TRUE;
         }
 
         /* Assume they are all same priority */
         ret = ddi_intr_get_pri(sc->sc_intr_htable[0], &sc->sc_intr_prio);

@@ -899,12 +889,11 @@
         }
 
         /* Add the vq handlers */
         for (i = 0; vq_handlers[i].vh_func; i++) {
                 ret = ddi_intr_add_handler(sc->sc_intr_htable[i],
-                    vq_handlers[i].vh_func,
-                    sc, vq_handlers[i].vh_priv);
+                    vq_handlers[i].vh_func, sc, vq_handlers[i].vh_priv);
                 if (ret != DDI_SUCCESS) {
                         dev_err(sc->sc_dev, CE_WARN,
                             "ddi_intr_add_handler failed");
                         /* Remove the handlers that succeeded. */
                         while (--i >= 0) {

@@ -914,14 +903,13 @@
                         goto out_add_handlers;
                 }
         }
 
         /* Don't forget the config handler */
-        if (config_handler) {
+        if (config_handler != NULL) {
                 ret = ddi_intr_add_handler(sc->sc_intr_htable[i],
-                    config_handler->vh_func,
-                    sc, config_handler->vh_priv);
+                    config_handler->vh_func, sc, config_handler->vh_priv);
                 if (ret != DDI_SUCCESS) {
                         dev_err(sc->sc_dev, CE_WARN,
                             "ddi_intr_add_handler failed");
                         /* Remove the handlers that succeeded. */
                         while (--i >= 0) {

@@ -933,12 +921,11 @@
         }
 
         /* We know we are using MSI, so set the config offset. */
         sc->sc_config_offset = VIRTIO_CONFIG_DEVICE_CONFIG_MSI;
 
-        ret = ddi_intr_get_cap(sc->sc_intr_htable[0],
-            &sc->sc_intr_cap);
+        ret = ddi_intr_get_cap(sc->sc_intr_htable[0], &sc->sc_intr_cap);
         /* Just in case. */
         if (ret != DDI_SUCCESS)
                 sc->sc_intr_cap = 0;
 
 out_add_handlers:

@@ -1006,32 +993,30 @@
         for (vq_handler_count = 0;
             vq_handlers && vq_handlers[vq_handler_count].vh_func;
             vq_handler_count++)
                 ;
 
-        if (config_handler)
+        if (config_handler != NULL)
                 config_handler_count = 1;
 
         vhc = kmem_zalloc(sizeof (struct virtio_handler_container) +
-            sizeof (struct virtio_int_handler) * vq_handler_count,
-            KM_SLEEP);
+            sizeof (struct virtio_int_handler) * vq_handler_count, KM_SLEEP);
 
         vhc->nhandlers = vq_handler_count;
         (void) memcpy(vhc->vq_handlers, vq_handlers,
             sizeof (struct virtio_int_handler) * vq_handler_count);
 
-        if (config_handler) {
+        if (config_handler != NULL) {
                 (void) memcpy(&vhc->config_handler, config_handler,
                     sizeof (struct virtio_int_handler));
         }
 
         /* Just a single entry for a single interrupt. */
         sc->sc_intr_htable = kmem_zalloc(sizeof (ddi_intr_handle_t), KM_SLEEP);
 
         ret = ddi_intr_alloc(sc->sc_dev, sc->sc_intr_htable,
-            DDI_INTR_TYPE_FIXED, 0, 1, &actual,
-            DDI_INTR_ALLOC_NORMAL);
+            DDI_INTR_TYPE_FIXED, 0, 1, &actual, DDI_INTR_ALLOC_NORMAL);
         if (ret != DDI_SUCCESS) {
                 dev_err(sc->sc_dev, CE_WARN,
                     "Failed to allocate a fixed interrupt: %d", ret);
                 goto out_int_alloc;
         }

@@ -1109,11 +1094,10 @@
 
 out_inttype:
         return (ret);
 }
 
-
 static int
 virtio_enable_msi(struct virtio_softc *sc)
 {
         int ret, i;
         int vq_handler_count = sc->sc_intr_num;

@@ -1149,10 +1133,11 @@
         }
 
         /* Bind the allocated MSI to the queues and config */
         for (i = 0; i < vq_handler_count; i++) {
                 int check;
+
                 ddi_put16(sc->sc_ioh,
                     /* LINTED E_BAD_PTR_CAST_ALIGN */
                     (uint16_t *)(sc->sc_io_addr +
                     VIRTIO_CONFIG_QUEUE_SELECT), i);
 

@@ -1164,19 +1149,20 @@
                 check = ddi_get16(sc->sc_ioh,
                     /* LINTED E_BAD_PTR_CAST_ALIGN */
                     (uint16_t *)(sc->sc_io_addr +
                     VIRTIO_CONFIG_QUEUE_VECTOR));
                 if (check != i) {
-                        dev_err(sc->sc_dev, CE_WARN, "Failed to bind handler"
+                        dev_err(sc->sc_dev, CE_WARN, "Failed to bind handler "
                             "for VQ %d, MSI %d. Check = %x", i, i, check);
                         ret = ENODEV;
                         goto out_bind;
                 }
         }
 
         if (sc->sc_intr_config) {
                 int check;
+
                 ddi_put16(sc->sc_ioh,
                     /* LINTED E_BAD_PTR_CAST_ALIGN */
                     (uint16_t *)(sc->sc_io_addr +
                     VIRTIO_CONFIG_CONFIG_VECTOR), i);
 

@@ -1217,18 +1203,21 @@
 
 out_enable:
         return (ret);
 }
 
-static int virtio_enable_intx(struct virtio_softc *sc)
+static int
+virtio_enable_intx(struct virtio_softc *sc)
 {
         int ret;
 
         ret = ddi_intr_enable(sc->sc_intr_htable[0]);
-        if (ret != DDI_SUCCESS)
+        if (ret != DDI_SUCCESS) {
                 dev_err(sc->sc_dev, CE_WARN,
                     "Failed to enable interrupt: %d", ret);
+        }
+
         return (ret);
 }
 
 /*
  * We can't enable/disable individual handlers in the INTx case so do

@@ -1280,21 +1269,20 @@
         if (sc->sc_intr_cap & DDI_INTR_FLAG_BLOCK) {
                 ret = ddi_intr_block_disable(sc->sc_intr_htable,
                     sc->sc_intr_num);
                 if (ret != DDI_SUCCESS) {
                         dev_err(sc->sc_dev, CE_WARN,
-                            "Failed to disable MSIs, won't be able to"
+                            "Failed to disable MSIs, won't be able to "
                             "reuse next time");
                 }
         } else {
                 for (i = 0; i < sc->sc_intr_num; i++) {
                         ret = ddi_intr_disable(sc->sc_intr_htable[i]);
                         if (ret != DDI_SUCCESS) {
                                 dev_err(sc->sc_dev, CE_WARN,
                                     "Failed to disable interrupt %d, "
                                     "won't be able to reuse", i);
-
                         }
                 }
         }
 
 

@@ -1303,14 +1291,13 @@
         }
 
         for (i = 0; i < sc->sc_intr_num; i++)
                 (void) ddi_intr_free(sc->sc_intr_htable[i]);
 
-        kmem_free(sc->sc_intr_htable,
-            sizeof (ddi_intr_handle_t) * sc->sc_intr_num);
+        kmem_free(sc->sc_intr_htable, sizeof (ddi_intr_handle_t) *
+            sc->sc_intr_num);
 
-
         /* After disabling interrupts, the config offset is non-MSI. */
         sc->sc_config_offset = VIRTIO_CONFIG_DEVICE_CONFIG_NOMSI;
 }
 
 /*