diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2007-07-26 13:41:03 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-26 14:35:17 -0400 |
commit | e2c9784325490c878b7f69aeec1bed98b288bd97 (patch) | |
tree | d474007607c713a30db818107ca0581269f059a2 /drivers/lguest/lguest_bus.c | |
parent | b2b47c214f4e85ce3968120d42e8b18eccb4f4e3 (diff) |
lguest: documentation III: Drivers
Documentation: The Drivers
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/lguest/lguest_bus.c')
-rw-r--r-- | drivers/lguest/lguest_bus.c | 72 |
1 files changed, 69 insertions, 3 deletions
diff --git a/drivers/lguest/lguest_bus.c b/drivers/lguest/lguest_bus.c index 9a22d199502e..55a7940ca732 100644 --- a/drivers/lguest/lguest_bus.c +++ b/drivers/lguest/lguest_bus.c | |||
@@ -46,6 +46,10 @@ static struct device_attribute lguest_dev_attrs[] = { | |||
46 | __ATTR_NULL | 46 | __ATTR_NULL |
47 | }; | 47 | }; |
48 | 48 | ||
49 | /*D:130 The generic bus infrastructure requires a function which says whether a | ||
50 | * device matches a driver. For us, it is simple: "struct lguest_driver" | ||
51 | * contains a "device_type" field which indicates what type of device it can | ||
52 | * handle, so we just cast the args and compare: */ | ||
49 | static int lguest_dev_match(struct device *_dev, struct device_driver *_drv) | 53 | static int lguest_dev_match(struct device *_dev, struct device_driver *_drv) |
50 | { | 54 | { |
51 | struct lguest_device *dev = container_of(_dev,struct lguest_device,dev); | 55 | struct lguest_device *dev = container_of(_dev,struct lguest_device,dev); |
@@ -53,6 +57,7 @@ static int lguest_dev_match(struct device *_dev, struct device_driver *_drv) | |||
53 | 57 | ||
54 | return (drv->device_type == lguest_devices[dev->index].type); | 58 | return (drv->device_type == lguest_devices[dev->index].type); |
55 | } | 59 | } |
60 | /*:*/ | ||
56 | 61 | ||
57 | struct lguest_bus { | 62 | struct lguest_bus { |
58 | struct bus_type bus; | 63 | struct bus_type bus; |
@@ -71,11 +76,24 @@ static struct lguest_bus lguest_bus = { | |||
71 | } | 76 | } |
72 | }; | 77 | }; |
73 | 78 | ||
79 | /*D:140 This is the callback which occurs once the bus infrastructure matches | ||
80 | * up a device and driver, ie. in response to add_lguest_device() calling | ||
81 | * device_register(), or register_lguest_driver() calling driver_register(). | ||
82 | * | ||
83 | * At the moment it's always the latter: the devices are added first, since | ||
84 | * scan_devices() is called from a "core_initcall", and the drivers themselves | ||
85 | * called later as a normal "initcall". But it would work the other way too. | ||
86 | * | ||
87 | * So now we have the happy couple, we add the status bit to indicate that we | ||
88 | * found a driver. If the driver truly loves the device, it will return | ||
89 | * happiness from its probe function (ok, perhaps this wasn't my greatest | ||
90 | * analogy), and we set the final "driver ok" bit so the Host sees it's all | ||
91 | * green. */ | ||
74 | static int lguest_dev_probe(struct device *_dev) | 92 | static int lguest_dev_probe(struct device *_dev) |
75 | { | 93 | { |
76 | int ret; | 94 | int ret; |
77 | struct lguest_device *dev = container_of(_dev,struct lguest_device,dev); | 95 | struct lguest_device*dev = container_of(_dev,struct lguest_device,dev); |
78 | struct lguest_driver *drv = container_of(dev->dev.driver, | 96 | struct lguest_driver*drv = container_of(dev->dev.driver, |
79 | struct lguest_driver, drv); | 97 | struct lguest_driver, drv); |
80 | 98 | ||
81 | lguest_devices[dev->index].status |= LGUEST_DEVICE_S_DRIVER; | 99 | lguest_devices[dev->index].status |= LGUEST_DEVICE_S_DRIVER; |
@@ -85,6 +103,10 @@ static int lguest_dev_probe(struct device *_dev) | |||
85 | return ret; | 103 | return ret; |
86 | } | 104 | } |
87 | 105 | ||
106 | /* The last part of the bus infrastructure is the function lguest drivers use | ||
107 | * to register themselves. Firstly, we do nothing if there's no lguest bus | ||
108 | * (ie. this is not a Guest), otherwise we fill in the embedded generic "struct | ||
109 | * driver" fields and call the generic driver_register(). */ | ||
88 | int register_lguest_driver(struct lguest_driver *drv) | 110 | int register_lguest_driver(struct lguest_driver *drv) |
89 | { | 111 | { |
90 | if (!lguest_devices) | 112 | if (!lguest_devices) |
@@ -97,12 +119,36 @@ int register_lguest_driver(struct lguest_driver *drv) | |||
97 | 119 | ||
98 | return driver_register(&drv->drv); | 120 | return driver_register(&drv->drv); |
99 | } | 121 | } |
122 | |||
123 | /* At the moment we build all the drivers into the kernel because they're so | ||
124 | * simple: 8144 bytes for all three of them as I type this. And as the console | ||
125 | * really needs to be built in, it's actually only 3527 bytes for the network | ||
126 | * and block drivers. | ||
127 | * | ||
128 | * If they get complex it will make sense for them to be modularized, so we | ||
129 | * need to explicitly export the symbol. | ||
130 | * | ||
131 | * I don't think non-GPL modules make sense, so it's a GPL-only export. | ||
132 | */ | ||
100 | EXPORT_SYMBOL_GPL(register_lguest_driver); | 133 | EXPORT_SYMBOL_GPL(register_lguest_driver); |
101 | 134 | ||
135 | /*D:120 This is the core of the lguest bus: actually adding a new device. | ||
136 | * It's a separate function because it's neater that way, and because an | ||
137 | * earlier version of the code supported hotplug and unplug. They were removed | ||
138 | * early on because they were never used. | ||
139 | * | ||
140 | * As Andrew Tridgell says, "Untested code is buggy code". | ||
141 | * | ||
142 | * It's worth reading this carefully: we start with an index into the array of | ||
143 | * "struct lguest_device_desc"s indicating the device which is new: */ | ||
102 | static void add_lguest_device(unsigned int index) | 144 | static void add_lguest_device(unsigned int index) |
103 | { | 145 | { |
104 | struct lguest_device *new; | 146 | struct lguest_device *new; |
105 | 147 | ||
148 | /* Each "struct lguest_device_desc" has a "status" field, which the | ||
149 | * Guest updates as the device is probed. In the worst case, the Host | ||
150 | * can look at these bits to tell what part of device setup failed, | ||
151 | * even if the console isn't available. */ | ||
106 | lguest_devices[index].status |= LGUEST_DEVICE_S_ACKNOWLEDGE; | 152 | lguest_devices[index].status |= LGUEST_DEVICE_S_ACKNOWLEDGE; |
107 | new = kmalloc(sizeof(struct lguest_device), GFP_KERNEL); | 153 | new = kmalloc(sizeof(struct lguest_device), GFP_KERNEL); |
108 | if (!new) { | 154 | if (!new) { |
@@ -111,12 +157,17 @@ static void add_lguest_device(unsigned int index) | |||
111 | return; | 157 | return; |
112 | } | 158 | } |
113 | 159 | ||
160 | /* The "struct lguest_device" setup is pretty straight-forward example | ||
161 | * code. */ | ||
114 | new->index = index; | 162 | new->index = index; |
115 | new->private = NULL; | 163 | new->private = NULL; |
116 | memset(&new->dev, 0, sizeof(new->dev)); | 164 | memset(&new->dev, 0, sizeof(new->dev)); |
117 | new->dev.parent = &lguest_bus.dev; | 165 | new->dev.parent = &lguest_bus.dev; |
118 | new->dev.bus = &lguest_bus.bus; | 166 | new->dev.bus = &lguest_bus.bus; |
119 | sprintf(new->dev.bus_id, "%u", index); | 167 | sprintf(new->dev.bus_id, "%u", index); |
168 | |||
169 | /* device_register() causes the bus infrastructure to look for a | ||
170 | * matching driver. */ | ||
120 | if (device_register(&new->dev) != 0) { | 171 | if (device_register(&new->dev) != 0) { |
121 | printk(KERN_EMERG "Cannot register lguest device %u\n", index); | 172 | printk(KERN_EMERG "Cannot register lguest device %u\n", index); |
122 | lguest_devices[index].status |= LGUEST_DEVICE_S_FAILED; | 173 | lguest_devices[index].status |= LGUEST_DEVICE_S_FAILED; |
@@ -124,6 +175,9 @@ static void add_lguest_device(unsigned int index) | |||
124 | } | 175 | } |
125 | } | 176 | } |
126 | 177 | ||
178 | /*D:110 scan_devices() simply iterates through the device array. The type 0 | ||
179 | * is reserved to mean "no device", and anything else means we have found a | ||
180 | * device: add it. */ | ||
127 | static void scan_devices(void) | 181 | static void scan_devices(void) |
128 | { | 182 | { |
129 | unsigned int i; | 183 | unsigned int i; |
@@ -133,12 +187,23 @@ static void scan_devices(void) | |||
133 | add_lguest_device(i); | 187 | add_lguest_device(i); |
134 | } | 188 | } |
135 | 189 | ||
190 | /*D:100 Fairly early in boot, lguest_bus_init() is called to set up the lguest | ||
191 | * bus. We check that we are a Guest by checking paravirt_ops.name: there are | ||
192 | * other ways of checking, but this seems most obvious to me. | ||
193 | * | ||
194 | * So we can access the array of "struct lguest_device_desc"s easily, we map | ||
195 | * that memory and store the pointer in the global "lguest_devices". Then we | ||
196 | * register the bus with the core. Doing two registrations seems clunky to me, | ||
197 | * but it seems to be the correct sysfs incantation. | ||
198 | * | ||
199 | * Finally we call scan_devices() which adds all the devices found in the | ||
200 | * "struct lguest_device_desc" array. */ | ||
136 | static int __init lguest_bus_init(void) | 201 | static int __init lguest_bus_init(void) |
137 | { | 202 | { |
138 | if (strcmp(paravirt_ops.name, "lguest") != 0) | 203 | if (strcmp(paravirt_ops.name, "lguest") != 0) |
139 | return 0; | 204 | return 0; |
140 | 205 | ||
141 | /* Devices are in page above top of "normal" mem. */ | 206 | /* Devices are in a single page above top of "normal" mem */ |
142 | lguest_devices = lguest_map(max_pfn<<PAGE_SHIFT, 1); | 207 | lguest_devices = lguest_map(max_pfn<<PAGE_SHIFT, 1); |
143 | 208 | ||
144 | if (bus_register(&lguest_bus.bus) != 0 | 209 | if (bus_register(&lguest_bus.bus) != 0 |
@@ -148,4 +213,5 @@ static int __init lguest_bus_init(void) | |||
148 | scan_devices(); | 213 | scan_devices(); |
149 | return 0; | 214 | return 0; |
150 | } | 215 | } |
216 | /* Do this after core stuff, before devices. */ | ||
151 | postcore_initcall(lguest_bus_init); | 217 | postcore_initcall(lguest_bus_init); |