diff options
author | Kristen Carlson Accardi <kristen.c.accardi@intel.com> | 2006-12-18 18:07:00 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-02-03 01:11:59 -0500 |
commit | 2b167c01190b647c976e7fab312f2e3d3b3a785f (patch) | |
tree | 9fa00bbcc0ee6a820057a5fc2ab3a9327f218346 | |
parent | e9dd85e5bdff2a3981dfaa55869ba920e985ea8a (diff) |
ACPI: bay: make bay a platform driver
Convert the bay driver to be a platform driver, so that we can have
sysfs entries.
Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r-- | drivers/acpi/bay.c | 87 |
1 files changed, 76 insertions, 11 deletions
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index 0c0a6204d167..3f0ae7d341e7 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <acpi/acpi_drivers.h> | 30 | #include <acpi/acpi_drivers.h> |
31 | #include <linux/seq_file.h> | 31 | #include <linux/seq_file.h> |
32 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> |
33 | #include <linux/platform_device.h> | ||
33 | 34 | ||
34 | #define ACPI_BAY_DRIVER_NAME "ACPI Removable Drive Bay Driver" | 35 | #define ACPI_BAY_DRIVER_NAME "ACPI Removable Drive Bay Driver" |
35 | 36 | ||
@@ -45,7 +46,6 @@ MODULE_LICENSE("GPL"); | |||
45 | struct acpi_buffer buffer = {sizeof(prefix), prefix};\ | 46 | struct acpi_buffer buffer = {sizeof(prefix), prefix};\ |
46 | acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\ | 47 | acpi_get_name(h, ACPI_FULL_PATHNAME, &buffer);\ |
47 | printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); } | 48 | printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); } |
48 | |||
49 | static void bay_notify(acpi_handle handle, u32 event, void *data); | 49 | static void bay_notify(acpi_handle handle, u32 event, void *data); |
50 | static int acpi_bay_add(struct acpi_device *device); | 50 | static int acpi_bay_add(struct acpi_device *device); |
51 | static int acpi_bay_remove(struct acpi_device *device, int type); | 51 | static int acpi_bay_remove(struct acpi_device *device, int type); |
@@ -66,6 +66,7 @@ struct bay { | |||
66 | acpi_handle handle; | 66 | acpi_handle handle; |
67 | char *name; | 67 | char *name; |
68 | struct list_head list; | 68 | struct list_head list; |
69 | struct platform_device *pdev; | ||
69 | }; | 70 | }; |
70 | 71 | ||
71 | LIST_HEAD(drive_bays); | 72 | LIST_HEAD(drive_bays); |
@@ -133,6 +134,33 @@ static void eject_device(acpi_handle handle) | |||
133 | pr_debug("Failed to evaluate _EJ0!\n"); | 134 | pr_debug("Failed to evaluate _EJ0!\n"); |
134 | } | 135 | } |
135 | 136 | ||
137 | /* | ||
138 | * show_present - read method for "present" file in sysfs | ||
139 | */ | ||
140 | static ssize_t show_present(struct device *dev, | ||
141 | struct device_attribute *attr, char *buf) | ||
142 | { | ||
143 | struct bay *bay = dev_get_drvdata(dev); | ||
144 | return snprintf(buf, PAGE_SIZE, "%d\n", bay_present(bay)); | ||
145 | |||
146 | } | ||
147 | DEVICE_ATTR(present, S_IRUGO, show_present, NULL); | ||
148 | |||
149 | /* | ||
150 | * write_eject - write method for "eject" file in sysfs | ||
151 | */ | ||
152 | static ssize_t write_eject(struct device *dev, struct device_attribute *attr, | ||
153 | const char *buf, size_t count) | ||
154 | { | ||
155 | struct bay *bay = dev_get_drvdata(dev); | ||
156 | |||
157 | if (!count) | ||
158 | return -EINVAL; | ||
159 | |||
160 | eject_device(bay->handle); | ||
161 | return count; | ||
162 | } | ||
163 | DEVICE_ATTR(eject, S_IWUSR, NULL, write_eject); | ||
136 | 164 | ||
137 | /** | 165 | /** |
138 | * is_ata - see if a device is an ata device | 166 | * is_ata - see if a device is an ata device |
@@ -218,14 +246,31 @@ static int acpi_bay_add(struct acpi_device *device) | |||
218 | 246 | ||
219 | static int acpi_bay_add_fs(struct bay *bay) | 247 | static int acpi_bay_add_fs(struct bay *bay) |
220 | { | 248 | { |
221 | if (!bay) | 249 | int ret; |
222 | return -EINVAL; | 250 | struct device *dev = &bay->pdev->dev; |
251 | |||
252 | ret = device_create_file(dev, &dev_attr_present); | ||
253 | if (ret) | ||
254 | goto add_fs_err; | ||
255 | ret = device_create_file(dev, &dev_attr_eject); | ||
256 | if (ret) { | ||
257 | device_remove_file(dev, &dev_attr_present); | ||
258 | goto add_fs_err; | ||
259 | } | ||
260 | return 0; | ||
261 | |||
262 | add_fs_err: | ||
263 | bay_dprintk(bay->handle, "Error adding sysfs files\n"); | ||
264 | return ret; | ||
223 | } | 265 | } |
224 | 266 | ||
225 | static void acpi_bay_remove_fs(struct bay *bay) | 267 | static void acpi_bay_remove_fs(struct bay *bay) |
226 | { | 268 | { |
227 | if (!bay) | 269 | struct device *dev = &bay->pdev->dev; |
228 | return; | 270 | |
271 | /* cleanup sysfs */ | ||
272 | device_remove_file(dev, &dev_attr_present); | ||
273 | device_remove_file(dev, &dev_attr_eject); | ||
229 | } | 274 | } |
230 | 275 | ||
231 | static int bay_is_dock_device(acpi_handle handle) | 276 | static int bay_is_dock_device(acpi_handle handle) |
@@ -240,10 +285,11 @@ static int bay_is_dock_device(acpi_handle handle) | |||
240 | return (is_dock_device(handle) || is_dock_device(parent)); | 285 | return (is_dock_device(handle) || is_dock_device(parent)); |
241 | } | 286 | } |
242 | 287 | ||
243 | static int bay_add(acpi_handle handle) | 288 | static int bay_add(acpi_handle handle, int id) |
244 | { | 289 | { |
245 | acpi_status status; | 290 | acpi_status status; |
246 | struct bay *new_bay; | 291 | struct bay *new_bay; |
292 | struct platform_device *pdev; | ||
247 | struct acpi_buffer nbuffer = {ACPI_ALLOCATE_BUFFER, NULL}; | 293 | struct acpi_buffer nbuffer = {ACPI_ALLOCATE_BUFFER, NULL}; |
248 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &nbuffer); | 294 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &nbuffer); |
249 | 295 | ||
@@ -252,12 +298,24 @@ static int bay_add(acpi_handle handle) | |||
252 | /* | 298 | /* |
253 | * Initialize bay device structure | 299 | * Initialize bay device structure |
254 | */ | 300 | */ |
255 | new_bay = kmalloc(GFP_ATOMIC, sizeof(*new_bay)); | 301 | new_bay = kzalloc(GFP_ATOMIC, sizeof(*new_bay)); |
256 | INIT_LIST_HEAD(&new_bay->list); | 302 | INIT_LIST_HEAD(&new_bay->list); |
257 | new_bay->handle = handle; | 303 | new_bay->handle = handle; |
258 | new_bay->name = (char *)nbuffer.pointer; | 304 | new_bay->name = (char *)nbuffer.pointer; |
259 | list_add(&new_bay->list, &drive_bays); | 305 | |
260 | acpi_bay_add_fs(new_bay); | 306 | /* initialize platform device stuff */ |
307 | pdev = platform_device_register_simple(ACPI_BAY_CLASS, id, NULL, 0); | ||
308 | if (pdev == NULL) { | ||
309 | printk(KERN_ERR PREFIX "Error registering bay device\n"); | ||
310 | goto bay_add_err; | ||
311 | } | ||
312 | new_bay->pdev = pdev; | ||
313 | platform_set_drvdata(pdev, new_bay); | ||
314 | |||
315 | if (acpi_bay_add_fs(new_bay)) { | ||
316 | platform_device_unregister(new_bay->pdev); | ||
317 | goto bay_add_err; | ||
318 | } | ||
261 | 319 | ||
262 | /* register for events on this device */ | 320 | /* register for events on this device */ |
263 | status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 321 | status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
@@ -273,8 +331,14 @@ static int bay_add(acpi_handle handle) | |||
273 | bay_dprintk(handle, "Is dependent on dock\n"); | 331 | bay_dprintk(handle, "Is dependent on dock\n"); |
274 | register_hotplug_dock_device(handle, bay_notify, new_bay); | 332 | register_hotplug_dock_device(handle, bay_notify, new_bay); |
275 | } | 333 | } |
334 | list_add(&new_bay->list, &drive_bays); | ||
276 | printk(KERN_INFO PREFIX "Bay [%s] Added\n", new_bay->name); | 335 | printk(KERN_INFO PREFIX "Bay [%s] Added\n", new_bay->name); |
277 | return 0; | 336 | return 0; |
337 | |||
338 | bay_add_err: | ||
339 | kfree(new_bay->name); | ||
340 | kfree(new_bay); | ||
341 | return -ENODEV; | ||
278 | } | 342 | } |
279 | 343 | ||
280 | static int acpi_bay_remove(struct acpi_device *device, int type) | 344 | static int acpi_bay_remove(struct acpi_device *device, int type) |
@@ -393,8 +457,8 @@ find_bay(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
393 | */ | 457 | */ |
394 | if (is_ejectable_bay(handle)) { | 458 | if (is_ejectable_bay(handle)) { |
395 | bay_dprintk(handle, "found ejectable bay"); | 459 | bay_dprintk(handle, "found ejectable bay"); |
396 | bay_add(handle); | 460 | if (!bay_add(handle, *count)) |
397 | (*count)++; | 461 | (*count)++; |
398 | } | 462 | } |
399 | return AE_OK; | 463 | return AE_OK; |
400 | } | 464 | } |
@@ -429,6 +493,7 @@ static void __exit bay_exit(void) | |||
429 | acpi_bay_remove_fs(bay); | 493 | acpi_bay_remove_fs(bay); |
430 | acpi_remove_notify_handler(bay->handle, ACPI_SYSTEM_NOTIFY, | 494 | acpi_remove_notify_handler(bay->handle, ACPI_SYSTEM_NOTIFY, |
431 | bay_notify); | 495 | bay_notify); |
496 | platform_device_unregister(bay->pdev); | ||
432 | kfree(bay->name); | 497 | kfree(bay->name); |
433 | kfree(bay); | 498 | kfree(bay); |
434 | } | 499 | } |