[WATCHDOG] Documentation/watchdog/src/watchdog-simple.c: improve this code
[pandora-kernel.git] / drivers / lguest / lguest_bus.c
index 18d6ab2..5732978 100644 (file)
@@ -1,7 +1,11 @@
+/*P:050 Lguest guests use a very simple bus for devices.  It's a simple array
+ * of device descriptors contained just above the top of normal memory.  The
+ * lguest bus is 80% tedious boilerplate code. :*/
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/lguest_bus.h>
 #include <asm/io.h>
+#include <asm/paravirt.h>
 
 static ssize_t type_show(struct device *_dev,
                          struct device_attribute *attr, char *buf)
@@ -43,6 +47,10 @@ static struct device_attribute lguest_dev_attrs[] = {
        __ATTR_NULL
 };
 
+/*D:130 The generic bus infrastructure requires a function which says whether a
+ * device matches a driver.  For us, it is simple: "struct lguest_driver"
+ * contains a "device_type" field which indicates what type of device it can
+ * handle, so we just cast the args and compare: */
 static int lguest_dev_match(struct device *_dev, struct device_driver *_drv)
 {
        struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
@@ -50,6 +58,7 @@ static int lguest_dev_match(struct device *_dev, struct device_driver *_drv)
 
        return (drv->device_type == lguest_devices[dev->index].type);
 }
+/*:*/
 
 struct lguest_bus {
        struct bus_type bus;
@@ -68,11 +77,24 @@ static struct lguest_bus lguest_bus = {
        }
 };
 
+/*D:140 This is the callback which occurs once the bus infrastructure matches
+ * up a device and driver, ie. in response to add_lguest_device() calling
+ * device_register(), or register_lguest_driver() calling driver_register().
+ *
+ * At the moment it's always the latter: the devices are added first, since
+ * scan_devices() is called from a "core_initcall", and the drivers themselves
+ * called later as a normal "initcall".  But it would work the other way too.
+ *
+ * So now we have the happy couple, we add the status bit to indicate that we
+ * found a driver.  If the driver truly loves the device, it will return
+ * happiness from its probe function (ok, perhaps this wasn't my greatest
+ * analogy), and we set the final "driver ok" bit so the Host sees it's all
+ * green. */
 static int lguest_dev_probe(struct device *_dev)
 {
        int ret;
-       struct lguest_device *dev = container_of(_dev,struct lguest_device,dev);
-       struct lguest_driver *drv = container_of(dev->dev.driver,
+       struct lguest_device*dev = container_of(_dev,struct lguest_device,dev);
+       struct lguest_driver*drv = container_of(dev->dev.driver,
                                                struct lguest_driver, drv);
 
        lguest_devices[dev->index].status |= LGUEST_DEVICE_S_DRIVER;
@@ -82,6 +104,10 @@ static int lguest_dev_probe(struct device *_dev)
        return ret;
 }
 
+/* The last part of the bus infrastructure is the function lguest drivers use
+ * to register themselves.  Firstly, we do nothing if there's no lguest bus
+ * (ie. this is not a Guest), otherwise we fill in the embedded generic "struct
+ * driver" fields and call the generic driver_register(). */
 int register_lguest_driver(struct lguest_driver *drv)
 {
        if (!lguest_devices)
@@ -94,12 +120,36 @@ int register_lguest_driver(struct lguest_driver *drv)
 
        return driver_register(&drv->drv);
 }
+
+/* At the moment we build all the drivers into the kernel because they're so
+ * simple: 8144 bytes for all three of them as I type this.  And as the console
+ * really needs to be built in, it's actually only 3527 bytes for the network
+ * and block drivers.
+ *
+ * If they get complex it will make sense for them to be modularized, so we
+ * need to explicitly export the symbol.
+ *
+ * I don't think non-GPL modules make sense, so it's a GPL-only export.
+ */
 EXPORT_SYMBOL_GPL(register_lguest_driver);
 
+/*D:120 This is the core of the lguest bus: actually adding a new device.
+ * It's a separate function because it's neater that way, and because an
+ * earlier version of the code supported hotplug and unplug.  They were removed
+ * early on because they were never used.
+ *
+ * As Andrew Tridgell says, "Untested code is buggy code".
+ *
+ * It's worth reading this carefully: we start with an index into the array of
+ * "struct lguest_device_desc"s indicating the device which is new: */
 static void add_lguest_device(unsigned int index)
 {
        struct lguest_device *new;
 
+       /* Each "struct lguest_device_desc" has a "status" field, which the
+        * Guest updates as the device is probed.  In the worst case, the Host
+        * can look at these bits to tell what part of device setup failed,
+        * even if the console isn't available. */
        lguest_devices[index].status |= LGUEST_DEVICE_S_ACKNOWLEDGE;
        new = kmalloc(sizeof(struct lguest_device), GFP_KERNEL);
        if (!new) {
@@ -108,12 +158,17 @@ static void add_lguest_device(unsigned int index)
                return;
        }
 
+       /* The "struct lguest_device" setup is pretty straight-forward example
+        * code. */
        new->index = index;
        new->private = NULL;
        memset(&new->dev, 0, sizeof(new->dev));
        new->dev.parent = &lguest_bus.dev;
        new->dev.bus = &lguest_bus.bus;
        sprintf(new->dev.bus_id, "%u", index);
+
+       /* device_register() causes the bus infrastructure to look for a
+        * matching driver. */
        if (device_register(&new->dev) != 0) {
                printk(KERN_EMERG "Cannot register lguest device %u\n", index);
                lguest_devices[index].status |= LGUEST_DEVICE_S_FAILED;
@@ -121,6 +176,9 @@ static void add_lguest_device(unsigned int index)
        }
 }
 
+/*D:110 scan_devices() simply iterates through the device array.  The type 0
+ * is reserved to mean "no device", and anything else means we have found a
+ * device: add it. */
 static void scan_devices(void)
 {
        unsigned int i;
@@ -130,12 +188,23 @@ static void scan_devices(void)
                        add_lguest_device(i);
 }
 
+/*D:100 Fairly early in boot, lguest_bus_init() is called to set up the lguest
+ * bus.  We check that we are a Guest by checking paravirt_ops.name: there are
+ * other ways of checking, but this seems most obvious to me.
+ *
+ * So we can access the array of "struct lguest_device_desc"s easily, we map
+ * that memory and store the pointer in the global "lguest_devices".  Then we
+ * register the bus with the core.  Doing two registrations seems clunky to me,
+ * but it seems to be the correct sysfs incantation.
+ *
+ * Finally we call scan_devices() which adds all the devices found in the
+ * "struct lguest_device_desc" array. */
 static int __init lguest_bus_init(void)
 {
-       if (strcmp(paravirt_ops.name, "lguest") != 0)
+       if (strcmp(pv_info.name, "lguest") != 0)
                return 0;
 
-       /* Devices are in page above top of "normal" mem. */
+       /* Devices are in a single page above top of "normal" mem */
        lguest_devices = lguest_map(max_pfn<<PAGE_SHIFT, 1);
 
        if (bus_register(&lguest_bus.bus) != 0
@@ -145,4 +214,5 @@ static int __init lguest_bus_init(void)
        scan_devices();
        return 0;
 }
+/* Do this after core stuff, before devices. */
 postcore_initcall(lguest_bus_init);