aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig22
-rw-r--r--drivers/misc/msi-laptop.c2
-rw-r--r--drivers/misc/sony-laptop.c204
-rw-r--r--drivers/misc/thinkpad_acpi.c321
-rw-r--r--drivers/misc/thinkpad_acpi.h38
5 files changed, 415 insertions, 172 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index df89367032c3..e0a1ff927a5b 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -149,6 +149,7 @@ config SONY_LAPTOP
149 tristate "Sony Laptop Extras" 149 tristate "Sony Laptop Extras"
150 depends on X86 && ACPI 150 depends on X86 && ACPI
151 select BACKLIGHT_CLASS_DEVICE 151 select BACKLIGHT_CLASS_DEVICE
152 depends on INPUT
152 ---help--- 153 ---help---
153 This mini-driver drives the SNC and SPIC devices present in the ACPI 154 This mini-driver drives the SNC and SPIC devices present in the ACPI
154 BIOS of the Sony Vaio laptops. 155 BIOS of the Sony Vaio laptops.
@@ -171,6 +172,7 @@ config THINKPAD_ACPI
171 select BACKLIGHT_CLASS_DEVICE 172 select BACKLIGHT_CLASS_DEVICE
172 select HWMON 173 select HWMON
173 select NVRAM 174 select NVRAM
175 depends on INPUT
174 ---help--- 176 ---help---
175 This is a driver for the IBM and Lenovo ThinkPad laptops. It adds 177 This is a driver for the IBM and Lenovo ThinkPad laptops. It adds
176 support for Fn-Fx key combinations, Bluetooth control, video 178 support for Fn-Fx key combinations, Bluetooth control, video
@@ -217,25 +219,5 @@ config THINKPAD_ACPI_BAY
217 219
218 If you are not sure, say Y here. 220 If you are not sure, say Y here.
219 221
220config THINKPAD_ACPI_INPUT_ENABLED
221 bool "Enable input layer support by default"
222 depends on THINKPAD_ACPI
223 default n
224 ---help---
225 This option enables thinkpad-acpi hot key handling over the input
226 layer at driver load time. When it is unset, the driver does not
227 enable hot key handling by default, and also starts up with a mostly
228 empty keymap.
229
230 This option should be enabled if you have a new enough HAL or other
231 userspace support that properly handles the thinkpad-acpi event
232 device. It auto-tunes the hot key support to those reported by the
233 firmware and enables it automatically.
234
235 If unsure, say N here to retain the old behaviour of ibm-acpi, and
236 thinkpad-acpi up to kernel 2.6.21: userspace will have to enable and
237 set up the thinkpad-acpi hot key handling using the sysfs interace
238 after loading the driver.
239
240 222
241endif # MISC_DEVICES 223endif # MISC_DEVICES
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c
index 932a415197b3..349be934db7c 100644
--- a/drivers/misc/msi-laptop.c
+++ b/drivers/misc/msi-laptop.c
@@ -353,7 +353,7 @@ static int __init msi_init(void)
353 if (IS_ERR(msibl_device)) 353 if (IS_ERR(msibl_device))
354 return PTR_ERR(msibl_device); 354 return PTR_ERR(msibl_device);
355 355
356 msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1, 356 msibl_device->props.max_brightness = MSI_LCD_LEVEL_MAX-1;
357 357
358 ret = platform_driver_register(&msipf_driver); 358 ret = platform_driver_register(&msipf_driver);
359 if (ret) 359 if (ret)
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index d38ddce592c0..f248080828f2 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -1173,7 +1173,8 @@ static struct acpi_driver sony_nc_driver = {
1173#define SONYPI_TYPE3_OFFSET 0x12 1173#define SONYPI_TYPE3_OFFSET 0x12
1174 1174
1175struct sony_pic_ioport { 1175struct sony_pic_ioport {
1176 struct acpi_resource_io io; 1176 struct acpi_resource_io io1;
1177 struct acpi_resource_io io2;
1177 struct list_head list; 1178 struct list_head list;
1178}; 1179};
1179 1180
@@ -1443,11 +1444,11 @@ static u8 sony_pic_call1(u8 dev)
1443{ 1444{
1444 u8 v1, v2; 1445 u8 v1, v2;
1445 1446
1446 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, 1447 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
1447 ITERATIONS_LONG); 1448 ITERATIONS_LONG);
1448 outb(dev, spic_dev.cur_ioport->io.minimum + 4); 1449 outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
1449 v1 = inb_p(spic_dev.cur_ioport->io.minimum + 4); 1450 v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4);
1450 v2 = inb_p(spic_dev.cur_ioport->io.minimum); 1451 v2 = inb_p(spic_dev.cur_ioport->io1.minimum);
1451 dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1); 1452 dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1);
1452 return v2; 1453 return v2;
1453} 1454}
@@ -1456,13 +1457,13 @@ static u8 sony_pic_call2(u8 dev, u8 fn)
1456{ 1457{
1457 u8 v1; 1458 u8 v1;
1458 1459
1459 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, 1460 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
1460 ITERATIONS_LONG); 1461 ITERATIONS_LONG);
1461 outb(dev, spic_dev.cur_ioport->io.minimum + 4); 1462 outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
1462 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, 1463 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2,
1463 ITERATIONS_LONG); 1464 ITERATIONS_LONG);
1464 outb(fn, spic_dev.cur_ioport->io.minimum); 1465 outb(fn, spic_dev.cur_ioport->io1.minimum);
1465 v1 = inb_p(spic_dev.cur_ioport->io.minimum); 1466 v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
1466 dprintk("sony_pic_call2: 0x%.4x\n", v1); 1467 dprintk("sony_pic_call2: 0x%.4x\n", v1);
1467 return v1; 1468 return v1;
1468} 1469}
@@ -1471,13 +1472,13 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
1471{ 1472{
1472 u8 v1; 1473 u8 v1;
1473 1474
1474 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG); 1475 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
1475 outb(dev, spic_dev.cur_ioport->io.minimum + 4); 1476 outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
1476 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG); 1477 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
1477 outb(fn, spic_dev.cur_ioport->io.minimum); 1478 outb(fn, spic_dev.cur_ioport->io1.minimum);
1478 wait_on_command(inb_p(spic_dev.cur_ioport->io.minimum + 4) & 2, ITERATIONS_LONG); 1479 wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
1479 outb(v, spic_dev.cur_ioport->io.minimum); 1480 outb(v, spic_dev.cur_ioport->io1.minimum);
1480 v1 = inb_p(spic_dev.cur_ioport->io.minimum); 1481 v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
1481 dprintk("sony_pic_call3: 0x%.4x\n", v1); 1482 dprintk("sony_pic_call3: 0x%.4x\n", v1);
1482 return v1; 1483 return v1;
1483} 1484}
@@ -2074,7 +2075,18 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
2074 2075
2075 switch (resource->type) { 2076 switch (resource->type) {
2076 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 2077 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
2078 {
2079 /* start IO enumeration */
2080 struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
2081 if (!ioport)
2082 return AE_ERROR;
2083
2084 list_add(&ioport->list, &dev->ioports);
2085 return AE_OK;
2086 }
2087
2077 case ACPI_RESOURCE_TYPE_END_DEPENDENT: 2088 case ACPI_RESOURCE_TYPE_END_DEPENDENT:
2089 /* end IO enumeration */
2078 return AE_OK; 2090 return AE_OK;
2079 2091
2080 case ACPI_RESOURCE_TYPE_IRQ: 2092 case ACPI_RESOURCE_TYPE_IRQ:
@@ -2101,7 +2113,7 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
2101 if (!interrupt) 2113 if (!interrupt)
2102 return AE_ERROR; 2114 return AE_ERROR;
2103 2115
2104 list_add_tail(&interrupt->list, &dev->interrupts); 2116 list_add(&interrupt->list, &dev->interrupts);
2105 interrupt->irq.triggering = p->triggering; 2117 interrupt->irq.triggering = p->triggering;
2106 interrupt->irq.polarity = p->polarity; 2118 interrupt->irq.polarity = p->polarity;
2107 interrupt->irq.sharable = p->sharable; 2119 interrupt->irq.sharable = p->sharable;
@@ -2113,18 +2125,27 @@ sony_pic_read_possible_resource(struct acpi_resource *resource, void *context)
2113 case ACPI_RESOURCE_TYPE_IO: 2125 case ACPI_RESOURCE_TYPE_IO:
2114 { 2126 {
2115 struct acpi_resource_io *io = &resource->data.io; 2127 struct acpi_resource_io *io = &resource->data.io;
2116 struct sony_pic_ioport *ioport = NULL; 2128 struct sony_pic_ioport *ioport =
2129 list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
2117 if (!io) { 2130 if (!io) {
2118 dprintk("Blank IO resource\n"); 2131 dprintk("Blank IO resource\n");
2119 return AE_OK; 2132 return AE_OK;
2120 } 2133 }
2121 2134
2122 ioport = kzalloc(sizeof(*ioport), GFP_KERNEL); 2135 if (!ioport->io1.minimum) {
2123 if (!ioport) 2136 memcpy(&ioport->io1, io, sizeof(*io));
2137 dprintk("IO1 at 0x%.4x (0x%.2x)\n", ioport->io1.minimum,
2138 ioport->io1.address_length);
2139 }
2140 else if (!ioport->io2.minimum) {
2141 memcpy(&ioport->io2, io, sizeof(*io));
2142 dprintk("IO2 at 0x%.4x (0x%.2x)\n", ioport->io2.minimum,
2143 ioport->io2.address_length);
2144 }
2145 else {
2146 printk(KERN_ERR DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n");
2124 return AE_ERROR; 2147 return AE_ERROR;
2125 2148 }
2126 list_add_tail(&ioport->list, &dev->ioports);
2127 memcpy(&ioport->io, io, sizeof(*io));
2128 return AE_OK; 2149 return AE_OK;
2129 } 2150 }
2130 default: 2151 default:
@@ -2199,10 +2220,22 @@ static int sony_pic_enable(struct acpi_device *device,
2199{ 2220{
2200 acpi_status status; 2221 acpi_status status;
2201 int result = 0; 2222 int result = 0;
2223 /* Type 1 resource layout is:
2224 * IO
2225 * IO
2226 * IRQNoFlags
2227 * End
2228 *
2229 * Type 2 and 3 resource layout is:
2230 * IO
2231 * IRQNoFlags
2232 * End
2233 */
2202 struct { 2234 struct {
2203 struct acpi_resource io_res; 2235 struct acpi_resource res1;
2204 struct acpi_resource irq_res; 2236 struct acpi_resource res2;
2205 struct acpi_resource end; 2237 struct acpi_resource res3;
2238 struct acpi_resource res4;
2206 } *resource; 2239 } *resource;
2207 struct acpi_buffer buffer = { 0, NULL }; 2240 struct acpi_buffer buffer = { 0, NULL };
2208 2241
@@ -2217,21 +2250,49 @@ static int sony_pic_enable(struct acpi_device *device,
2217 buffer.length = sizeof(*resource) + 1; 2250 buffer.length = sizeof(*resource) + 1;
2218 buffer.pointer = resource; 2251 buffer.pointer = resource;
2219 2252
2220 /* setup io resource */ 2253 /* setup Type 1 resources */
2221 resource->io_res.type = ACPI_RESOURCE_TYPE_IO; 2254 if (spic_dev.model == SONYPI_DEVICE_TYPE1) {
2222 resource->io_res.length = sizeof(struct acpi_resource);
2223 memcpy(&resource->io_res.data.io, &ioport->io,
2224 sizeof(struct acpi_resource_io));
2225 2255
2226 /* setup irq resource */ 2256 /* setup io resources */
2227 resource->irq_res.type = ACPI_RESOURCE_TYPE_IRQ; 2257 resource->res1.type = ACPI_RESOURCE_TYPE_IO;
2228 resource->irq_res.length = sizeof(struct acpi_resource); 2258 resource->res1.length = sizeof(struct acpi_resource);
2229 memcpy(&resource->irq_res.data.irq, &irq->irq, 2259 memcpy(&resource->res1.data.io, &ioport->io1,
2230 sizeof(struct acpi_resource_irq)); 2260 sizeof(struct acpi_resource_io));
2231 /* we requested a shared irq */
2232 resource->irq_res.data.irq.sharable = ACPI_SHARED;
2233 2261
2234 resource->end.type = ACPI_RESOURCE_TYPE_END_TAG; 2262 resource->res2.type = ACPI_RESOURCE_TYPE_IO;
2263 resource->res2.length = sizeof(struct acpi_resource);
2264 memcpy(&resource->res2.data.io, &ioport->io2,
2265 sizeof(struct acpi_resource_io));
2266
2267 /* setup irq resource */
2268 resource->res3.type = ACPI_RESOURCE_TYPE_IRQ;
2269 resource->res3.length = sizeof(struct acpi_resource);
2270 memcpy(&resource->res3.data.irq, &irq->irq,
2271 sizeof(struct acpi_resource_irq));
2272 /* we requested a shared irq */
2273 resource->res3.data.irq.sharable = ACPI_SHARED;
2274
2275 resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG;
2276
2277 }
2278 /* setup Type 2/3 resources */
2279 else {
2280 /* setup io resource */
2281 resource->res1.type = ACPI_RESOURCE_TYPE_IO;
2282 resource->res1.length = sizeof(struct acpi_resource);
2283 memcpy(&resource->res1.data.io, &ioport->io1,
2284 sizeof(struct acpi_resource_io));
2285
2286 /* setup irq resource */
2287 resource->res2.type = ACPI_RESOURCE_TYPE_IRQ;
2288 resource->res2.length = sizeof(struct acpi_resource);
2289 memcpy(&resource->res2.data.irq, &irq->irq,
2290 sizeof(struct acpi_resource_irq));
2291 /* we requested a shared irq */
2292 resource->res2.data.irq.sharable = ACPI_SHARED;
2293
2294 resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG;
2295 }
2235 2296
2236 /* Attempt to set the resource */ 2297 /* Attempt to set the resource */
2237 dprintk("Evaluating _SRS\n"); 2298 dprintk("Evaluating _SRS\n");
@@ -2239,7 +2300,7 @@ static int sony_pic_enable(struct acpi_device *device,
2239 2300
2240 /* check for total failure */ 2301 /* check for total failure */
2241 if (ACPI_FAILURE(status)) { 2302 if (ACPI_FAILURE(status)) {
2242 printk(KERN_ERR DRV_PFX "Error evaluating _SRS"); 2303 printk(KERN_ERR DRV_PFX "Error evaluating _SRS\n");
2243 result = -ENODEV; 2304 result = -ENODEV;
2244 goto end; 2305 goto end;
2245 } 2306 }
@@ -2268,11 +2329,14 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
2268 2329
2269 struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; 2330 struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;
2270 2331
2271 ev = inb_p(dev->cur_ioport->io.minimum); 2332 ev = inb_p(dev->cur_ioport->io1.minimum);
2272 data_mask = inb_p(dev->cur_ioport->io.minimum + dev->evport_offset); 2333 if (dev->cur_ioport->io2.minimum)
2334 data_mask = inb_p(dev->cur_ioport->io2.minimum);
2335 else
2336 data_mask = inb_p(dev->cur_ioport->io1.minimum + dev->evport_offset);
2273 2337
2274 dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", 2338 dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
2275 ev, data_mask, dev->cur_ioport->io.minimum, dev->evport_offset); 2339 ev, data_mask, dev->cur_ioport->io1.minimum, dev->evport_offset);
2276 2340
2277 if (ev == 0x00 || ev == 0xff) 2341 if (ev == 0x00 || ev == 0xff)
2278 return IRQ_HANDLED; 2342 return IRQ_HANDLED;
@@ -2323,8 +2387,11 @@ static int sony_pic_remove(struct acpi_device *device, int type)
2323 } 2387 }
2324 2388
2325 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev); 2389 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
2326 release_region(spic_dev.cur_ioport->io.minimum, 2390 release_region(spic_dev.cur_ioport->io1.minimum,
2327 spic_dev.cur_ioport->io.address_length); 2391 spic_dev.cur_ioport->io1.address_length);
2392 if (spic_dev.cur_ioport->io2.minimum)
2393 release_region(spic_dev.cur_ioport->io2.minimum,
2394 spic_dev.cur_ioport->io2.address_length);
2328 2395
2329 sonypi_compat_exit(); 2396 sonypi_compat_exit();
2330 2397
@@ -2397,14 +2464,36 @@ static int sony_pic_add(struct acpi_device *device)
2397 goto err_remove_input; 2464 goto err_remove_input;
2398 2465
2399 /* request io port */ 2466 /* request io port */
2400 list_for_each_entry(io, &spic_dev.ioports, list) { 2467 list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
2401 if (request_region(io->io.minimum, io->io.address_length, 2468 if (request_region(io->io1.minimum, io->io1.address_length,
2402 "Sony Programable I/O Device")) { 2469 "Sony Programable I/O Device")) {
2403 dprintk("I/O port: 0x%.4x (0x%.4x) + 0x%.2x\n", 2470 dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
2404 io->io.minimum, io->io.maximum, 2471 io->io1.minimum, io->io1.maximum,
2405 io->io.address_length); 2472 io->io1.address_length);
2406 spic_dev.cur_ioport = io; 2473 /* Type 1 have 2 ioports */
2407 break; 2474 if (io->io2.minimum) {
2475 if (request_region(io->io2.minimum,
2476 io->io2.address_length,
2477 "Sony Programable I/O Device")) {
2478 dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
2479 io->io2.minimum, io->io2.maximum,
2480 io->io2.address_length);
2481 spic_dev.cur_ioport = io;
2482 break;
2483 }
2484 else {
2485 dprintk("Unable to get I/O port2: "
2486 "0x%.4x (0x%.4x) + 0x%.2x\n",
2487 io->io2.minimum, io->io2.maximum,
2488 io->io2.address_length);
2489 release_region(io->io1.minimum,
2490 io->io1.address_length);
2491 }
2492 }
2493 else {
2494 spic_dev.cur_ioport = io;
2495 break;
2496 }
2408 } 2497 }
2409 } 2498 }
2410 if (!spic_dev.cur_ioport) { 2499 if (!spic_dev.cur_ioport) {
@@ -2414,7 +2503,7 @@ static int sony_pic_add(struct acpi_device *device)
2414 } 2503 }
2415 2504
2416 /* request IRQ */ 2505 /* request IRQ */
2417 list_for_each_entry(irq, &spic_dev.interrupts, list) { 2506 list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
2418 if (!request_irq(irq->irq.interrupts[0], sony_pic_irq, 2507 if (!request_irq(irq->irq.interrupts[0], sony_pic_irq,
2419 IRQF_SHARED, "sony-laptop", &spic_dev)) { 2508 IRQF_SHARED, "sony-laptop", &spic_dev)) {
2420 dprintk("IRQ: %d - triggering: %d - " 2509 dprintk("IRQ: %d - triggering: %d - "
@@ -2462,8 +2551,11 @@ err_free_irq:
2462 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev); 2551 free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
2463 2552
2464err_release_region: 2553err_release_region:
2465 release_region(spic_dev.cur_ioport->io.minimum, 2554 release_region(spic_dev.cur_ioport->io1.minimum,
2466 spic_dev.cur_ioport->io.address_length); 2555 spic_dev.cur_ioport->io1.address_length);
2556 if (spic_dev.cur_ioport->io2.minimum)
2557 release_region(spic_dev.cur_ioport->io2.minimum,
2558 spic_dev.cur_ioport->io2.address_length);
2467 2559
2468err_remove_compat: 2560err_remove_compat:
2469 sonypi_compat_exit(); 2561 sonypi_compat_exit();
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index bb8956d0c104..37891a8c030a 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -21,8 +21,8 @@
21 * 02110-1301, USA. 21 * 02110-1301, USA.
22 */ 22 */
23 23
24#define IBM_VERSION "0.15" 24#define IBM_VERSION "0.16"
25#define TPACPI_SYSFS_VERSION 0x010000 25#define TPACPI_SYSFS_VERSION 0x020000
26 26
27/* 27/*
28 * Changelog: 28 * Changelog:
@@ -117,6 +117,12 @@ IBM_BIOS_MODULE_ALIAS("K[U,X-Z]");
117 117
118#define __unused __attribute__ ((unused)) 118#define __unused __attribute__ ((unused))
119 119
120static enum {
121 TPACPI_LIFE_INIT = 0,
122 TPACPI_LIFE_RUNNING,
123 TPACPI_LIFE_EXITING,
124} tpacpi_lifecycle;
125
120/**************************************************************************** 126/****************************************************************************
121 **************************************************************************** 127 ****************************************************************************
122 * 128 *
@@ -342,6 +348,9 @@ static void dispatch_acpi_notify(acpi_handle handle, u32 event, void *data)
342{ 348{
343 struct ibm_struct *ibm = data; 349 struct ibm_struct *ibm = data;
344 350
351 if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
352 return;
353
345 if (!ibm || !ibm->acpi || !ibm->acpi->notify) 354 if (!ibm || !ibm->acpi || !ibm->acpi->notify)
346 return; 355 return;
347 356
@@ -517,8 +526,10 @@ static char *next_cmd(char **cmds)
517 ****************************************************************************/ 526 ****************************************************************************/
518 527
519static struct platform_device *tpacpi_pdev; 528static struct platform_device *tpacpi_pdev;
529static struct platform_device *tpacpi_sensors_pdev;
520static struct class_device *tpacpi_hwmon; 530static struct class_device *tpacpi_hwmon;
521static struct input_dev *tpacpi_inputdev; 531static struct input_dev *tpacpi_inputdev;
532static struct mutex tpacpi_inputdev_send_mutex;
522 533
523 534
524static int tpacpi_resume_handler(struct platform_device *pdev) 535static int tpacpi_resume_handler(struct platform_device *pdev)
@@ -543,6 +554,12 @@ static struct platform_driver tpacpi_pdriver = {
543 .resume = tpacpi_resume_handler, 554 .resume = tpacpi_resume_handler,
544}; 555};
545 556
557static struct platform_driver tpacpi_hwmon_pdriver = {
558 .driver = {
559 .name = IBM_HWMON_DRVR_NAME,
560 .owner = THIS_MODULE,
561 },
562};
546 563
547/************************************************************************* 564/*************************************************************************
548 * thinkpad-acpi driver attributes 565 * thinkpad-acpi driver attributes
@@ -692,6 +709,8 @@ static int parse_strtoul(const char *buf,
692{ 709{
693 char *endp; 710 char *endp;
694 711
712 while (*buf && isspace(*buf))
713 buf++;
695 *value = simple_strtoul(buf, &endp, 0); 714 *value = simple_strtoul(buf, &endp, 0);
696 while (*endp && isspace(*endp)) 715 while (*endp && isspace(*endp))
697 endp++; 716 endp++;
@@ -906,9 +925,26 @@ static ssize_t hotkey_radio_sw_show(struct device *dev,
906static struct device_attribute dev_attr_hotkey_radio_sw = 925static struct device_attribute dev_attr_hotkey_radio_sw =
907 __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL); 926 __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL);
908 927
928/* sysfs hotkey report_mode -------------------------------------------- */
929static ssize_t hotkey_report_mode_show(struct device *dev,
930 struct device_attribute *attr,
931 char *buf)
932{
933 return snprintf(buf, PAGE_SIZE, "%d\n",
934 (hotkey_report_mode != 0) ? hotkey_report_mode : 1);
935}
936
937static struct device_attribute dev_attr_hotkey_report_mode =
938 __ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL);
939
909/* --------------------------------------------------------------------- */ 940/* --------------------------------------------------------------------- */
910 941
911static struct attribute *hotkey_mask_attributes[] = { 942static struct attribute *hotkey_attributes[] __initdata = {
943 &dev_attr_hotkey_enable.attr,
944 &dev_attr_hotkey_report_mode.attr,
945};
946
947static struct attribute *hotkey_mask_attributes[] __initdata = {
912 &dev_attr_hotkey_mask.attr, 948 &dev_attr_hotkey_mask.attr,
913 &dev_attr_hotkey_bios_enabled.attr, 949 &dev_attr_hotkey_bios_enabled.attr,
914 &dev_attr_hotkey_bios_mask.attr, 950 &dev_attr_hotkey_bios_mask.attr,
@@ -972,6 +1008,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
972 1008
973 int res, i; 1009 int res, i;
974 int status; 1010 int status;
1011 int hkeyv;
975 1012
976 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); 1013 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n");
977 1014
@@ -987,27 +1024,45 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
987 str_supported(tp_features.hotkey)); 1024 str_supported(tp_features.hotkey));
988 1025
989 if (tp_features.hotkey) { 1026 if (tp_features.hotkey) {
990 hotkey_dev_attributes = create_attr_set(7, NULL); 1027 hotkey_dev_attributes = create_attr_set(8, NULL);
991 if (!hotkey_dev_attributes) 1028 if (!hotkey_dev_attributes)
992 return -ENOMEM; 1029 return -ENOMEM;
993 res = add_to_attr_set(hotkey_dev_attributes, 1030 res = add_many_to_attr_set(hotkey_dev_attributes,
994 &dev_attr_hotkey_enable.attr); 1031 hotkey_attributes,
1032 ARRAY_SIZE(hotkey_attributes));
995 if (res) 1033 if (res)
996 return res; 1034 return res;
997 1035
998 /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, 1036 /* mask not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
999 A30, R30, R31, T20-22, X20-21, X22-24 */ 1037 A30, R30, R31, T20-22, X20-21, X22-24. Detected by checking
1000 tp_features.hotkey_mask = 1038 for HKEY interface version 0x100 */
1001 acpi_evalf(hkey_handle, NULL, "DHKN", "qv"); 1039 if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) {
1040 if ((hkeyv >> 8) != 1) {
1041 printk(IBM_ERR "unknown version of the "
1042 "HKEY interface: 0x%x\n", hkeyv);
1043 printk(IBM_ERR "please report this to %s\n",
1044 IBM_MAIL);
1045 } else {
1046 /*
1047 * MHKV 0x100 in A31, R40, R40e,
1048 * T4x, X31, and later
1049 * */
1050 tp_features.hotkey_mask = 1;
1051 }
1052 }
1002 1053
1003 vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", 1054 vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n",
1004 str_supported(tp_features.hotkey_mask)); 1055 str_supported(tp_features.hotkey_mask));
1005 1056
1006 if (tp_features.hotkey_mask) { 1057 if (tp_features.hotkey_mask) {
1007 /* MHKA available in A31, R40, R40e, T4x, X31, and later */
1008 if (!acpi_evalf(hkey_handle, &hotkey_all_mask, 1058 if (!acpi_evalf(hkey_handle, &hotkey_all_mask,
1009 "MHKA", "qd")) 1059 "MHKA", "qd")) {
1060 printk(IBM_ERR
1061 "missing MHKA handler, "
1062 "please report this to %s\n",
1063 IBM_MAIL);
1010 hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */ 1064 hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */
1065 }
1011 } 1066 }
1012 1067
1013 res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); 1068 res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask);
@@ -1055,11 +1110,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
1055 TPACPI_HOTKEY_MAP_SIZE); 1110 TPACPI_HOTKEY_MAP_SIZE);
1056 } 1111 }
1057 1112
1058#ifndef CONFIG_THINKPAD_ACPI_INPUT_ENABLED
1059 for (i = 0; i < 12; i++)
1060 hotkey_keycode_map[i] = KEY_UNKNOWN;
1061#endif /* ! CONFIG_THINKPAD_ACPI_INPUT_ENABLED */
1062
1063 set_bit(EV_KEY, tpacpi_inputdev->evbit); 1113 set_bit(EV_KEY, tpacpi_inputdev->evbit);
1064 set_bit(EV_MSC, tpacpi_inputdev->evbit); 1114 set_bit(EV_MSC, tpacpi_inputdev->evbit);
1065 set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); 1115 set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
@@ -1081,14 +1131,17 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
1081 set_bit(SW_RADIO, tpacpi_inputdev->swbit); 1131 set_bit(SW_RADIO, tpacpi_inputdev->swbit);
1082 } 1132 }
1083 1133
1084#ifdef CONFIG_THINKPAD_ACPI_INPUT_ENABLED
1085 dbg_printk(TPACPI_DBG_INIT, 1134 dbg_printk(TPACPI_DBG_INIT,
1086 "enabling hot key handling\n"); 1135 "enabling hot key handling\n");
1087 res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask) 1136 res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask)
1088 | hotkey_orig_mask); 1137 | hotkey_orig_mask);
1089 if (res) 1138 if (res)
1090 return res; 1139 return res;
1091#endif /* CONFIG_THINKPAD_ACPI_INPUT_ENABLED */ 1140
1141 dbg_printk(TPACPI_DBG_INIT,
1142 "legacy hot key reporting over procfs %s\n",
1143 (hotkey_report_mode < 2) ?
1144 "enabled" : "disabled");
1092 } 1145 }
1093 1146
1094 return (tp_features.hotkey)? 0 : 1; 1147 return (tp_features.hotkey)? 0 : 1;
@@ -1115,6 +1168,8 @@ static void tpacpi_input_send_key(unsigned int scancode,
1115 unsigned int keycode) 1168 unsigned int keycode)
1116{ 1169{
1117 if (keycode != KEY_RESERVED) { 1170 if (keycode != KEY_RESERVED) {
1171 mutex_lock(&tpacpi_inputdev_send_mutex);
1172
1118 input_report_key(tpacpi_inputdev, keycode, 1); 1173 input_report_key(tpacpi_inputdev, keycode, 1);
1119 if (keycode == KEY_UNKNOWN) 1174 if (keycode == KEY_UNKNOWN)
1120 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, 1175 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
@@ -1126,6 +1181,8 @@ static void tpacpi_input_send_key(unsigned int scancode,
1126 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, 1181 input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN,
1127 scancode); 1182 scancode);
1128 input_sync(tpacpi_inputdev); 1183 input_sync(tpacpi_inputdev);
1184
1185 mutex_unlock(&tpacpi_inputdev_send_mutex);
1129 } 1186 }
1130} 1187}
1131 1188
@@ -1133,67 +1190,102 @@ static void tpacpi_input_send_radiosw(void)
1133{ 1190{
1134 int wlsw; 1191 int wlsw;
1135 1192
1136 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) 1193 mutex_lock(&tpacpi_inputdev_send_mutex);
1194
1195 if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) {
1137 input_report_switch(tpacpi_inputdev, 1196 input_report_switch(tpacpi_inputdev,
1138 SW_RADIO, !!wlsw); 1197 SW_RADIO, !!wlsw);
1198 input_sync(tpacpi_inputdev);
1199 }
1200
1201 mutex_unlock(&tpacpi_inputdev_send_mutex);
1139} 1202}
1140 1203
1141static void hotkey_notify(struct ibm_struct *ibm, u32 event) 1204static void hotkey_notify(struct ibm_struct *ibm, u32 event)
1142{ 1205{
1143 u32 hkey; 1206 u32 hkey;
1144 unsigned int keycode, scancode; 1207 unsigned int keycode, scancode;
1145 int sendacpi = 1; 1208 int send_acpi_ev;
1146 1209 int ignore_acpi_ev;
1147 if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { 1210
1148 if (tpacpi_inputdev->users > 0) { 1211 if (event != 0x80) {
1149 switch (hkey >> 12) { 1212 printk(IBM_ERR "unknown HKEY notification event %d\n", event);
1150 case 1: 1213 /* forward it to userspace, maybe it knows how to handle it */
1151 /* 0x1000-0x1FFF: key presses */ 1214 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
1152 scancode = hkey & 0xfff; 1215 ibm->acpi->device->dev.bus_id,
1153 if (scancode > 0 && scancode < 0x21) { 1216 event, 0);
1154 scancode--; 1217 return;
1155 keycode = hotkey_keycode_map[scancode]; 1218 }
1156 tpacpi_input_send_key(scancode, keycode); 1219
1157 sendacpi = (keycode == KEY_RESERVED 1220 while (1) {
1158 || keycode == KEY_UNKNOWN); 1221 if (!acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) {
1159 } else { 1222 printk(IBM_ERR "failed to retrieve HKEY event\n");
1160 printk(IBM_ERR 1223 return;
1161 "hotkey 0x%04x out of range for keyboard map\n", 1224 }
1162 hkey); 1225
1163 } 1226 if (hkey == 0) {
1164 break; 1227 /* queue empty */
1165 case 5: 1228 return;
1166 /* 0x5000-0x5FFF: LID */ 1229 }
1167 /* we don't handle it through this path, just 1230
1168 * eat up known LID events */ 1231 send_acpi_ev = 0;
1169 if (hkey != 0x5001 && hkey != 0x5002) { 1232 ignore_acpi_ev = 0;
1170 printk(IBM_ERR 1233
1171 "unknown LID-related hotkey event: 0x%04x\n", 1234 switch (hkey >> 12) {
1172 hkey); 1235 case 1:
1173 } 1236 /* 0x1000-0x1FFF: key presses */
1237 scancode = hkey & 0xfff;
1238 if (scancode > 0 && scancode < 0x21) {
1239 scancode--;
1240 keycode = hotkey_keycode_map[scancode];
1241 tpacpi_input_send_key(scancode, keycode);
1242 } else {
1243 printk(IBM_ERR
1244 "hotkey 0x%04x out of range for keyboard map\n",
1245 hkey);
1246 send_acpi_ev = 1;
1247 }
1248 break;
1249 case 5:
1250 /* 0x5000-0x5FFF: LID */
1251 /* we don't handle it through this path, just
1252 * eat up known LID events */
1253 if (hkey != 0x5001 && hkey != 0x5002) {
1254 printk(IBM_ERR
1255 "unknown LID-related HKEY event: 0x%04x\n",
1256 hkey);
1257 send_acpi_ev = 1;
1258 } else {
1259 ignore_acpi_ev = 1;
1260 }
1261 break;
1262 case 7:
1263 /* 0x7000-0x7FFF: misc */
1264 if (tp_features.hotkey_wlsw && hkey == 0x7000) {
1265 tpacpi_input_send_radiosw();
1174 break; 1266 break;
1175 case 7:
1176 /* 0x7000-0x7FFF: misc */
1177 if (tp_features.hotkey_wlsw && hkey == 0x7000) {
1178 tpacpi_input_send_radiosw();
1179 sendacpi = 0;
1180 break;
1181 }
1182 /* fallthrough to default */
1183 default:
1184 /* case 2: dock-related */
1185 /* 0x2305 - T43 waking up due to bay lever eject while aslept */
1186 /* case 3: ultra-bay related. maybe bay in dock? */
1187 /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */
1188 printk(IBM_NOTICE "unhandled hotkey event 0x%04x\n", hkey);
1189 } 1267 }
1268 /* fallthrough to default */
1269 default:
1270 /* case 2: dock-related */
1271 /* 0x2305 - T43 waking up due to bay lever eject while aslept */
1272 /* case 3: ultra-bay related. maybe bay in dock? */
1273 /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */
1274 printk(IBM_NOTICE "unhandled HKEY event 0x%04x\n", hkey);
1275 send_acpi_ev = 1;
1190 } 1276 }
1191 1277
1192 if (sendacpi) 1278 /* Legacy events */
1279 if (!ignore_acpi_ev && (send_acpi_ev || hotkey_report_mode < 2)) {
1193 acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey); 1280 acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey);
1194 } else { 1281 }
1195 printk(IBM_ERR "unknown hotkey notification event %d\n", event); 1282
1196 acpi_bus_generate_proc_event(ibm->acpi->device, event, 0); 1283 /* netlink events */
1284 if (!ignore_acpi_ev && send_acpi_ev) {
1285 acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class,
1286 ibm->acpi->device->dev.bus_id,
1287 event, hkey);
1288 }
1197 } 1289 }
1198} 1290}
1199 1291
@@ -2789,7 +2881,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
2789 2881
2790 switch(thermal_read_mode) { 2882 switch(thermal_read_mode) {
2791 case TPACPI_THERMAL_TPEC_16: 2883 case TPACPI_THERMAL_TPEC_16:
2792 res = sysfs_create_group(&tpacpi_pdev->dev.kobj, 2884 res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
2793 &thermal_temp_input16_group); 2885 &thermal_temp_input16_group);
2794 if (res) 2886 if (res)
2795 return res; 2887 return res;
@@ -2797,7 +2889,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm)
2797 case TPACPI_THERMAL_TPEC_8: 2889 case TPACPI_THERMAL_TPEC_8:
2798 case TPACPI_THERMAL_ACPI_TMP07: 2890 case TPACPI_THERMAL_ACPI_TMP07:
2799 case TPACPI_THERMAL_ACPI_UPDT: 2891 case TPACPI_THERMAL_ACPI_UPDT:
2800 res = sysfs_create_group(&tpacpi_pdev->dev.kobj, 2892 res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
2801 &thermal_temp_input8_group); 2893 &thermal_temp_input8_group);
2802 if (res) 2894 if (res)
2803 return res; 2895 return res;
@@ -2814,13 +2906,13 @@ static void thermal_exit(void)
2814{ 2906{
2815 switch(thermal_read_mode) { 2907 switch(thermal_read_mode) {
2816 case TPACPI_THERMAL_TPEC_16: 2908 case TPACPI_THERMAL_TPEC_16:
2817 sysfs_remove_group(&tpacpi_pdev->dev.kobj, 2909 sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
2818 &thermal_temp_input16_group); 2910 &thermal_temp_input16_group);
2819 break; 2911 break;
2820 case TPACPI_THERMAL_TPEC_8: 2912 case TPACPI_THERMAL_TPEC_8:
2821 case TPACPI_THERMAL_ACPI_TMP07: 2913 case TPACPI_THERMAL_ACPI_TMP07:
2822 case TPACPI_THERMAL_ACPI_UPDT: 2914 case TPACPI_THERMAL_ACPI_UPDT:
2823 sysfs_remove_group(&tpacpi_pdev->dev.kobj, 2915 sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj,
2824 &thermal_temp_input16_group); 2916 &thermal_temp_input16_group);
2825 break; 2917 break;
2826 case TPACPI_THERMAL_NONE: 2918 case TPACPI_THERMAL_NONE:
@@ -3603,7 +3695,7 @@ static struct device_attribute dev_attr_fan_fan1_input =
3603 __ATTR(fan1_input, S_IRUGO, 3695 __ATTR(fan1_input, S_IRUGO,
3604 fan_fan1_input_show, NULL); 3696 fan_fan1_input_show, NULL);
3605 3697
3606/* sysfs fan fan_watchdog (driver) ------------------------------------- */ 3698/* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */
3607static ssize_t fan_fan_watchdog_show(struct device_driver *drv, 3699static ssize_t fan_fan_watchdog_show(struct device_driver *drv,
3608 char *buf) 3700 char *buf)
3609{ 3701{
@@ -3745,10 +3837,10 @@ static int __init fan_init(struct ibm_init_struct *iibm)
3745 3837
3746 if (fan_status_access_mode != TPACPI_FAN_NONE || 3838 if (fan_status_access_mode != TPACPI_FAN_NONE ||
3747 fan_control_access_mode != TPACPI_FAN_WR_NONE) { 3839 fan_control_access_mode != TPACPI_FAN_WR_NONE) {
3748 rc = sysfs_create_group(&tpacpi_pdev->dev.kobj, 3840 rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj,
3749 &fan_attr_group); 3841 &fan_attr_group);
3750 if (!(rc < 0)) 3842 if (!(rc < 0))
3751 rc = driver_create_file(&tpacpi_pdriver.driver, 3843 rc = driver_create_file(&tpacpi_hwmon_pdriver.driver,
3752 &driver_attr_fan_watchdog); 3844 &driver_attr_fan_watchdog);
3753 if (rc < 0) 3845 if (rc < 0)
3754 return rc; 3846 return rc;
@@ -3831,8 +3923,8 @@ static void fan_exit(void)
3831 vdbg_printk(TPACPI_DBG_EXIT, "cancelling any pending fan watchdog tasks\n"); 3923 vdbg_printk(TPACPI_DBG_EXIT, "cancelling any pending fan watchdog tasks\n");
3832 3924
3833 /* FIXME: can we really do this unconditionally? */ 3925 /* FIXME: can we really do this unconditionally? */
3834 sysfs_remove_group(&tpacpi_pdev->dev.kobj, &fan_attr_group); 3926 sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, &fan_attr_group);
3835 driver_remove_file(&tpacpi_pdriver.driver, &driver_attr_fan_watchdog); 3927 driver_remove_file(&tpacpi_hwmon_pdriver.driver, &driver_attr_fan_watchdog);
3836 3928
3837 cancel_delayed_work(&fan_watchdog_task); 3929 cancel_delayed_work(&fan_watchdog_task);
3838 flush_scheduled_work(); 3930 flush_scheduled_work();
@@ -3865,6 +3957,9 @@ static void fan_watchdog_fire(struct work_struct *ignored)
3865{ 3957{
3866 int rc; 3958 int rc;
3867 3959
3960 if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING)
3961 return;
3962
3868 printk(IBM_NOTICE "fan watchdog: enabling fan\n"); 3963 printk(IBM_NOTICE "fan watchdog: enabling fan\n");
3869 rc = fan_set_enable(); 3964 rc = fan_set_enable();
3870 if (rc < 0) { 3965 if (rc < 0) {
@@ -3885,7 +3980,8 @@ static void fan_watchdog_reset(void)
3885 if (fan_watchdog_active) 3980 if (fan_watchdog_active)
3886 cancel_delayed_work(&fan_watchdog_task); 3981 cancel_delayed_work(&fan_watchdog_task);
3887 3982
3888 if (fan_watchdog_maxinterval > 0) { 3983 if (fan_watchdog_maxinterval > 0 &&
3984 tpacpi_lifecycle != TPACPI_LIFE_EXITING) {
3889 fan_watchdog_active = 1; 3985 fan_watchdog_active = 1;
3890 if (!schedule_delayed_work(&fan_watchdog_task, 3986 if (!schedule_delayed_work(&fan_watchdog_task,
3891 msecs_to_jiffies(fan_watchdog_maxinterval 3987 msecs_to_jiffies(fan_watchdog_maxinterval
@@ -4279,6 +4375,19 @@ static struct ibm_struct fan_driver_data = {
4279 **************************************************************************** 4375 ****************************************************************************
4280 ****************************************************************************/ 4376 ****************************************************************************/
4281 4377
4378/* sysfs name ---------------------------------------------------------- */
4379static ssize_t thinkpad_acpi_pdev_name_show(struct device *dev,
4380 struct device_attribute *attr,
4381 char *buf)
4382{
4383 return snprintf(buf, PAGE_SIZE, "%s\n", IBM_NAME);
4384}
4385
4386static struct device_attribute dev_attr_thinkpad_acpi_pdev_name =
4387 __ATTR(name, S_IRUGO, thinkpad_acpi_pdev_name_show, NULL);
4388
4389/* --------------------------------------------------------------------- */
4390
4282/* /proc support */ 4391/* /proc support */
4283static struct proc_dir_entry *proc_dir; 4392static struct proc_dir_entry *proc_dir;
4284 4393
@@ -4623,6 +4732,9 @@ module_param_named(fan_control, fan_control_allowed, bool, 0);
4623static int brightness_mode; 4732static int brightness_mode;
4624module_param_named(brightness_mode, brightness_mode, int, 0); 4733module_param_named(brightness_mode, brightness_mode, int, 0);
4625 4734
4735static unsigned int hotkey_report_mode;
4736module_param(hotkey_report_mode, uint, 0);
4737
4626#define IBM_PARAM(feature) \ 4738#define IBM_PARAM(feature) \
4627 module_param_call(feature, set_ibm_param, NULL, NULL, 0) 4739 module_param_call(feature, set_ibm_param, NULL, NULL, 0)
4628 4740
@@ -4648,6 +4760,12 @@ static int __init thinkpad_acpi_module_init(void)
4648{ 4760{
4649 int ret, i; 4761 int ret, i;
4650 4762
4763 tpacpi_lifecycle = TPACPI_LIFE_INIT;
4764
4765 /* Parameter checking */
4766 if (hotkey_report_mode > 2)
4767 return -EINVAL;
4768
4651 /* Driver-level probe */ 4769 /* Driver-level probe */
4652 4770
4653 get_thinkpad_model_data(&thinkpad_id); 4771 get_thinkpad_model_data(&thinkpad_id);
@@ -4672,19 +4790,31 @@ static int __init thinkpad_acpi_module_init(void)
4672 4790
4673 ret = platform_driver_register(&tpacpi_pdriver); 4791 ret = platform_driver_register(&tpacpi_pdriver);
4674 if (ret) { 4792 if (ret) {
4675 printk(IBM_ERR "unable to register platform driver\n"); 4793 printk(IBM_ERR "unable to register main platform driver\n");
4676 thinkpad_acpi_module_exit(); 4794 thinkpad_acpi_module_exit();
4677 return ret; 4795 return ret;
4678 } 4796 }
4679 tp_features.platform_drv_registered = 1; 4797 tp_features.platform_drv_registered = 1;
4680 4798
4799 ret = platform_driver_register(&tpacpi_hwmon_pdriver);
4800 if (ret) {
4801 printk(IBM_ERR "unable to register hwmon platform driver\n");
4802 thinkpad_acpi_module_exit();
4803 return ret;
4804 }
4805 tp_features.sensors_pdrv_registered = 1;
4806
4681 ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver); 4807 ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver);
4808 if (!ret) {
4809 tp_features.platform_drv_attrs_registered = 1;
4810 ret = tpacpi_create_driver_attributes(&tpacpi_hwmon_pdriver.driver);
4811 }
4682 if (ret) { 4812 if (ret) {
4683 printk(IBM_ERR "unable to create sysfs driver attributes\n"); 4813 printk(IBM_ERR "unable to create sysfs driver attributes\n");
4684 thinkpad_acpi_module_exit(); 4814 thinkpad_acpi_module_exit();
4685 return ret; 4815 return ret;
4686 } 4816 }
4687 tp_features.platform_drv_attrs_registered = 1; 4817 tp_features.sensors_pdrv_attrs_registered = 1;
4688 4818
4689 4819
4690 /* Device initialization */ 4820 /* Device initialization */
@@ -4697,7 +4827,26 @@ static int __init thinkpad_acpi_module_init(void)
4697 thinkpad_acpi_module_exit(); 4827 thinkpad_acpi_module_exit();
4698 return ret; 4828 return ret;
4699 } 4829 }
4700 tpacpi_hwmon = hwmon_device_register(&tpacpi_pdev->dev); 4830 tpacpi_sensors_pdev = platform_device_register_simple(
4831 IBM_HWMON_DRVR_NAME,
4832 -1, NULL, 0);
4833 if (IS_ERR(tpacpi_sensors_pdev)) {
4834 ret = PTR_ERR(tpacpi_sensors_pdev);
4835 tpacpi_sensors_pdev = NULL;
4836 printk(IBM_ERR "unable to register hwmon platform device\n");
4837 thinkpad_acpi_module_exit();
4838 return ret;
4839 }
4840 ret = device_create_file(&tpacpi_sensors_pdev->dev,
4841 &dev_attr_thinkpad_acpi_pdev_name);
4842 if (ret) {
4843 printk(IBM_ERR
4844 "unable to create sysfs hwmon device attributes\n");
4845 thinkpad_acpi_module_exit();
4846 return ret;
4847 }
4848 tp_features.sensors_pdev_attrs_registered = 1;
4849 tpacpi_hwmon = hwmon_device_register(&tpacpi_sensors_pdev->dev);
4701 if (IS_ERR(tpacpi_hwmon)) { 4850 if (IS_ERR(tpacpi_hwmon)) {
4702 ret = PTR_ERR(tpacpi_hwmon); 4851 ret = PTR_ERR(tpacpi_hwmon);
4703 tpacpi_hwmon = NULL; 4852 tpacpi_hwmon = NULL;
@@ -4705,6 +4854,7 @@ static int __init thinkpad_acpi_module_init(void)
4705 thinkpad_acpi_module_exit(); 4854 thinkpad_acpi_module_exit();
4706 return ret; 4855 return ret;
4707 } 4856 }
4857 mutex_init(&tpacpi_inputdev_send_mutex);
4708 tpacpi_inputdev = input_allocate_device(); 4858 tpacpi_inputdev = input_allocate_device();
4709 if (!tpacpi_inputdev) { 4859 if (!tpacpi_inputdev) {
4710 printk(IBM_ERR "unable to allocate input device\n"); 4860 printk(IBM_ERR "unable to allocate input device\n");
@@ -4739,6 +4889,7 @@ static int __init thinkpad_acpi_module_init(void)
4739 tp_features.input_device_registered = 1; 4889 tp_features.input_device_registered = 1;
4740 } 4890 }
4741 4891
4892 tpacpi_lifecycle = TPACPI_LIFE_RUNNING;
4742 return 0; 4893 return 0;
4743} 4894}
4744 4895
@@ -4746,6 +4897,8 @@ static void thinkpad_acpi_module_exit(void)
4746{ 4897{
4747 struct ibm_struct *ibm, *itmp; 4898 struct ibm_struct *ibm, *itmp;
4748 4899
4900 tpacpi_lifecycle = TPACPI_LIFE_EXITING;
4901
4749 list_for_each_entry_safe_reverse(ibm, itmp, 4902 list_for_each_entry_safe_reverse(ibm, itmp,
4750 &tpacpi_all_drivers, 4903 &tpacpi_all_drivers,
4751 all_drivers) { 4904 all_drivers) {
@@ -4764,12 +4917,22 @@ static void thinkpad_acpi_module_exit(void)
4764 if (tpacpi_hwmon) 4917 if (tpacpi_hwmon)
4765 hwmon_device_unregister(tpacpi_hwmon); 4918 hwmon_device_unregister(tpacpi_hwmon);
4766 4919
4920 if (tp_features.sensors_pdev_attrs_registered)
4921 device_remove_file(&tpacpi_sensors_pdev->dev,
4922 &dev_attr_thinkpad_acpi_pdev_name);
4923 if (tpacpi_sensors_pdev)
4924 platform_device_unregister(tpacpi_sensors_pdev);
4767 if (tpacpi_pdev) 4925 if (tpacpi_pdev)
4768 platform_device_unregister(tpacpi_pdev); 4926 platform_device_unregister(tpacpi_pdev);
4769 4927
4928 if (tp_features.sensors_pdrv_attrs_registered)
4929 tpacpi_remove_driver_attributes(&tpacpi_hwmon_pdriver.driver);
4770 if (tp_features.platform_drv_attrs_registered) 4930 if (tp_features.platform_drv_attrs_registered)
4771 tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver); 4931 tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver);
4772 4932
4933 if (tp_features.sensors_pdrv_registered)
4934 platform_driver_unregister(&tpacpi_hwmon_pdriver);
4935
4773 if (tp_features.platform_drv_registered) 4936 if (tp_features.platform_drv_registered)
4774 platform_driver_unregister(&tpacpi_pdriver); 4937 platform_driver_unregister(&tpacpi_pdriver);
4775 4938
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h
index eee8809a50d9..c5fdd688cc99 100644
--- a/drivers/misc/thinkpad_acpi.h
+++ b/drivers/misc/thinkpad_acpi.h
@@ -58,13 +58,14 @@
58 58
59#define IBM_NAME "thinkpad" 59#define IBM_NAME "thinkpad"
60#define IBM_DESC "ThinkPad ACPI Extras" 60#define IBM_DESC "ThinkPad ACPI Extras"
61#define IBM_FILE "thinkpad_acpi" 61#define IBM_FILE IBM_NAME "_acpi"
62#define IBM_URL "http://ibm-acpi.sf.net/" 62#define IBM_URL "http://ibm-acpi.sf.net/"
63#define IBM_MAIL "ibm-acpi-devel@lists.sourceforge.net" 63#define IBM_MAIL "ibm-acpi-devel@lists.sourceforge.net"
64 64
65#define IBM_PROC_DIR "ibm" 65#define IBM_PROC_DIR "ibm"
66#define IBM_ACPI_EVENT_PREFIX "ibm" 66#define IBM_ACPI_EVENT_PREFIX "ibm"
67#define IBM_DRVR_NAME IBM_FILE 67#define IBM_DRVR_NAME IBM_FILE
68#define IBM_HWMON_DRVR_NAME IBM_NAME "_hwmon"
68 69
69#define IBM_LOG IBM_FILE ": " 70#define IBM_LOG IBM_FILE ": "
70#define IBM_ERR KERN_ERR IBM_LOG 71#define IBM_ERR KERN_ERR IBM_LOG
@@ -171,6 +172,7 @@ static int parse_strtoul(const char *buf, unsigned long max,
171 172
172/* Device model */ 173/* Device model */
173static struct platform_device *tpacpi_pdev; 174static struct platform_device *tpacpi_pdev;
175static struct platform_device *tpacpi_sensors_pdev;
174static struct class_device *tpacpi_hwmon; 176static struct class_device *tpacpi_hwmon;
175static struct platform_driver tpacpi_pdriver; 177static struct platform_driver tpacpi_pdriver;
176static struct input_dev *tpacpi_inputdev; 178static struct input_dev *tpacpi_inputdev;
@@ -181,6 +183,7 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv);
181static int experimental; 183static int experimental;
182static u32 dbg_level; 184static u32 dbg_level;
183static int force_load; 185static int force_load;
186static unsigned int hotkey_report_mode;
184 187
185static int thinkpad_acpi_module_init(void); 188static int thinkpad_acpi_module_init(void);
186static void thinkpad_acpi_module_exit(void); 189static void thinkpad_acpi_module_exit(void);
@@ -232,22 +235,25 @@ struct ibm_init_struct {
232 235
233static struct { 236static struct {
234#ifdef CONFIG_THINKPAD_ACPI_BAY 237#ifdef CONFIG_THINKPAD_ACPI_BAY
235 u16 bay_status:1; 238 u32 bay_status:1;
236 u16 bay_eject:1; 239 u32 bay_eject:1;
237 u16 bay_status2:1; 240 u32 bay_status2:1;
238 u16 bay_eject2:1; 241 u32 bay_eject2:1;
239#endif 242#endif
240 u16 bluetooth:1; 243 u32 bluetooth:1;
241 u16 hotkey:1; 244 u32 hotkey:1;
242 u16 hotkey_mask:1; 245 u32 hotkey_mask:1;
243 u16 hotkey_wlsw:1; 246 u32 hotkey_wlsw:1;
244 u16 light:1; 247 u32 light:1;
245 u16 light_status:1; 248 u32 light_status:1;
246 u16 wan:1; 249 u32 wan:1;
247 u16 fan_ctrl_status_undef:1; 250 u32 fan_ctrl_status_undef:1;
248 u16 input_device_registered:1; 251 u32 input_device_registered:1;
249 u16 platform_drv_registered:1; 252 u32 platform_drv_registered:1;
250 u16 platform_drv_attrs_registered:1; 253 u32 platform_drv_attrs_registered:1;
254 u32 sensors_pdrv_registered:1;
255 u32 sensors_pdrv_attrs_registered:1;
256 u32 sensors_pdev_attrs_registered:1;
251} tp_features; 257} tp_features;
252 258
253struct thinkpad_id_data { 259struct thinkpad_id_data {