Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(376)

Side by Side Diff: drivers/platform/x86/chromeos_acpi.c

Issue 6690023: CHROMIUMOS: chromeos_acpi: Introduce ability to handle buffers. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/kernel.git@master
Patch Set: Address review comments Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « drivers/platform/x86/chromeos.c ('k') | include/linux/chromeos_platform.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * chromeos_acpi.c - ChromeOS specific ACPI support 2 * chromeos_acpi.c - ChromeOS specific ACPI support
3 * 3 *
4 * 4 *
5 * Copyright (C) 2011 The Chromium OS Authors 5 * Copyright (C) 2011 The Chromium OS Authors
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or 9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version. 10 * (at your option) any later version.
(...skipping 18 matching lines...) Expand all
29 * All values are presented in the string form (numbers as decimal values) and 29 * All values are presented in the string form (numbers as decimal values) and
30 * can be accessed as the contents of the appropriate read only files in the 30 * can be accessed as the contents of the appropriate read only files in the
31 * sysfs directory tree originating in /sys/devices/platform/chromeos_acpi. 31 * sysfs directory tree originating in /sys/devices/platform/chromeos_acpi.
32 */ 32 */
33 33
34 #include <linux/kernel.h> 34 #include <linux/kernel.h>
35 #include <linux/module.h> 35 #include <linux/module.h>
36 #include <linux/platform_device.h> 36 #include <linux/platform_device.h>
37 #include <linux/acpi.h> 37 #include <linux/acpi.h>
38 38
39 MODULE_AUTHOR("Google Inc."); 39 #include "chromeos_acpi.h"
40 MODULE_DESCRIPTION("Chrome OS Extras Driver");
41 MODULE_LICENSE("GPL");
42 40
43 #define MY_LOGPREFIX "chromeos_acpi: " 41 #define MY_LOGPREFIX "chromeos_acpi: "
44 #define MY_ERR KERN_ERR MY_LOGPREFIX 42 #define MY_ERR KERN_ERR MY_LOGPREFIX
45 #define MY_NOTICE KERN_NOTICE MY_LOGPREFIX 43 #define MY_NOTICE KERN_NOTICE MY_LOGPREFIX
46 #define MY_INFO KERN_INFO MY_LOGPREFIX 44 #define MY_INFO KERN_INFO MY_LOGPREFIX
47 45
48 /* ACPI method name for MLST; the response for this method is a 46 /* ACPI method name for MLST; the response for this method is a
49 * package of strings listing the methods which should be reflected in 47 * package of strings listing the methods which should be reflected in
50 * sysfs. */ 48 * sysfs. */
51 #define MLST_METHOD "MLST" 49 #define MLST_METHOD "MLST"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 */ 104 */
107 struct chromeos_acpi_dev { 105 struct chromeos_acpi_dev {
108 struct platform_device *p_dev; 106 struct platform_device *p_dev;
109 struct acpi_attribute *attributes; 107 struct acpi_attribute *attributes;
110 struct acpi_attribute_group *groups; 108 struct acpi_attribute_group *groups;
111 }; 109 };
112 110
113 static struct chromeos_acpi_dev chromeos_acpi = { }; 111 static struct chromeos_acpi_dev chromeos_acpi = { };
114 112
115 113
116 /* Values set at probe time */
117 int chromeos_acpi_chnv = -1;
118 int chromeos_acpi_chsw = -1;
119
120 bool chromeos_acpi_available;
121
122
123 /* 114 /*
124 * To show attribute value just access the container structure's `value' 115 * To show attribute value just access the container structure's `value'
125 * field. 116 * field.
126 */ 117 */
127 static ssize_t show_acpi_attribute(struct device *dev, 118 static ssize_t show_acpi_attribute(struct device *dev,
128 struct device_attribute *attr, char *buf) 119 struct device_attribute *attr, char *buf)
129 { 120 {
130 struct acpi_attribute *paa; 121 struct acpi_attribute *paa;
131 122
132 paa = container_of(attr, struct acpi_attribute, dev_attr); 123 paa = container_of(attr, struct acpi_attribute, dev_attr);
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 element->type); 318 element->type);
328 continue; 319 continue;
329 } 320 }
330 aag->ag.attrs[j++] = &paa->dev_attr.attr; 321 aag->ag.attrs[j++] = &paa->dev_attr.attr;
331 } 322 }
332 323
333 if (sysfs_create_group(&chromeos_acpi.p_dev->dev.kobj, &aag->ag)) 324 if (sysfs_create_group(&chromeos_acpi.p_dev->dev.kobj, &aag->ag))
334 printk(MY_ERR "failed to create group %s.%d\n", pm, instance); 325 printk(MY_ERR "failed to create group %s.%d\n", pm, instance);
335 } 326 }
336 327
328
329 #ifdef CONFIG_CHROMEOS
337 /* 330 /*
338 * handle_single_int() extract a single int value 331 * handle_single_int() extract a single int value
339 * 332 *
340 * @po: package contents as returned by ACPI 333 * @po: package contents as returned by ACPI
341 * @found: integer pointer to store the value in 334 * @found: integer pointer to store the value in
342 * 335 *
343 */ 336 */
344 static void handle_single_int(union acpi_object *po, int *found) 337 static void handle_single_int(union acpi_object *po, int *found)
345 { 338 {
346 union acpi_object *element = po->package.elements; 339 union acpi_object *element = po->package.elements;
347 340
348 if (!element) { 341 if (!element) {
349 WARN_ON(1); 342 WARN_ON(1);
350 return; 343 return;
351 } 344 }
352 345
353 if (element->type == ACPI_TYPE_INTEGER) 346 if (element->type == ACPI_TYPE_INTEGER)
354 *found = (int) element->integer.value; 347 *found = (int) element->integer.value;
355 else 348 else
356 printk(MY_ERR "acpi_object unexpected type %d, expected int\n", 349 printk(MY_ERR "acpi_object unexpected type %d, expected int\n",
357 element->type); 350 element->type);
358 } 351 }
359 352 #endif
360 353
361 /* 354 /*
362 * handle_acpi_package() create sysfs group including attributes 355 * handle_acpi_package() create sysfs group including attributes
363 * representing an ACPI package. 356 * representing an ACPI package.
364 * 357 *
365 * @po: package contents as returned by ACPI 358 * @po: package contents as returned by ACPI
366 * @pm: name of the group 359 * @pm: name of the group
367 * 360 *
368 * Scalar objects included in the package get sys fs attributes created for 361 * Scalar objects included in the package get sys fs attributes created for
369 * them. Nested packages are passed to a function creating a sys fs group per 362 * them. Nested packages are passed to a function creating a sys fs group per
(...skipping 16 matching lines...) Expand all
386 break; 379 break;
387 380
388 case ACPI_TYPE_STRING: 381 case ACPI_TYPE_STRING:
389 copy_size = min(element->string.length, 382 copy_size = min(element->string.length,
390 sizeof(attr_value) - 1); 383 sizeof(attr_value) - 1);
391 memcpy(attr_value, element->string.pointer, copy_size); 384 memcpy(attr_value, element->string.pointer, copy_size);
392 attr_value[copy_size] = '\0'; 385 attr_value[copy_size] = '\0';
393 add_sysfs_attribute(attr_value, pm, count, j); 386 add_sysfs_attribute(attr_value, pm, count, j);
394 break; 387 break;
395 388
389 case ACPI_TYPE_BUFFER: {
390 char *base, *p;
391 int i;
392 unsigned room_left;
393 /* Include this many characters per line */
394 unsigned char_per_line = 16;
395 unsigned string_buffer_size =
396 /* three characters to display one byte */
397 element->buffer.length * 3 +
398 /* one newline per line, all rounded up, plus
399 * extra newline in the end, plus terminating
400 * zero, hence + 4
401 */
402 element->buffer.length/char_per_line + 4;
403
404 if (string_buffer_size > sizeof(attr_value)) {
405 p = kzalloc(string_buffer_size, GFP_KERNEL);
406 if (!p) {
407 printk(MY_ERR "out of memory in %s!\n",
408 __func__);
409 break;
410 }
411 } else {
412 p = attr_value;
413 }
414
415 base = p;
416 room_left = string_buffer_size;
417 for (i = 0; i < element->buffer.length; i++) {
418 int printed;
419 printed = snprintf(p, room_left, " %2.2x",
420 element->buffer.pointer[i]);
421 room_left -= printed;
422 p += printed;
423 if (((i + 1) % char_per_line) == 0) {
424 if (!room_left)
425 break;
426 room_left--;
427 *p++ = '\n';
428 }
429 }
430 if (room_left < 2) {
431 printk(MY_ERR "%s: no room in the buffer!\n",
432 __func__);
433 *p = '\0';
434 } else {
435 *p++ = '\n';
436 *p++ = '\0';
437 }
438 add_sysfs_attribute(base, pm, count, j);
439 if (string_buffer_size > sizeof(attr_value))
440 kfree(p);
441 break;
442 }
396 case ACPI_TYPE_PACKAGE: 443 case ACPI_TYPE_PACKAGE:
397 handle_nested_acpi_package(element, pm, count, j); 444 handle_nested_acpi_package(element, pm, count, j);
398 break; 445 break;
399 446
400 default: 447 default:
401 » » » printk(MY_ERR "ignoring type %d\n", element->type); 448 » » » printk(MY_ERR "ignoring type %d (%s)\n",
449 » » » element->type, pm);
402 break; 450 break;
403 } 451 }
404 } 452 }
405 } 453 }
406 454
407 455
408 /* 456 /*
409 * add_acpi_method() evaluate an ACPI method and create sysfs attributes. 457 * add_acpi_method() evaluate an ACPI method and create sysfs attributes.
410 * 458 *
411 * @device: ACPI device 459 * @device: ACPI device
(...skipping 14 matching lines...) Expand all
426 printk(MY_ERR "failed to retrieve %s (%d)\n", pm, status); 474 printk(MY_ERR "failed to retrieve %s (%d)\n", pm, status);
427 return; 475 return;
428 } 476 }
429 477
430 po = output.pointer; 478 po = output.pointer;
431 479
432 if (po->type != ACPI_TYPE_PACKAGE) 480 if (po->type != ACPI_TYPE_PACKAGE)
433 printk(MY_ERR "%s is not a package, ignored\n", pm); 481 printk(MY_ERR "%s is not a package, ignored\n", pm);
434 else 482 else
435 handle_acpi_package(po, pm); 483 handle_acpi_package(po, pm);
436 484 #ifdef CONFIG_CHROMEOS
437 /* Need to export a couple of variables to chromeos.c */ 485 /* Need to export a couple of variables to chromeos.c */
438 if (!strncmp(pm, "CHNV", 4)) 486 if (!strncmp(pm, "CHNV", 4))
439 handle_single_int(po, &chromeos_acpi_chnv); 487 handle_single_int(po, &chromeos_acpi_chnv);
440 else if (!strncmp(pm, "CHSW", 4)) 488 else if (!strncmp(pm, "CHSW", 4))
441 handle_single_int(po, &chromeos_acpi_chsw); 489 handle_single_int(po, &chromeos_acpi_chsw);
442 490 #endif
443 kfree(output.pointer); 491 kfree(output.pointer);
444 } 492 }
445 493
446 /* 494 /*
447 * chromeos_process_mlst() Evaluate the MLST method and add methods listed 495 * chromeos_process_mlst() Evaluate the MLST method and add methods listed
448 * in the response. 496 * in the response.
449 * 497 *
450 * @device: ACPI device 498 * @device: ACPI device
451 * 499 *
452 * Returns: 0 if successful, non-zero if error. 500 * Returns: 0 if successful, non-zero if error.
(...skipping 22 matching lines...) Expand all
475 kfree(output.pointer); 523 kfree(output.pointer);
476 return -EINVAL; 524 return -EINVAL;
477 } 525 }
478 526
479 for (j = 0; j < po->package.count; j++) { 527 for (j = 0; j < po->package.count; j++) {
480 union acpi_object *element = po->package.elements + j; 528 union acpi_object *element = po->package.elements + j;
481 int copy_size = 0; 529 int copy_size = 0;
482 char method[ACPI_NAME_SIZE + 1]; 530 char method[ACPI_NAME_SIZE + 1];
483 531
484 if (element->type == ACPI_TYPE_STRING) { 532 if (element->type == ACPI_TYPE_STRING) {
485 » » » copy_size = min(element->string.length, ACPI_NAME_SIZE); 533 » » » copy_size = min(element->string.length,
534 » » » » » (u32)ACPI_NAME_SIZE);
486 memcpy(method, element->string.pointer, copy_size); 535 memcpy(method, element->string.pointer, copy_size);
487 method[copy_size] = '\0'; 536 method[copy_size] = '\0';
488 add_acpi_method(device, method); 537 add_acpi_method(device, method);
489 } else { 538 } else {
490 pr_debug(MY_LOGPREFIX "ignoring type %d\n", 539 pr_debug(MY_LOGPREFIX "ignoring type %d\n",
491 element->type); 540 element->type);
492 } 541 }
493 } 542 }
494 543
495 kfree(output.pointer); 544 kfree(output.pointer);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 } 580 }
532 581
533 ret = acpi_bus_register_driver(&chromeos_acpi_driver); 582 ret = acpi_bus_register_driver(&chromeos_acpi_driver);
534 if (ret < 0) { 583 if (ret < 0) {
535 printk(MY_ERR "failed to register driver (%d)\n", ret); 584 printk(MY_ERR "failed to register driver (%d)\n", ret);
536 platform_device_unregister(chromeos_acpi.p_dev); 585 platform_device_unregister(chromeos_acpi.p_dev);
537 chromeos_acpi.p_dev = NULL; 586 chromeos_acpi.p_dev = NULL;
538 return ret; 587 return ret;
539 } 588 }
540 589
590 #ifdef CONFIG_CHROMEOS
541 chromeos_acpi_available = true; 591 chromeos_acpi_available = true;
542 592 #endif
543 return 0; 593 return 0;
544 } 594 }
545 subsys_initcall(chromeos_acpi_init); 595
596 static void chromeos_acpi_exit(void)
597 {
598 #ifdef CONFIG_CHROMEOS
599 » chromeos_acpi_available = false;
600 #endif
601 » acpi_bus_unregister_driver(&chromeos_acpi_driver);
602
603 » while (chromeos_acpi.groups) {
604 » » struct acpi_attribute_group *aag;
605 » » aag = chromeos_acpi.groups;
606 » » chromeos_acpi.groups = aag->next_acpi_attr_group;
607 » » sysfs_remove_group(&chromeos_acpi.p_dev->dev.kobj, &aag->ag);
608 » » kfree(aag);
609 » }
610
611 » while (chromeos_acpi.attributes) {
612 » » struct acpi_attribute *aa = chromeos_acpi.attributes;
613 » » chromeos_acpi.attributes = aa->next_acpi_attr;
614 » » device_remove_file(&chromeos_acpi.p_dev->dev, &aa->dev_attr);
615 » » kfree(aa);
616 » }
617
618 » platform_device_unregister(chromeos_acpi.p_dev);
619 » printk(MY_INFO "removed\n");
620 }
621
622 module_init(chromeos_acpi_init);
623 module_exit(chromeos_acpi_exit);
624
625 MODULE_LICENSE("GPL");
626 MODULE_AUTHOR("Google Inc.");
627 MODULE_DESCRIPTION("Chrome OS ACPI Driver");
OLDNEW
« no previous file with comments | « drivers/platform/x86/chromeos.c ('k') | include/linux/chromeos_platform.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698