summaryrefslogtreecommitdiff
path: root/src/devices/device.c
diff options
context:
space:
mode:
authorKyösti Mälkki <kyosti.malkki@gmail.com>2012-07-07 17:15:51 +0300
committerStefan Reinauer <stefan.reinauer@coreboot.org>2012-07-10 19:52:24 +0200
commita5650a4b4ac85722d772083761ffea32557774b4 (patch)
tree188f35747cf3f64d157bf7ef99e233d8dc6c27a2 /src/devices/device.c
parentda09be6328505ac4473aff48b8ef27b9986bfa22 (diff)
Use dev_lock for alloc_find_dev()
If threads called alloc_find_dev() with same device_path simultaneously, two device nodes could be allocated. This bug is not triggered by current code. Change-Id: Ifc87021c8d6f422901c5de5dd17392e3e2309afa Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com> Reviewed-on: http://review.coreboot.org/1188 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich <rminnich@gmail.com> Reviewed-by: Sven Schnelle <svens@stackframe.org>
Diffstat (limited to 'src/devices/device.c')
-rw-r--r--src/devices/device.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/src/devices/device.c b/src/devices/device.c
index ebac1a073e..fafa59924e 100644
--- a/src/devices/device.c
+++ b/src/devices/device.c
@@ -66,12 +66,10 @@ DECLARE_SPIN_LOCK(dev_lock)
*
* @see device_path
*/
-device_t alloc_dev(struct bus *parent, struct device_path *path)
+static device_t __alloc_dev(struct bus *parent, struct device_path *path)
{
device_t dev, child;
- spin_lock(&dev_lock);
-
/* Find the last child of our parent. */
for (child = parent->children; child && child->sibling; /* */ )
child = child->sibling;
@@ -99,11 +97,37 @@ device_t alloc_dev(struct bus *parent, struct device_path *path)
last_dev->next = dev;
last_dev = dev;
+ return dev;
+}
+
+device_t alloc_dev(struct bus *parent, struct device_path *path)
+{
+ device_t dev;
+ spin_lock(&dev_lock);
+ dev = __alloc_dev(parent, path);
spin_unlock(&dev_lock);
return dev;
}
/**
+ * See if a device structure already exists and if not allocate it.
+ *
+ * @param parent The bus to find the device on.
+ * @param path The relative path from the bus to the appropriate device.
+ * @return Pointer to a device structure for the device on bus at path.
+ */
+device_t alloc_find_dev(struct bus *parent, struct device_path *path)
+{
+ device_t child;
+ spin_lock(&dev_lock);
+ child = find_dev_path(parent, path);
+ if (!child)
+ child = __alloc_dev(parent, path);
+ spin_unlock(&dev_lock);
+ return child;
+}
+
+/**
* Round a number up to an alignment.
*
* @param val The starting value.