aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/bay.c
diff options
context:
space:
mode:
authorKristen Carlson Accardi <kristen.c.accardi@intel.com>2006-12-18 18:07:00 -0500
committerLen Brown <len.brown@intel.com>2007-02-03 01:11:59 -0500
commit2b167c01190b647c976e7fab312f2e3d3b3a785f (patch)
tree9fa00bbcc0ee6a820057a5fc2ab3a9327f218346 /drivers/acpi/bay.c
parente9dd85e5bdff2a3981dfaa55869ba920e985ea8a (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>
Diffstat (limited to 'drivers/acpi/bay.c')
-rw-r--r--drivers/acpi/bay.c87
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
49static void bay_notify(acpi_handle handle, u32 event, void *data); 49static void bay_notify(acpi_handle handle, u32 event, void *data);
50static int acpi_bay_add(struct acpi_device *device); 50static int acpi_bay_add(struct acpi_device *device);
51static int acpi_bay_remove(struct acpi_device *device, int type); 51static 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
71LIST_HEAD(drive_bays); 72LIST_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 */
140static 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}
147DEVICE_ATTR(present, S_IRUGO, show_present, NULL);
148
149/*
150 * write_eject - write method for "eject" file in sysfs
151 */
152static 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}
163DEVICE_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
219static int acpi_bay_add_fs(struct bay *bay) 247static 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
225static void acpi_bay_remove_fs(struct bay *bay) 267static 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
231static int bay_is_dock_device(acpi_handle handle) 276static 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
243static int bay_add(acpi_handle handle) 288static 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
338bay_add_err:
339 kfree(new_bay->name);
340 kfree(new_bay);
341 return -ENODEV;
278} 342}
279 343
280static int acpi_bay_remove(struct acpi_device *device, int type) 344static 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 }