qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 10/27] dimm: add busy slot check and slot auto-alloc


From: Igor Mammedov
Subject: [Qemu-devel] [PATCH 10/27] dimm: add busy slot check and slot auto-allocation
Date: Thu, 21 Nov 2013 03:38:31 +0100

- if slot property is not specified on -device/device_add command,
treat default value as request for assigning DimmDevice to
the first free slot.

- if slot is provided with -device/device_add command, attempt to
use it or fail command if it's already occupied.

Signed-off-by: Igor Mammedov <address@hidden>
---
v2:
  s/dc/dbc/
---
 hw/mem/dimm.c         |   51 ++++++++++++++++++++++++++++++++++++++++++++++++-
 include/hw/mem/dimm.h |    4 +++
 2 files changed, 54 insertions(+), 1 deletions(-)

diff --git a/hw/mem/dimm.c b/hw/mem/dimm.c
index b3d6fda..8837ffe 100644
--- a/hw/mem/dimm.c
+++ b/hw/mem/dimm.c
@@ -21,6 +21,7 @@
 #include "hw/mem/dimm.h"
 #include "qemu/config-file.h"
 #include "qapi/visitor.h"
+#include "qemu/bitmap.h"
 
 static void dimm_bus_initfn(Object *obj)
 {
@@ -28,6 +29,45 @@ static void dimm_bus_initfn(Object *obj)
 
     b->allow_hotplug = true;
 }
+
+static int dimm_bus_slot2bitmap(DeviceState *dev, void *opaque)
+{
+    unsigned long *bitmap = opaque;
+    BusClass *bc = BUS_GET_CLASS(qdev_get_parent_bus(dev));
+    DimmDevice *d = DIMM(dev);
+
+    if (dev->realized) { /* count only realized DIMMs */
+        g_assert(d->slot < bc->max_dev);
+        set_bit(d->slot, bitmap);
+    }
+    return 0;
+}
+
+static int dimm_bus_get_free_slot(DimmBus *bus, const int *hint, Error **errp)
+{
+    BusClass *bc = BUS_GET_CLASS(bus);
+    unsigned long *bitmap = bitmap_new(bc->max_dev);
+    int slot = 0;
+
+    qbus_walk_children(BUS(bus), dimm_bus_slot2bitmap, NULL, bitmap);
+
+    /* check if requested slot is not occupied */
+    if (hint) {
+        if (!test_bit(*hint, bitmap)) {
+            slot = *hint;
+        } else {
+            error_setg(errp, "slot %d is busy", *hint);
+        }
+        goto out;
+    }
+
+    /* search for free slot */
+    slot = find_first_zero_bit(bitmap, bc->max_dev);
+out:
+    g_free(bitmap);
+    return slot;
+}
+
 static void dimm_bus_register_memory(DimmBus *bus, DimmDevice *dimm,
                                      Error **errp)
 {
@@ -43,6 +83,7 @@ static void dimm_bus_class_init(ObjectClass *oc, void *data)
 
     bc->max_dev = qemu_opt_get_number(opts, "slots", 0);
     dbc->register_memory = dimm_bus_register_memory;
+    dbc->get_free_slot = dimm_bus_get_free_slot;
 }
 
 static const TypeInfo dimm_bus_info = {
@@ -57,7 +98,7 @@ static const TypeInfo dimm_bus_info = {
 static Property dimm_properties[] = {
     DEFINE_PROP_UINT64("start", DimmDevice, start, 0),
     DEFINE_PROP_UINT32("node", DimmDevice, node, 0),
-    DEFINE_PROP_INT32("slot", DimmDevice, slot, 0),
+    DEFINE_PROP_INT32("slot", DimmDevice, slot, -1),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -132,6 +173,7 @@ static void dimm_realize(DeviceState *dev, Error **errp)
     DimmBus *bus = DIMM_BUS(qdev_get_parent_bus(dev));
     BusClass *bc = BUS_GET_CLASS(bus);
     DimmBusClass *dbc = DIMM_BUS_GET_CLASS(bus);
+    int *slot_hint;
 
     if (!dimm->mr) {
         error_setg(errp, "'memdev' property is not set");
@@ -147,6 +189,13 @@ static void dimm_realize(DeviceState *dev, Error **errp)
         error_setg(errp, "maximum allowed slot is: %d", bc->max_dev - 1);
         return;
     }
+    g_assert(dbc->get_free_slot);
+    slot_hint = dimm->slot < 0 ? NULL : &dimm->slot;
+    dimm->slot = dbc->get_free_slot(bus, slot_hint, errp);
+    if (error_is_set(errp)) {
+        return;
+    }
+
 
     g_assert(dbc->register_memory);
     dbc->register_memory(bus, dimm, errp);
diff --git a/include/hw/mem/dimm.h b/include/hw/mem/dimm.h
index ae9ad2e..963b26d 100644
--- a/include/hw/mem/dimm.h
+++ b/include/hw/mem/dimm.h
@@ -75,11 +75,15 @@ typedef struct DimmBus {
 /**
  * DimmBusClass:
  * @parent_class: opaque parent class container
+ * @get_free_slot: returns a not occupied slot number. If @hint is provided,
+ * it tries to return slot specified by @hint if it's not busy or returns
+ * error in @errp.
  * @register_memory: map @DimmDevice into hot-plugable address space
  */
 typedef struct DimmBusClass {
     BusClass parent_class;
 
+    int (*get_free_slot)(DimmBus *bus, const int *hint, Error **errp);
     void (*register_memory)(DimmBus *bus, DimmDevice *dimm, Error **errp);
 } DimmBusClass;
 
-- 
1.7.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]