Blame view

drivers/acpi/container.c 6.88 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  /*
   * acpi_container.c  - ACPI Generic Container Driver
   * ($Revision: )
   *
   * Copyright (C) 2004 Anil S Keshavamurthy (anil.s.keshavamurthy@intel.com)
   * Copyright (C) 2004 Keiichiro Tokunaga (tokunaga.keiich@jp.fujitsu.com)
   * Copyright (C) 2004 Motoyuki Ito (motoyuki@soft.fujitsu.com)
   * Copyright (C) 2004 Intel Corp.
   * Copyright (C) 2004 FUJITSU LIMITED
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or (at
   *  your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful, but
   *  WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   *  General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License along
   *  with this program; if not, write to the Free Software Foundation, Inc.,
   *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   */
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
32
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
34
35
36
37
  #include <linux/types.h>
  #include <linux/acpi.h>
  #include <acpi/acpi_bus.h>
  #include <acpi/acpi_drivers.h>
  #include <acpi/container.h>
a192a9580   Len Brown   ACPI: Move defini...
38
  #define PREFIX "ACPI: "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
40
41
42
43
  #define ACPI_CONTAINER_DEVICE_NAME	"ACPI container device"
  #define ACPI_CONTAINER_CLASS		"container"
  
  #define INSTALL_NOTIFY_HANDLER		1
  #define UNINSTALL_NOTIFY_HANDLER	2
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  #define _COMPONENT			ACPI_CONTAINER_COMPONENT
f52fd66d2   Len Brown   ACPI: clean up AC...
45
  ACPI_MODULE_NAME("container");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46

f52fd66d2   Len Brown   ACPI: clean up AC...
47
  MODULE_AUTHOR("Anil S Keshavamurthy");
7cda93e00   Len Brown   ACPI: delete extr...
48
  MODULE_DESCRIPTION("ACPI container driver");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
  MODULE_LICENSE("GPL");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
50
51
  static int acpi_container_add(struct acpi_device *device);
  static int acpi_container_remove(struct acpi_device *device, int type);
1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
52
53
54
55
56
57
58
  static const struct acpi_device_id container_device_ids[] = {
  	{"ACPI0004", 0},
  	{"PNP0A05", 0},
  	{"PNP0A06", 0},
  	{"", 0},
  };
  MODULE_DEVICE_TABLE(acpi, container_device_ids);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
59
  static struct acpi_driver acpi_container_driver = {
c2b6705b7   Len Brown   ACPI: fix acpi_dr...
60
  	.name = "container",
4be44fcd3   Len Brown   [ACPI] Lindent al...
61
  	.class = ACPI_CONTAINER_CLASS,
1ba90e3a8   Thomas Renninger   ACPI: autoload mo...
62
  	.ids = container_device_ids,
4be44fcd3   Len Brown   [ACPI] Lindent al...
63
64
65
66
  	.ops = {
  		.add = acpi_container_add,
  		.remove = acpi_container_remove,
  		},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
  /*******************************************************************/
4be44fcd3   Len Brown   [ACPI] Lindent al...
69
  static int is_device_present(acpi_handle handle)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
71
72
  	acpi_handle temp;
  	acpi_status status;
27663c585   Matthew Wilcox   ACPI: Change acpi...
73
  	unsigned long long sta;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
77
  
  	status = acpi_get_handle(handle, "_STA", &temp);
  	if (ACPI_FAILURE(status))
a0bd4ac49   Bjorn Helgaas   ACPI: Remove dupl...
78
  		return 1;	/* _STA not found, assume device present */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
  
  	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
  	if (ACPI_FAILURE(status))
d550d98d3   Patrick Mochel   ACPI: delete trac...
82
  		return 0;	/* Firmware error */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83

a0bd4ac49   Bjorn Helgaas   ACPI: Remove dupl...
84
  	return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
87
  }
  
  /*******************************************************************/
4be44fcd3   Len Brown   [ACPI] Lindent al...
88
  static int acpi_container_add(struct acpi_device *device)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
90
  {
  	struct acpi_container *container;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
  
  	if (!device) {
6468463ab   Len Brown   ACPI: un-export A...
93
94
  		printk(KERN_ERR PREFIX "device is NULL
  ");
d550d98d3   Patrick Mochel   ACPI: delete trac...
95
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
96
  	}
36bcbec7c   Burman Yan   ACPI: replace kma...
97
  	container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
4be44fcd3   Len Brown   [ACPI] Lindent al...
98
  	if (!container)
d550d98d3   Patrick Mochel   ACPI: delete trac...
99
  		return -ENOMEM;
4be44fcd3   Len Brown   [ACPI] Lindent al...
100

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
103
  	container->handle = device->handle;
  	strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
  	strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
db89b4f0d   Pavel Machek   ACPI: catch calls...
104
  	device->driver_data = container;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105

4be44fcd3   Len Brown   [ACPI] Lindent al...
106
107
108
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>
  ",
  			  acpi_device_name(device), acpi_device_bid(device)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109

d550d98d3   Patrick Mochel   ACPI: delete trac...
110
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
112
  static int acpi_container_remove(struct acpi_device *device, int type)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
114
115
  	acpi_status status = AE_OK;
  	struct acpi_container *pc = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116

50dd09697   Jan Engelhardt   ACPI: Remove unne...
117
  	pc = acpi_driver_data(device);
6044ec888   Jesper Juhl   [PATCH] kfree cle...
118
  	kfree(pc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
  	return status;
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
121
  static int container_device_add(struct acpi_device **device, acpi_handle handle)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
  {
  	acpi_handle phandle;
  	struct acpi_device *pdev;
  	int result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
  
  	if (acpi_get_parent(handle, &phandle)) {
d550d98d3   Patrick Mochel   ACPI: delete trac...
128
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
130
131
  	}
  
  	if (acpi_bus_get_device(phandle, &pdev)) {
d550d98d3   Patrick Mochel   ACPI: delete trac...
132
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
135
  	}
  
  	if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_DEVICE)) {
d550d98d3   Patrick Mochel   ACPI: delete trac...
136
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
  	}
3fb02738b   Rajesh Shah   [PATCH] acpi brid...
138
  	result = acpi_bus_start(*device);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139

d550d98d3   Patrick Mochel   ACPI: delete trac...
140
  	return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
142
  static void container_notify_cb(acpi_handle handle, u32 type, void *context)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
144
  	struct acpi_device *device = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
147
  	int result;
  	int present;
  	acpi_status status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
  
  	present = is_device_present(handle);
4be44fcd3   Len Brown   [ACPI] Lindent al...
150

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
154
  	switch (type) {
  	case ACPI_NOTIFY_BUS_CHECK:
  		/* Fall through */
  	case ACPI_NOTIFY_DEVICE_CHECK:
4d9391557   Frank Seidel   ACPI: add missing...
155
156
  		printk(KERN_WARNING "Container driver received %s event
  ",
4be44fcd3   Len Brown   [ACPI] Lindent al...
157
158
  		       (type == ACPI_NOTIFY_BUS_CHECK) ?
  		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
161
162
163
  		status = acpi_bus_get_device(handle, &device);
  		if (present) {
  			if (ACPI_FAILURE(status) || !device) {
  				result = container_device_add(&device, handle);
  				if (!result)
f883d9db0   Patrick Mochel   ACPI: convert to ...
164
  					kobject_uevent(&device->dev.kobj,
312c004d3   Kay Sievers   [PATCH] driver co...
165
  						       KOBJ_ONLINE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
  				else
4d9391557   Frank Seidel   ACPI: add missing...
167
168
169
  					printk(KERN_WARNING
  					       "Failed to add container
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
172
173
  			}
  		} else {
  			if (ACPI_SUCCESS(status)) {
  				/* device exist and this is a remove request */
f883d9db0   Patrick Mochel   ACPI: convert to ...
174
  				kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
178
179
  			}
  		}
  		break;
  	case ACPI_NOTIFY_EJECT_REQUEST:
  		if (!acpi_bus_get_device(handle, &device) && device) {
f883d9db0   Patrick Mochel   ACPI: convert to ...
180
  			kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
183
184
185
  		}
  		break;
  	default:
  		break;
  	}
d550d98d3   Patrick Mochel   ACPI: delete trac...
186
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187
188
189
190
  }
  
  static acpi_status
  container_walk_namespace_cb(acpi_handle handle,
4be44fcd3   Len Brown   [ACPI] Lindent al...
191
  			    u32 lvl, void *context, void **rv)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
193
  	char *hid = NULL;
4be44fcd3   Len Brown   [ACPI] Lindent al...
194
195
196
  	struct acpi_device_info *info;
  	acpi_status status;
  	int *action = context;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197

15b8dd53f   Bob Moore   ACPICA: Major upd...
198
199
  	status = acpi_get_object_info(handle, &info);
  	if (ACPI_FAILURE(status)) {
d550d98d3   Patrick Mochel   ACPI: delete trac...
200
  		return AE_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  	if (info->valid & ACPI_VALID_HID)
15b8dd53f   Bob Moore   ACPICA: Major upd...
203
  		hid = info->hardware_id.string;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
206
207
208
209
  
  	if (hid == NULL) {
  		goto end;
  	}
  
  	if (strcmp(hid, "ACPI0004") && strcmp(hid, "PNP0A05") &&
4be44fcd3   Len Brown   [ACPI] Lindent al...
210
  	    strcmp(hid, "PNP0A06")) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
212
  		goto end;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
213
  	switch (*action) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
  	case INSTALL_NOTIFY_HANDLER:
  		acpi_install_notify_handler(handle,
4be44fcd3   Len Brown   [ACPI] Lindent al...
216
217
  					    ACPI_SYSTEM_NOTIFY,
  					    container_notify_cb, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
218
219
220
  		break;
  	case UNINSTALL_NOTIFY_HANDLER:
  		acpi_remove_notify_handler(handle,
4be44fcd3   Len Brown   [ACPI] Lindent al...
221
222
  					   ACPI_SYSTEM_NOTIFY,
  					   container_notify_cb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
225
226
  		break;
  	default:
  		break;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
227
        end:
15b8dd53f   Bob Moore   ACPICA: Major upd...
228
  	kfree(info);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229

d550d98d3   Patrick Mochel   ACPI: delete trac...
230
  	return AE_OK;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
232
  static int __init acpi_container_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
234
235
  	int result = 0;
  	int action = INSTALL_NOTIFY_HANDLER;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
237
238
  
  	result = acpi_bus_register_driver(&acpi_container_driver);
  	if (result < 0) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
239
  		return (result);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
242
243
  	}
  
  	/* register notify handler to every container device */
  	acpi_walk_namespace(ACPI_TYPE_DEVICE,
4be44fcd3   Len Brown   [ACPI] Lindent al...
244
245
  			    ACPI_ROOT_OBJECT,
  			    ACPI_UINT32_MAX,
2263576cf   Lin Ming   ACPICA: Add post-...
246
  			    container_walk_namespace_cb, NULL, &action, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247

4be44fcd3   Len Brown   [ACPI] Lindent al...
248
  	return (0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
250
  static void __exit acpi_container_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
252
  	int action = UNINSTALL_NOTIFY_HANDLER;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
253

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
  
  	acpi_walk_namespace(ACPI_TYPE_DEVICE,
4be44fcd3   Len Brown   [ACPI] Lindent al...
256
257
  			    ACPI_ROOT_OBJECT,
  			    ACPI_UINT32_MAX,
2263576cf   Lin Ming   ACPICA: Add post-...
258
  			    container_walk_namespace_cb, NULL, &action, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
260
  
  	acpi_bus_unregister_driver(&acpi_container_driver);
d550d98d3   Patrick Mochel   ACPI: delete trac...
261
  	return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
262
263
264
265
  }
  
  module_init(acpi_container_init);
  module_exit(acpi_container_exit);