diff options
-rw-r--r-- | drivers/hwmon/applesmc.c | 539 |
1 files changed, 297 insertions, 242 deletions
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 5f67e390e45c..f213997adaec 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
33 | #include <linux/input-polldev.h> | 33 | #include <linux/input-polldev.h> |
34 | #include <linux/kernel.h> | 34 | #include <linux/kernel.h> |
35 | #include <linux/slab.h> | ||
35 | #include <linux/module.h> | 36 | #include <linux/module.h> |
36 | #include <linux/timer.h> | 37 | #include <linux/timer.h> |
37 | #include <linux/dmi.h> | 38 | #include <linux/dmi.h> |
@@ -51,6 +52,7 @@ | |||
51 | 52 | ||
52 | #define APPLESMC_MAX_DATA_LENGTH 32 | 53 | #define APPLESMC_MAX_DATA_LENGTH 32 |
53 | 54 | ||
55 | /* wait up to 32 ms for a status change. */ | ||
54 | #define APPLESMC_MIN_WAIT 0x0040 | 56 | #define APPLESMC_MIN_WAIT 0x0040 |
55 | #define APPLESMC_MAX_WAIT 0x8000 | 57 | #define APPLESMC_MAX_WAIT 0x8000 |
56 | 58 | ||
@@ -200,6 +202,25 @@ struct dmi_match_data { | |||
200 | int temperature_set; | 202 | int temperature_set; |
201 | }; | 203 | }; |
202 | 204 | ||
205 | /* AppleSMC entry - cached register information */ | ||
206 | struct applesmc_entry { | ||
207 | char key[5]; /* four-letter key code */ | ||
208 | u8 valid; /* set when entry is successfully read once */ | ||
209 | u8 len; /* bounded by APPLESMC_MAX_DATA_LENGTH */ | ||
210 | char type[5]; /* four-letter type code */ | ||
211 | u8 flags; /* 0x10: func; 0x40: write; 0x80: read */ | ||
212 | }; | ||
213 | |||
214 | /* Register lookup and registers common to all SMCs */ | ||
215 | static struct applesmc_registers { | ||
216 | struct mutex mutex; /* register read/write mutex */ | ||
217 | unsigned int key_count; /* number of SMC registers */ | ||
218 | bool init_complete; /* true when fully initialized */ | ||
219 | struct applesmc_entry *cache; /* cached key entries */ | ||
220 | } smcreg = { | ||
221 | .mutex = __MUTEX_INITIALIZER(smcreg.mutex), | ||
222 | }; | ||
223 | |||
203 | static const int debug; | 224 | static const int debug; |
204 | static struct platform_device *pdev; | 225 | static struct platform_device *pdev; |
205 | static s16 rest_x; | 226 | static s16 rest_x; |
@@ -221,8 +242,6 @@ static unsigned int fans_handled; | |||
221 | /* Indicates which temperature sensors set to use. */ | 242 | /* Indicates which temperature sensors set to use. */ |
222 | static unsigned int applesmc_temperature_set; | 243 | static unsigned int applesmc_temperature_set; |
223 | 244 | ||
224 | static DEFINE_MUTEX(applesmc_lock); | ||
225 | |||
226 | /* | 245 | /* |
227 | * Last index written to key_at_index sysfs file, and value to use for all other | 246 | * Last index written to key_at_index sysfs file, and value to use for all other |
228 | * key_at_index_* sysfs files. | 247 | * key_at_index_* sysfs files. |
@@ -245,16 +264,10 @@ static int __wait_status(u8 val) | |||
245 | for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { | 264 | for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { |
246 | udelay(us); | 265 | udelay(us); |
247 | if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) { | 266 | if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) { |
248 | if (debug) | ||
249 | printk(KERN_DEBUG | ||
250 | "Waited %d us for status %x\n", | ||
251 | 2 * us - APPLESMC_MIN_WAIT, val); | ||
252 | return 0; | 267 | return 0; |
253 | } | 268 | } |
254 | } | 269 | } |
255 | 270 | ||
256 | pr_warn("wait status failed: %x != %x\n", val, inb(APPLESMC_CMD_PORT)); | ||
257 | |||
258 | return -EIO; | 271 | return -EIO; |
259 | } | 272 | } |
260 | 273 | ||
@@ -272,156 +285,228 @@ static int send_command(u8 cmd) | |||
272 | if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c) | 285 | if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c) |
273 | return 0; | 286 | return 0; |
274 | } | 287 | } |
275 | pr_warn("command failed: %x -> %x\n", cmd, inb(APPLESMC_CMD_PORT)); | ||
276 | return -EIO; | 288 | return -EIO; |
277 | } | 289 | } |
278 | 290 | ||
279 | /* | 291 | static int send_argument(const char *key) |
280 | * applesmc_read_key - reads len bytes from a given key, and put them in buffer. | ||
281 | * Returns zero on success or a negative error on failure. Callers must | ||
282 | * hold applesmc_lock. | ||
283 | */ | ||
284 | static int applesmc_read_key(const char* key, u8* buffer, u8 len) | ||
285 | { | 292 | { |
286 | int i; | 293 | int i; |
287 | 294 | ||
288 | if (len > APPLESMC_MAX_DATA_LENGTH) { | ||
289 | pr_err("%s(): cannot read more than %d bytes\n", | ||
290 | __func__, APPLESMC_MAX_DATA_LENGTH); | ||
291 | return -EINVAL; | ||
292 | } | ||
293 | |||
294 | if (send_command(APPLESMC_READ_CMD)) | ||
295 | return -EIO; | ||
296 | |||
297 | for (i = 0; i < 4; i++) { | 295 | for (i = 0; i < 4; i++) { |
298 | outb(key[i], APPLESMC_DATA_PORT); | 296 | outb(key[i], APPLESMC_DATA_PORT); |
299 | if (__wait_status(0x04)) | 297 | if (__wait_status(0x04)) |
300 | return -EIO; | 298 | return -EIO; |
301 | } | 299 | } |
302 | if (debug) | 300 | return 0; |
303 | printk(KERN_DEBUG "<%s", key); | 301 | } |
302 | |||
303 | static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) | ||
304 | { | ||
305 | int i; | ||
306 | |||
307 | if (send_command(cmd) || send_argument(key)) { | ||
308 | pr_warn("%s: read arg fail\n", key); | ||
309 | return -EIO; | ||
310 | } | ||
304 | 311 | ||
305 | outb(len, APPLESMC_DATA_PORT); | 312 | outb(len, APPLESMC_DATA_PORT); |
306 | if (debug) | ||
307 | printk(KERN_DEBUG ">%x", len); | ||
308 | 313 | ||
309 | for (i = 0; i < len; i++) { | 314 | for (i = 0; i < len; i++) { |
310 | if (__wait_status(0x05)) | 315 | if (__wait_status(0x05)) { |
316 | pr_warn("%s: read data fail\n", key); | ||
311 | return -EIO; | 317 | return -EIO; |
318 | } | ||
312 | buffer[i] = inb(APPLESMC_DATA_PORT); | 319 | buffer[i] = inb(APPLESMC_DATA_PORT); |
313 | if (debug) | ||
314 | printk(KERN_DEBUG "<%x", buffer[i]); | ||
315 | } | 320 | } |
316 | if (debug) | ||
317 | printk(KERN_DEBUG "\n"); | ||
318 | 321 | ||
319 | return 0; | 322 | return 0; |
320 | } | 323 | } |
321 | 324 | ||
322 | /* | 325 | static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len) |
323 | * applesmc_write_key - writes len bytes from buffer to a given key. | ||
324 | * Returns zero on success or a negative error on failure. Callers must | ||
325 | * hold applesmc_lock. | ||
326 | */ | ||
327 | static int applesmc_write_key(const char* key, u8* buffer, u8 len) | ||
328 | { | 326 | { |
329 | int i; | 327 | int i; |
330 | 328 | ||
331 | if (len > APPLESMC_MAX_DATA_LENGTH) { | 329 | if (send_command(cmd) || send_argument(key)) { |
332 | pr_err("%s(): cannot write more than %d bytes\n", | 330 | pr_warn("%s: write arg fail\n", key); |
333 | __func__, APPLESMC_MAX_DATA_LENGTH); | ||
334 | return -EINVAL; | ||
335 | } | ||
336 | |||
337 | if (send_command(APPLESMC_WRITE_CMD)) | ||
338 | return -EIO; | 331 | return -EIO; |
339 | |||
340 | for (i = 0; i < 4; i++) { | ||
341 | outb(key[i], APPLESMC_DATA_PORT); | ||
342 | if (__wait_status(0x04)) | ||
343 | return -EIO; | ||
344 | } | 332 | } |
345 | 333 | ||
346 | outb(len, APPLESMC_DATA_PORT); | 334 | outb(len, APPLESMC_DATA_PORT); |
347 | 335 | ||
348 | for (i = 0; i < len; i++) { | 336 | for (i = 0; i < len; i++) { |
349 | if (__wait_status(0x04)) | 337 | if (__wait_status(0x04)) { |
338 | pr_warn("%s: write data fail\n", key); | ||
350 | return -EIO; | 339 | return -EIO; |
340 | } | ||
351 | outb(buffer[i], APPLESMC_DATA_PORT); | 341 | outb(buffer[i], APPLESMC_DATA_PORT); |
352 | } | 342 | } |
353 | 343 | ||
354 | return 0; | 344 | return 0; |
355 | } | 345 | } |
356 | 346 | ||
347 | static int read_register_count(unsigned int *count) | ||
348 | { | ||
349 | __be32 be; | ||
350 | int ret; | ||
351 | |||
352 | ret = read_smc(APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4); | ||
353 | if (ret) | ||
354 | return ret; | ||
355 | |||
356 | *count = be32_to_cpu(be); | ||
357 | return 0; | ||
358 | } | ||
359 | |||
357 | /* | 360 | /* |
358 | * applesmc_get_key_at_index - get key at index, and put the result in key | 361 | * Serialized I/O |
359 | * (char[6]). Returns zero on success or a negative error on failure. Callers | 362 | * |
360 | * must hold applesmc_lock. | 363 | * Returns zero on success or a negative error on failure. |
364 | * All functions below are concurrency safe - callers should NOT hold lock. | ||
361 | */ | 365 | */ |
362 | static int applesmc_get_key_at_index(int index, char* key) | 366 | |
367 | static int applesmc_read_entry(const struct applesmc_entry *entry, | ||
368 | u8 *buf, u8 len) | ||
363 | { | 369 | { |
364 | int i; | 370 | int ret; |
365 | u8 readkey[4]; | ||
366 | readkey[0] = index >> 24; | ||
367 | readkey[1] = index >> 16; | ||
368 | readkey[2] = index >> 8; | ||
369 | readkey[3] = index; | ||
370 | 371 | ||
371 | if (send_command(APPLESMC_GET_KEY_BY_INDEX_CMD)) | 372 | if (entry->len != len) |
372 | return -EIO; | 373 | return -EINVAL; |
374 | mutex_lock(&smcreg.mutex); | ||
375 | ret = read_smc(APPLESMC_READ_CMD, entry->key, buf, len); | ||
376 | mutex_unlock(&smcreg.mutex); | ||
373 | 377 | ||
374 | for (i = 0; i < 4; i++) { | 378 | return ret; |
375 | outb(readkey[i], APPLESMC_DATA_PORT); | 379 | } |
376 | if (__wait_status(0x04)) | 380 | |
377 | return -EIO; | 381 | static int applesmc_write_entry(const struct applesmc_entry *entry, |
382 | const u8 *buf, u8 len) | ||
383 | { | ||
384 | int ret; | ||
385 | |||
386 | if (entry->len != len) | ||
387 | return -EINVAL; | ||
388 | mutex_lock(&smcreg.mutex); | ||
389 | ret = write_smc(APPLESMC_WRITE_CMD, entry->key, buf, len); | ||
390 | mutex_unlock(&smcreg.mutex); | ||
391 | return ret; | ||
392 | } | ||
393 | |||
394 | static const struct applesmc_entry *applesmc_get_entry_by_index(int index) | ||
395 | { | ||
396 | struct applesmc_entry *cache = &smcreg.cache[index]; | ||
397 | u8 key[4], info[6]; | ||
398 | __be32 be; | ||
399 | int ret = 0; | ||
400 | |||
401 | if (cache->valid) | ||
402 | return cache; | ||
403 | |||
404 | mutex_lock(&smcreg.mutex); | ||
405 | |||
406 | if (cache->valid) | ||
407 | goto out; | ||
408 | be = cpu_to_be32(index); | ||
409 | ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4); | ||
410 | if (ret) | ||
411 | goto out; | ||
412 | ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6); | ||
413 | if (ret) | ||
414 | goto out; | ||
415 | |||
416 | memcpy(cache->key, key, 4); | ||
417 | cache->len = info[0]; | ||
418 | memcpy(cache->type, &info[1], 4); | ||
419 | cache->flags = info[5]; | ||
420 | cache->valid = 1; | ||
421 | |||
422 | out: | ||
423 | mutex_unlock(&smcreg.mutex); | ||
424 | if (ret) | ||
425 | return ERR_PTR(ret); | ||
426 | return cache; | ||
427 | } | ||
428 | |||
429 | static int applesmc_get_lower_bound(unsigned int *lo, const char *key) | ||
430 | { | ||
431 | int begin = 0, end = smcreg.key_count; | ||
432 | const struct applesmc_entry *entry; | ||
433 | |||
434 | while (begin != end) { | ||
435 | int middle = begin + (end - begin) / 2; | ||
436 | entry = applesmc_get_entry_by_index(middle); | ||
437 | if (IS_ERR(entry)) | ||
438 | return PTR_ERR(entry); | ||
439 | if (strcmp(entry->key, key) < 0) | ||
440 | begin = middle + 1; | ||
441 | else | ||
442 | end = middle; | ||
378 | } | 443 | } |
379 | 444 | ||
380 | outb(4, APPLESMC_DATA_PORT); | 445 | *lo = begin; |
446 | return 0; | ||
447 | } | ||
381 | 448 | ||
382 | for (i = 0; i < 4; i++) { | 449 | static int applesmc_get_upper_bound(unsigned int *hi, const char *key) |
383 | if (__wait_status(0x05)) | 450 | { |
384 | return -EIO; | 451 | int begin = 0, end = smcreg.key_count; |
385 | key[i] = inb(APPLESMC_DATA_PORT); | 452 | const struct applesmc_entry *entry; |
453 | |||
454 | while (begin != end) { | ||
455 | int middle = begin + (end - begin) / 2; | ||
456 | entry = applesmc_get_entry_by_index(middle); | ||
457 | if (IS_ERR(entry)) | ||
458 | return PTR_ERR(entry); | ||
459 | if (strcmp(key, entry->key) < 0) | ||
460 | end = middle; | ||
461 | else | ||
462 | begin = middle + 1; | ||
386 | } | 463 | } |
387 | key[4] = 0; | ||
388 | 464 | ||
465 | *hi = begin; | ||
389 | return 0; | 466 | return 0; |
390 | } | 467 | } |
391 | 468 | ||
392 | /* | 469 | static const struct applesmc_entry *applesmc_get_entry_by_key(const char *key) |
393 | * applesmc_get_key_type - get key type, and put the result in type (char[6]). | ||
394 | * Returns zero on success or a negative error on failure. Callers must | ||
395 | * hold applesmc_lock. | ||
396 | */ | ||
397 | static int applesmc_get_key_type(char* key, char* type) | ||
398 | { | 470 | { |
399 | int i; | 471 | int begin, end; |
472 | int ret; | ||
400 | 473 | ||
401 | if (send_command(APPLESMC_GET_KEY_TYPE_CMD)) | 474 | ret = applesmc_get_lower_bound(&begin, key); |
402 | return -EIO; | 475 | if (ret) |
476 | return ERR_PTR(ret); | ||
477 | ret = applesmc_get_upper_bound(&end, key); | ||
478 | if (ret) | ||
479 | return ERR_PTR(ret); | ||
480 | if (end - begin != 1) | ||
481 | return ERR_PTR(-EINVAL); | ||
403 | 482 | ||
404 | for (i = 0; i < 4; i++) { | 483 | return applesmc_get_entry_by_index(begin); |
405 | outb(key[i], APPLESMC_DATA_PORT); | 484 | } |
406 | if (__wait_status(0x04)) | ||
407 | return -EIO; | ||
408 | } | ||
409 | 485 | ||
410 | outb(6, APPLESMC_DATA_PORT); | 486 | static int applesmc_read_key(const char *key, u8 *buffer, u8 len) |
487 | { | ||
488 | const struct applesmc_entry *entry; | ||
411 | 489 | ||
412 | for (i = 0; i < 6; i++) { | 490 | entry = applesmc_get_entry_by_key(key); |
413 | if (__wait_status(0x05)) | 491 | if (IS_ERR(entry)) |
414 | return -EIO; | 492 | return PTR_ERR(entry); |
415 | type[i] = inb(APPLESMC_DATA_PORT); | ||
416 | } | ||
417 | type[5] = 0; | ||
418 | 493 | ||
419 | return 0; | 494 | return applesmc_read_entry(entry, buffer, len); |
495 | } | ||
496 | |||
497 | static int applesmc_write_key(const char *key, const u8 *buffer, u8 len) | ||
498 | { | ||
499 | const struct applesmc_entry *entry; | ||
500 | |||
501 | entry = applesmc_get_entry_by_key(key); | ||
502 | if (IS_ERR(entry)) | ||
503 | return PTR_ERR(entry); | ||
504 | |||
505 | return applesmc_write_entry(entry, buffer, len); | ||
420 | } | 506 | } |
421 | 507 | ||
422 | /* | 508 | /* |
423 | * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). Callers must | 509 | * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). |
424 | * hold applesmc_lock. | ||
425 | */ | 510 | */ |
426 | static int applesmc_read_motion_sensor(int index, s16* value) | 511 | static int applesmc_read_motion_sensor(int index, s16* value) |
427 | { | 512 | { |
@@ -458,12 +543,10 @@ static void applesmc_device_init(void) | |||
458 | if (!applesmc_accelerometer) | 543 | if (!applesmc_accelerometer) |
459 | return; | 544 | return; |
460 | 545 | ||
461 | mutex_lock(&applesmc_lock); | ||
462 | |||
463 | for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) { | 546 | for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) { |
464 | if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) && | 547 | if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) && |
465 | (buffer[0] != 0x00 || buffer[1] != 0x00)) | 548 | (buffer[0] != 0x00 || buffer[1] != 0x00)) |
466 | goto out; | 549 | return; |
467 | buffer[0] = 0xe0; | 550 | buffer[0] = 0xe0; |
468 | buffer[1] = 0x00; | 551 | buffer[1] = 0x00; |
469 | applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2); | 552 | applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2); |
@@ -471,34 +554,93 @@ static void applesmc_device_init(void) | |||
471 | } | 554 | } |
472 | 555 | ||
473 | pr_warn("failed to init the device\n"); | 556 | pr_warn("failed to init the device\n"); |
474 | |||
475 | out: | ||
476 | mutex_unlock(&applesmc_lock); | ||
477 | } | 557 | } |
478 | 558 | ||
479 | /* | 559 | /* |
480 | * applesmc_get_fan_count - get the number of fans. Callers must NOT hold | 560 | * applesmc_get_fan_count - get the number of fans. |
481 | * applesmc_lock. | ||
482 | */ | 561 | */ |
483 | static int applesmc_get_fan_count(void) | 562 | static int applesmc_get_fan_count(void) |
484 | { | 563 | { |
485 | int ret; | 564 | int ret; |
486 | u8 buffer[1]; | 565 | u8 buffer[1]; |
487 | 566 | ||
488 | mutex_lock(&applesmc_lock); | ||
489 | |||
490 | ret = applesmc_read_key(FANS_COUNT, buffer, 1); | 567 | ret = applesmc_read_key(FANS_COUNT, buffer, 1); |
491 | 568 | ||
492 | mutex_unlock(&applesmc_lock); | ||
493 | if (ret) | 569 | if (ret) |
494 | return ret; | 570 | return ret; |
495 | else | 571 | else |
496 | return buffer[0]; | 572 | return buffer[0]; |
497 | } | 573 | } |
498 | 574 | ||
575 | /* | ||
576 | * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent. | ||
577 | */ | ||
578 | static int applesmc_init_smcreg_try(void) | ||
579 | { | ||
580 | struct applesmc_registers *s = &smcreg; | ||
581 | int ret; | ||
582 | |||
583 | if (s->init_complete) | ||
584 | return 0; | ||
585 | |||
586 | ret = read_register_count(&s->key_count); | ||
587 | if (ret) | ||
588 | return ret; | ||
589 | |||
590 | if (!s->cache) | ||
591 | s->cache = kcalloc(s->key_count, sizeof(*s->cache), GFP_KERNEL); | ||
592 | if (!s->cache) | ||
593 | return -ENOMEM; | ||
594 | |||
595 | s->init_complete = true; | ||
596 | |||
597 | pr_info("key=%d\n", s->key_count); | ||
598 | |||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | /* | ||
603 | * applesmc_init_smcreg - Initialize register cache. | ||
604 | * | ||
605 | * Retries until initialization is successful, or the operation times out. | ||
606 | * | ||
607 | */ | ||
608 | static int applesmc_init_smcreg(void) | ||
609 | { | ||
610 | int ms, ret; | ||
611 | |||
612 | for (ms = 0; ms < INIT_TIMEOUT_MSECS; ms += INIT_WAIT_MSECS) { | ||
613 | ret = applesmc_init_smcreg_try(); | ||
614 | if (!ret) { | ||
615 | if (ms) | ||
616 | pr_info("init_smcreg() took %d ms\n", ms); | ||
617 | return 0; | ||
618 | } | ||
619 | msleep(INIT_WAIT_MSECS); | ||
620 | } | ||
621 | |||
622 | kfree(smcreg.cache); | ||
623 | smcreg.cache = NULL; | ||
624 | |||
625 | return ret; | ||
626 | } | ||
627 | |||
628 | static void applesmc_destroy_smcreg(void) | ||
629 | { | ||
630 | kfree(smcreg.cache); | ||
631 | smcreg.cache = NULL; | ||
632 | smcreg.init_complete = false; | ||
633 | } | ||
634 | |||
499 | /* Device model stuff */ | 635 | /* Device model stuff */ |
500 | static int applesmc_probe(struct platform_device *dev) | 636 | static int applesmc_probe(struct platform_device *dev) |
501 | { | 637 | { |
638 | int ret; | ||
639 | |||
640 | ret = applesmc_init_smcreg(); | ||
641 | if (ret) | ||
642 | return ret; | ||
643 | |||
502 | applesmc_device_init(); | 644 | applesmc_device_init(); |
503 | 645 | ||
504 | return 0; | 646 | return 0; |
@@ -507,10 +649,8 @@ static int applesmc_probe(struct platform_device *dev) | |||
507 | /* Synchronize device with memorized backlight state */ | 649 | /* Synchronize device with memorized backlight state */ |
508 | static int applesmc_pm_resume(struct device *dev) | 650 | static int applesmc_pm_resume(struct device *dev) |
509 | { | 651 | { |
510 | mutex_lock(&applesmc_lock); | ||
511 | if (applesmc_light) | 652 | if (applesmc_light) |
512 | applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2); | 653 | applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2); |
513 | mutex_unlock(&applesmc_lock); | ||
514 | return 0; | 654 | return 0; |
515 | } | 655 | } |
516 | 656 | ||
@@ -551,20 +691,15 @@ static void applesmc_idev_poll(struct input_polled_dev *dev) | |||
551 | struct input_dev *idev = dev->input; | 691 | struct input_dev *idev = dev->input; |
552 | s16 x, y; | 692 | s16 x, y; |
553 | 693 | ||
554 | mutex_lock(&applesmc_lock); | ||
555 | |||
556 | if (applesmc_read_motion_sensor(SENSOR_X, &x)) | 694 | if (applesmc_read_motion_sensor(SENSOR_X, &x)) |
557 | goto out; | 695 | return; |
558 | if (applesmc_read_motion_sensor(SENSOR_Y, &y)) | 696 | if (applesmc_read_motion_sensor(SENSOR_Y, &y)) |
559 | goto out; | 697 | return; |
560 | 698 | ||
561 | x = -x; | 699 | x = -x; |
562 | input_report_abs(idev, ABS_X, x - rest_x); | 700 | input_report_abs(idev, ABS_X, x - rest_x); |
563 | input_report_abs(idev, ABS_Y, y - rest_y); | 701 | input_report_abs(idev, ABS_Y, y - rest_y); |
564 | input_sync(idev); | 702 | input_sync(idev); |
565 | |||
566 | out: | ||
567 | mutex_unlock(&applesmc_lock); | ||
568 | } | 703 | } |
569 | 704 | ||
570 | /* Sysfs Files */ | 705 | /* Sysfs Files */ |
@@ -581,8 +716,6 @@ static ssize_t applesmc_position_show(struct device *dev, | |||
581 | int ret; | 716 | int ret; |
582 | s16 x, y, z; | 717 | s16 x, y, z; |
583 | 718 | ||
584 | mutex_lock(&applesmc_lock); | ||
585 | |||
586 | ret = applesmc_read_motion_sensor(SENSOR_X, &x); | 719 | ret = applesmc_read_motion_sensor(SENSOR_X, &x); |
587 | if (ret) | 720 | if (ret) |
588 | goto out; | 721 | goto out; |
@@ -594,7 +727,6 @@ static ssize_t applesmc_position_show(struct device *dev, | |||
594 | goto out; | 727 | goto out; |
595 | 728 | ||
596 | out: | 729 | out: |
597 | mutex_unlock(&applesmc_lock); | ||
598 | if (ret) | 730 | if (ret) |
599 | return ret; | 731 | return ret; |
600 | else | 732 | else |
@@ -604,18 +736,19 @@ out: | |||
604 | static ssize_t applesmc_light_show(struct device *dev, | 736 | static ssize_t applesmc_light_show(struct device *dev, |
605 | struct device_attribute *attr, char *sysfsbuf) | 737 | struct device_attribute *attr, char *sysfsbuf) |
606 | { | 738 | { |
739 | const struct applesmc_entry *entry; | ||
607 | static int data_length; | 740 | static int data_length; |
608 | int ret; | 741 | int ret; |
609 | u8 left = 0, right = 0; | 742 | u8 left = 0, right = 0; |
610 | u8 buffer[10], query[6]; | 743 | u8 buffer[10]; |
611 | |||
612 | mutex_lock(&applesmc_lock); | ||
613 | 744 | ||
614 | if (!data_length) { | 745 | if (!data_length) { |
615 | ret = applesmc_get_key_type(LIGHT_SENSOR_LEFT_KEY, query); | 746 | entry = applesmc_get_entry_by_key(LIGHT_SENSOR_LEFT_KEY); |
616 | if (ret) | 747 | if (IS_ERR(entry)) |
617 | goto out; | 748 | return PTR_ERR(entry); |
618 | data_length = clamp_val(query[0], 0, 10); | 749 | if (entry->len > 10) |
750 | return -ENXIO; | ||
751 | data_length = entry->len; | ||
619 | pr_info("light sensor data length set to %d\n", data_length); | 752 | pr_info("light sensor data length set to %d\n", data_length); |
620 | } | 753 | } |
621 | 754 | ||
@@ -632,7 +765,6 @@ static ssize_t applesmc_light_show(struct device *dev, | |||
632 | right = buffer[2]; | 765 | right = buffer[2]; |
633 | 766 | ||
634 | out: | 767 | out: |
635 | mutex_unlock(&applesmc_lock); | ||
636 | if (ret) | 768 | if (ret) |
637 | return ret; | 769 | return ret; |
638 | else | 770 | else |
@@ -661,14 +793,10 @@ static ssize_t applesmc_show_temperature(struct device *dev, | |||
661 | const char* key = | 793 | const char* key = |
662 | temperature_sensors_sets[applesmc_temperature_set][attr->index]; | 794 | temperature_sensors_sets[applesmc_temperature_set][attr->index]; |
663 | 795 | ||
664 | mutex_lock(&applesmc_lock); | ||
665 | |||
666 | ret = applesmc_read_key(key, buffer, 2); | 796 | ret = applesmc_read_key(key, buffer, 2); |
667 | temp = buffer[0]*1000; | 797 | temp = buffer[0]*1000; |
668 | temp += (buffer[1] >> 6) * 250; | 798 | temp += (buffer[1] >> 6) * 250; |
669 | 799 | ||
670 | mutex_unlock(&applesmc_lock); | ||
671 | |||
672 | if (ret) | 800 | if (ret) |
673 | return ret; | 801 | return ret; |
674 | else | 802 | else |
@@ -691,12 +819,9 @@ static ssize_t applesmc_show_fan_speed(struct device *dev, | |||
691 | newkey[3] = fan_speed_keys[sensor_attr->nr][3]; | 819 | newkey[3] = fan_speed_keys[sensor_attr->nr][3]; |
692 | newkey[4] = 0; | 820 | newkey[4] = 0; |
693 | 821 | ||
694 | mutex_lock(&applesmc_lock); | ||
695 | |||
696 | ret = applesmc_read_key(newkey, buffer, 2); | 822 | ret = applesmc_read_key(newkey, buffer, 2); |
697 | speed = ((buffer[0] << 8 | buffer[1]) >> 2); | 823 | speed = ((buffer[0] << 8 | buffer[1]) >> 2); |
698 | 824 | ||
699 | mutex_unlock(&applesmc_lock); | ||
700 | if (ret) | 825 | if (ret) |
701 | return ret; | 826 | return ret; |
702 | else | 827 | else |
@@ -725,13 +850,10 @@ static ssize_t applesmc_store_fan_speed(struct device *dev, | |||
725 | newkey[3] = fan_speed_keys[sensor_attr->nr][3]; | 850 | newkey[3] = fan_speed_keys[sensor_attr->nr][3]; |
726 | newkey[4] = 0; | 851 | newkey[4] = 0; |
727 | 852 | ||
728 | mutex_lock(&applesmc_lock); | ||
729 | |||
730 | buffer[0] = (speed >> 6) & 0xff; | 853 | buffer[0] = (speed >> 6) & 0xff; |
731 | buffer[1] = (speed << 2) & 0xff; | 854 | buffer[1] = (speed << 2) & 0xff; |
732 | ret = applesmc_write_key(newkey, buffer, 2); | 855 | ret = applesmc_write_key(newkey, buffer, 2); |
733 | 856 | ||
734 | mutex_unlock(&applesmc_lock); | ||
735 | if (ret) | 857 | if (ret) |
736 | return ret; | 858 | return ret; |
737 | else | 859 | else |
@@ -746,12 +868,9 @@ static ssize_t applesmc_show_fan_manual(struct device *dev, | |||
746 | u8 buffer[2]; | 868 | u8 buffer[2]; |
747 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 869 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
748 | 870 | ||
749 | mutex_lock(&applesmc_lock); | ||
750 | |||
751 | ret = applesmc_read_key(FANS_MANUAL, buffer, 2); | 871 | ret = applesmc_read_key(FANS_MANUAL, buffer, 2); |
752 | manual = ((buffer[0] << 8 | buffer[1]) >> attr->index) & 0x01; | 872 | manual = ((buffer[0] << 8 | buffer[1]) >> attr->index) & 0x01; |
753 | 873 | ||
754 | mutex_unlock(&applesmc_lock); | ||
755 | if (ret) | 874 | if (ret) |
756 | return ret; | 875 | return ret; |
757 | else | 876 | else |
@@ -770,8 +889,6 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, | |||
770 | 889 | ||
771 | input = simple_strtoul(sysfsbuf, NULL, 10); | 890 | input = simple_strtoul(sysfsbuf, NULL, 10); |
772 | 891 | ||
773 | mutex_lock(&applesmc_lock); | ||
774 | |||
775 | ret = applesmc_read_key(FANS_MANUAL, buffer, 2); | 892 | ret = applesmc_read_key(FANS_MANUAL, buffer, 2); |
776 | val = (buffer[0] << 8 | buffer[1]); | 893 | val = (buffer[0] << 8 | buffer[1]); |
777 | if (ret) | 894 | if (ret) |
@@ -788,7 +905,6 @@ static ssize_t applesmc_store_fan_manual(struct device *dev, | |||
788 | ret = applesmc_write_key(FANS_MANUAL, buffer, 2); | 905 | ret = applesmc_write_key(FANS_MANUAL, buffer, 2); |
789 | 906 | ||
790 | out: | 907 | out: |
791 | mutex_unlock(&applesmc_lock); | ||
792 | if (ret) | 908 | if (ret) |
793 | return ret; | 909 | return ret; |
794 | else | 910 | else |
@@ -810,12 +926,9 @@ static ssize_t applesmc_show_fan_position(struct device *dev, | |||
810 | newkey[3] = FAN_POSITION[3]; | 926 | newkey[3] = FAN_POSITION[3]; |
811 | newkey[4] = 0; | 927 | newkey[4] = 0; |
812 | 928 | ||
813 | mutex_lock(&applesmc_lock); | ||
814 | |||
815 | ret = applesmc_read_key(newkey, buffer, 16); | 929 | ret = applesmc_read_key(newkey, buffer, 16); |
816 | buffer[16] = 0; | 930 | buffer[16] = 0; |
817 | 931 | ||
818 | mutex_unlock(&applesmc_lock); | ||
819 | if (ret) | 932 | if (ret) |
820 | return ret; | 933 | return ret; |
821 | else | 934 | else |
@@ -831,18 +944,14 @@ static ssize_t applesmc_calibrate_show(struct device *dev, | |||
831 | static ssize_t applesmc_calibrate_store(struct device *dev, | 944 | static ssize_t applesmc_calibrate_store(struct device *dev, |
832 | struct device_attribute *attr, const char *sysfsbuf, size_t count) | 945 | struct device_attribute *attr, const char *sysfsbuf, size_t count) |
833 | { | 946 | { |
834 | mutex_lock(&applesmc_lock); | ||
835 | applesmc_calibrate(); | 947 | applesmc_calibrate(); |
836 | mutex_unlock(&applesmc_lock); | ||
837 | 948 | ||
838 | return count; | 949 | return count; |
839 | } | 950 | } |
840 | 951 | ||
841 | static void applesmc_backlight_set(struct work_struct *work) | 952 | static void applesmc_backlight_set(struct work_struct *work) |
842 | { | 953 | { |
843 | mutex_lock(&applesmc_lock); | ||
844 | applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2); | 954 | applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2); |
845 | mutex_unlock(&applesmc_lock); | ||
846 | } | 955 | } |
847 | static DECLARE_WORK(backlight_work, &applesmc_backlight_set); | 956 | static DECLARE_WORK(backlight_work, &applesmc_backlight_set); |
848 | 957 | ||
@@ -865,13 +974,10 @@ static ssize_t applesmc_key_count_show(struct device *dev, | |||
865 | u8 buffer[4]; | 974 | u8 buffer[4]; |
866 | u32 count; | 975 | u32 count; |
867 | 976 | ||
868 | mutex_lock(&applesmc_lock); | ||
869 | |||
870 | ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4); | 977 | ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4); |
871 | count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) + | 978 | count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) + |
872 | ((u32)buffer[2]<<8) + buffer[3]; | 979 | ((u32)buffer[2]<<8) + buffer[3]; |
873 | 980 | ||
874 | mutex_unlock(&applesmc_lock); | ||
875 | if (ret) | 981 | if (ret) |
876 | return ret; | 982 | return ret; |
877 | else | 983 | else |
@@ -881,113 +987,53 @@ static ssize_t applesmc_key_count_show(struct device *dev, | |||
881 | static ssize_t applesmc_key_at_index_read_show(struct device *dev, | 987 | static ssize_t applesmc_key_at_index_read_show(struct device *dev, |
882 | struct device_attribute *attr, char *sysfsbuf) | 988 | struct device_attribute *attr, char *sysfsbuf) |
883 | { | 989 | { |
884 | char key[5]; | 990 | const struct applesmc_entry *entry; |
885 | char info[6]; | ||
886 | int ret; | 991 | int ret; |
887 | 992 | ||
888 | mutex_lock(&applesmc_lock); | 993 | entry = applesmc_get_entry_by_index(key_at_index); |
889 | 994 | if (IS_ERR(entry)) | |
890 | ret = applesmc_get_key_at_index(key_at_index, key); | 995 | return PTR_ERR(entry); |
891 | 996 | ret = applesmc_read_entry(entry, sysfsbuf, entry->len); | |
892 | if (ret || !key[0]) { | 997 | if (ret) |
893 | mutex_unlock(&applesmc_lock); | ||
894 | |||
895 | return -EINVAL; | ||
896 | } | ||
897 | |||
898 | ret = applesmc_get_key_type(key, info); | ||
899 | |||
900 | if (ret) { | ||
901 | mutex_unlock(&applesmc_lock); | ||
902 | |||
903 | return ret; | 998 | return ret; |
904 | } | ||
905 | 999 | ||
906 | /* | 1000 | return entry->len; |
907 | * info[0] maximum value (APPLESMC_MAX_DATA_LENGTH) is much lower than | ||
908 | * PAGE_SIZE, so we don't need any checks before writing to sysfsbuf. | ||
909 | */ | ||
910 | ret = applesmc_read_key(key, sysfsbuf, info[0]); | ||
911 | |||
912 | mutex_unlock(&applesmc_lock); | ||
913 | |||
914 | if (!ret) { | ||
915 | return info[0]; | ||
916 | } else { | ||
917 | return ret; | ||
918 | } | ||
919 | } | 1001 | } |
920 | 1002 | ||
921 | static ssize_t applesmc_key_at_index_data_length_show(struct device *dev, | 1003 | static ssize_t applesmc_key_at_index_data_length_show(struct device *dev, |
922 | struct device_attribute *attr, char *sysfsbuf) | 1004 | struct device_attribute *attr, char *sysfsbuf) |
923 | { | 1005 | { |
924 | char key[5]; | 1006 | const struct applesmc_entry *entry; |
925 | char info[6]; | ||
926 | int ret; | ||
927 | |||
928 | mutex_lock(&applesmc_lock); | ||
929 | 1007 | ||
930 | ret = applesmc_get_key_at_index(key_at_index, key); | 1008 | entry = applesmc_get_entry_by_index(key_at_index); |
1009 | if (IS_ERR(entry)) | ||
1010 | return PTR_ERR(entry); | ||
931 | 1011 | ||
932 | if (ret || !key[0]) { | 1012 | return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", entry->len); |
933 | mutex_unlock(&applesmc_lock); | ||
934 | |||
935 | return -EINVAL; | ||
936 | } | ||
937 | |||
938 | ret = applesmc_get_key_type(key, info); | ||
939 | |||
940 | mutex_unlock(&applesmc_lock); | ||
941 | |||
942 | if (!ret) | ||
943 | return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", info[0]); | ||
944 | else | ||
945 | return ret; | ||
946 | } | 1013 | } |
947 | 1014 | ||
948 | static ssize_t applesmc_key_at_index_type_show(struct device *dev, | 1015 | static ssize_t applesmc_key_at_index_type_show(struct device *dev, |
949 | struct device_attribute *attr, char *sysfsbuf) | 1016 | struct device_attribute *attr, char *sysfsbuf) |
950 | { | 1017 | { |
951 | char key[5]; | 1018 | const struct applesmc_entry *entry; |
952 | char info[6]; | ||
953 | int ret; | ||
954 | |||
955 | mutex_lock(&applesmc_lock); | ||
956 | |||
957 | ret = applesmc_get_key_at_index(key_at_index, key); | ||
958 | |||
959 | if (ret || !key[0]) { | ||
960 | mutex_unlock(&applesmc_lock); | ||
961 | |||
962 | return -EINVAL; | ||
963 | } | ||
964 | |||
965 | ret = applesmc_get_key_type(key, info); | ||
966 | 1019 | ||
967 | mutex_unlock(&applesmc_lock); | 1020 | entry = applesmc_get_entry_by_index(key_at_index); |
1021 | if (IS_ERR(entry)) | ||
1022 | return PTR_ERR(entry); | ||
968 | 1023 | ||
969 | if (!ret) | 1024 | return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->type); |
970 | return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", info+1); | ||
971 | else | ||
972 | return ret; | ||
973 | } | 1025 | } |
974 | 1026 | ||
975 | static ssize_t applesmc_key_at_index_name_show(struct device *dev, | 1027 | static ssize_t applesmc_key_at_index_name_show(struct device *dev, |
976 | struct device_attribute *attr, char *sysfsbuf) | 1028 | struct device_attribute *attr, char *sysfsbuf) |
977 | { | 1029 | { |
978 | char key[5]; | 1030 | const struct applesmc_entry *entry; |
979 | int ret; | ||
980 | |||
981 | mutex_lock(&applesmc_lock); | ||
982 | 1031 | ||
983 | ret = applesmc_get_key_at_index(key_at_index, key); | 1032 | entry = applesmc_get_entry_by_index(key_at_index); |
1033 | if (IS_ERR(entry)) | ||
1034 | return PTR_ERR(entry); | ||
984 | 1035 | ||
985 | mutex_unlock(&applesmc_lock); | 1036 | return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key); |
986 | |||
987 | if (!ret && key[0]) | ||
988 | return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key); | ||
989 | else | ||
990 | return -EINVAL; | ||
991 | } | 1037 | } |
992 | 1038 | ||
993 | static ssize_t applesmc_key_at_index_show(struct device *dev, | 1039 | static ssize_t applesmc_key_at_index_show(struct device *dev, |
@@ -999,12 +1045,13 @@ static ssize_t applesmc_key_at_index_show(struct device *dev, | |||
999 | static ssize_t applesmc_key_at_index_store(struct device *dev, | 1045 | static ssize_t applesmc_key_at_index_store(struct device *dev, |
1000 | struct device_attribute *attr, const char *sysfsbuf, size_t count) | 1046 | struct device_attribute *attr, const char *sysfsbuf, size_t count) |
1001 | { | 1047 | { |
1002 | mutex_lock(&applesmc_lock); | 1048 | unsigned long newkey; |
1003 | 1049 | ||
1004 | key_at_index = simple_strtoul(sysfsbuf, NULL, 10); | 1050 | if (strict_strtoul(sysfsbuf, 10, &newkey) < 0 |
1005 | 1051 | || newkey >= smcreg.key_count) | |
1006 | mutex_unlock(&applesmc_lock); | 1052 | return -EINVAL; |
1007 | 1053 | ||
1054 | key_at_index = newkey; | ||
1008 | return count; | 1055 | return count; |
1009 | } | 1056 | } |
1010 | 1057 | ||
@@ -1646,10 +1693,15 @@ static int __init applesmc_init(void) | |||
1646 | goto out_driver; | 1693 | goto out_driver; |
1647 | } | 1694 | } |
1648 | 1695 | ||
1649 | ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_name.attr); | 1696 | /* create register cache */ |
1697 | ret = applesmc_init_smcreg(); | ||
1650 | if (ret) | 1698 | if (ret) |
1651 | goto out_device; | 1699 | goto out_device; |
1652 | 1700 | ||
1701 | ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_name.attr); | ||
1702 | if (ret) | ||
1703 | goto out_smcreg; | ||
1704 | |||
1653 | /* Create key enumeration sysfs files */ | 1705 | /* Create key enumeration sysfs files */ |
1654 | ret = sysfs_create_group(&pdev->dev.kobj, &key_enumeration_group); | 1706 | ret = sysfs_create_group(&pdev->dev.kobj, &key_enumeration_group); |
1655 | if (ret) | 1707 | if (ret) |
@@ -1751,6 +1803,8 @@ out_fans: | |||
1751 | sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); | 1803 | sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); |
1752 | out_name: | 1804 | out_name: |
1753 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); | 1805 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); |
1806 | out_smcreg: | ||
1807 | applesmc_destroy_smcreg(); | ||
1754 | out_device: | 1808 | out_device: |
1755 | platform_device_unregister(pdev); | 1809 | platform_device_unregister(pdev); |
1756 | out_driver: | 1810 | out_driver: |
@@ -1779,6 +1833,7 @@ static void __exit applesmc_exit(void) | |||
1779 | &fan_attribute_groups[--fans_handled]); | 1833 | &fan_attribute_groups[--fans_handled]); |
1780 | sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); | 1834 | sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); |
1781 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); | 1835 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); |
1836 | applesmc_destroy_smcreg(); | ||
1782 | platform_device_unregister(pdev); | 1837 | platform_device_unregister(pdev); |
1783 | platform_driver_unregister(&applesmc_driver); | 1838 | platform_driver_unregister(&applesmc_driver); |
1784 | release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); | 1839 | release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); |