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 | } |
