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

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: Enable Chromeos ACPI buffer handling. 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
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 #include "chromeos_acpi.h"
40
39 MODULE_AUTHOR("Google Inc."); 41 MODULE_AUTHOR("Google Inc.");
40 MODULE_DESCRIPTION("Chrome OS Extras Driver"); 42 MODULE_DESCRIPTION("Chrome OS Extras Driver");
41 MODULE_LICENSE("GPL"); 43 MODULE_LICENSE("GPL");
42 44
43 #define MY_LOGPREFIX "chromeos_acpi: " 45 #define MY_LOGPREFIX "chromeos_acpi: "
44 #define MY_ERR KERN_ERR MY_LOGPREFIX 46 #define MY_ERR KERN_ERR MY_LOGPREFIX
45 #define MY_NOTICE KERN_NOTICE MY_LOGPREFIX 47 #define MY_NOTICE KERN_NOTICE MY_LOGPREFIX
46 #define MY_INFO KERN_INFO MY_LOGPREFIX 48 #define MY_INFO KERN_INFO MY_LOGPREFIX
47 49
48 /* ACPI method name for MLST; the response for this method is a 50 /* ACPI method name for MLST; the response for this method is a
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 */ 108 */
107 struct chromeos_acpi_dev { 109 struct chromeos_acpi_dev {
108 struct platform_device *p_dev; 110 struct platform_device *p_dev;
109 struct acpi_attribute *attributes; 111 struct acpi_attribute *attributes;
110 struct acpi_attribute_group *groups; 112 struct acpi_attribute_group *groups;
111 }; 113 };
112 114
113 static struct chromeos_acpi_dev chromeos_acpi = { }; 115 static struct chromeos_acpi_dev chromeos_acpi = { };
114 116
115 117
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 /* 118 /*
124 * To show attribute value just access the container structure's `value' 119 * To show attribute value just access the container structure's `value'
125 * field. 120 * field.
126 */ 121 */
127 static ssize_t show_acpi_attribute(struct device *dev, 122 static ssize_t show_acpi_attribute(struct device *dev,
128 struct device_attribute *attr, char *buf) 123 struct device_attribute *attr, char *buf)
129 { 124 {
130 struct acpi_attribute *paa; 125 struct acpi_attribute *paa;
131 126
132 paa = container_of(attr, struct acpi_attribute, dev_attr); 127 paa = container_of(attr, struct acpi_attribute, dev_attr);
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 element->type); 322 element->type);
328 continue; 323 continue;
329 } 324 }
330 aag->ag.attrs[j++] = &paa->dev_attr.attr; 325 aag->ag.attrs[j++] = &paa->dev_attr.attr;
331 } 326 }
332 327
333 if (sysfs_create_group(&chromeos_acpi.p_dev->dev.kobj, &aag->ag)) 328 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); 329 printk(MY_ERR "failed to create group %s.%d\n", pm, instance);
335 } 330 }
336 331
332
333 #ifdef CONFIG_CHROMEOS
Olof Johansson 2011/03/14 21:24:32 It would be preferred to just change the Kconfig t
vb 2011/03/14 22:00:04 I am not sure I follow: this code is not needed un
Olof Johansson 2011/03/14 22:28:47 There's not much use in using CONFIG_CHROMEOS_ACPI
vb 2011/03/14 22:55:25 Ah, that's exactly the thing: the case like now, w
337 /* 334 /*
338 * handle_single_int() extract a single int value 335 * handle_single_int() extract a single int value
339 * 336 *
340 * @po: package contents as returned by ACPI 337 * @po: package contents as returned by ACPI
341 * @found: integer pointer to store the value in 338 * @found: integer pointer to store the value in
342 * 339 *
343 */ 340 */
344 static void handle_single_int(union acpi_object *po, int *found) 341 static void handle_single_int(union acpi_object *po, int *found)
345 { 342 {
346 union acpi_object *element = po->package.elements; 343 union acpi_object *element = po->package.elements;
347 344
348 if (!element) { 345 if (!element) {
349 WARN_ON(1); 346 WARN_ON(1);
350 return; 347 return;
351 } 348 }
352 349
353 if (element->type == ACPI_TYPE_INTEGER) 350 if (element->type == ACPI_TYPE_INTEGER)
354 *found = (int) element->integer.value; 351 *found = (int) element->integer.value;
355 else 352 else
356 printk(MY_ERR "acpi_object unexpected type %d, expected int\n", 353 printk(MY_ERR "acpi_object unexpected type %d, expected int\n",
357 element->type); 354 element->type);
358 } 355 }
359 356 #endif
360 357
361 /* 358 /*
362 * handle_acpi_package() create sysfs group including attributes 359 * handle_acpi_package() create sysfs group including attributes
363 * representing an ACPI package. 360 * representing an ACPI package.
364 * 361 *
365 * @po: package contents as returned by ACPI 362 * @po: package contents as returned by ACPI
366 * @pm: name of the group 363 * @pm: name of the group
367 * 364 *
368 * Scalar objects included in the package get sys fs attributes created for 365 * 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 366 * them. Nested packages are passed to a function creating a sys fs group per
(...skipping 16 matching lines...) Expand all
386 break; 383 break;
387 384
388 case ACPI_TYPE_STRING: 385 case ACPI_TYPE_STRING:
389 copy_size = min(element->string.length, 386 copy_size = min(element->string.length,
390 sizeof(attr_value) - 1); 387 sizeof(attr_value) - 1);
391 memcpy(attr_value, element->string.pointer, copy_size); 388 memcpy(attr_value, element->string.pointer, copy_size);
392 attr_value[copy_size] = '\0'; 389 attr_value[copy_size] = '\0';
393 add_sysfs_attribute(attr_value, pm, count, j); 390 add_sysfs_attribute(attr_value, pm, count, j);
394 break; 391 break;
395 392
393 case ACPI_TYPE_BUFFER: {
394 char *base, *p;
395 int i;
396 unsigned room_left;
397 /* Include this many characters per line */
398 unsigned char_per_line = 16;
399 unsigned string_buffer_size =
400 /* three characters to display one byte */
401 element->buffer.length * 3 +
402 /* one newline per line, all rounded up, plust
Randall Spangler 2011/03/14 21:22:28 plust?
vb 2011/03/14 22:00:04 Done.
403 * extra newline in the end, plus terminating
404 * zero, hence + 4
405 */
406 element->buffer.length/char_per_line + 4;
407
408 if (string_buffer_size > sizeof(attr_value)) {
409 p = kzalloc(string_buffer_size, GFP_KERNEL);
410 if (!p) {
411 printk(MY_ERR "out of memory in %s!\n",
412 __func__);
413 break;
414 }
415 } else {
416 p = attr_value;
417 }
418
419 base = p;
420 room_left = string_buffer_size;
421 for (i = 0; i < element->buffer.length; i++) {
422 int printed;
423 printed = snprintf(p, room_left, " %2.2x",
424 element->buffer.pointer[i]);
425 room_left -= printed;
426 p += printed;
427 if (((i + 1) % char_per_line) == 0) {
Randall Spangler 2011/03/14 21:22:28 Check for room_left != 0 If somehow printed==room
vb 2011/03/14 22:00:04 Done.
428 room_left--;
429 *p++ = '\n';
430 }
431 }
432 *p++ = '\n';
Randall Spangler 2011/03/14 21:22:28 Same paranoia here - check room_left>=2
vb 2011/03/14 22:00:04 Done.
433 *p++ = '\0';
434 add_sysfs_attribute(base, pm, count, j);
435 if (string_buffer_size > sizeof(attr_value))
436 kfree(p);
437 break;
438 }
Olof Johansson 2011/03/14 21:24:32 It is common practice to pass the binary data over
vb 2011/03/14 22:00:04 This would be a much larger change, because as of
Olof Johansson 2011/03/14 22:28:47 SGTM
vb 2011/03/14 22:55:25 opened http://code.google.com/p/chromium-os/issue
396 case ACPI_TYPE_PACKAGE: 439 case ACPI_TYPE_PACKAGE:
397 handle_nested_acpi_package(element, pm, count, j); 440 handle_nested_acpi_package(element, pm, count, j);
398 break; 441 break;
399 442
400 default: 443 default:
401 » » » printk(MY_ERR "ignoring type %d\n", element->type); 444 » » » printk(MY_ERR "ignoring type %d (%s)\n",
445 » » » element->type, pm);
402 break; 446 break;
403 } 447 }
404 } 448 }
405 } 449 }
406 450
407 451
408 /* 452 /*
409 * add_acpi_method() evaluate an ACPI method and create sysfs attributes. 453 * add_acpi_method() evaluate an ACPI method and create sysfs attributes.
410 * 454 *
411 * @device: ACPI device 455 * @device: ACPI device
(...skipping 14 matching lines...) Expand all
426 printk(MY_ERR "failed to retrieve %s (%d)\n", pm, status); 470 printk(MY_ERR "failed to retrieve %s (%d)\n", pm, status);
427 return; 471 return;
428 } 472 }
429 473
430 po = output.pointer; 474 po = output.pointer;
431 475
432 if (po->type != ACPI_TYPE_PACKAGE) 476 if (po->type != ACPI_TYPE_PACKAGE)
433 printk(MY_ERR "%s is not a package, ignored\n", pm); 477 printk(MY_ERR "%s is not a package, ignored\n", pm);
434 else 478 else
435 handle_acpi_package(po, pm); 479 handle_acpi_package(po, pm);
436 480 #ifdef CONFIG_CHROMEOS
437 /* Need to export a couple of variables to chromeos.c */ 481 /* Need to export a couple of variables to chromeos.c */
438 if (!strncmp(pm, "CHNV", 4)) 482 if (!strncmp(pm, "CHNV", 4))
439 handle_single_int(po, &chromeos_acpi_chnv); 483 handle_single_int(po, &chromeos_acpi_chnv);
440 else if (!strncmp(pm, "CHSW", 4)) 484 else if (!strncmp(pm, "CHSW", 4))
441 handle_single_int(po, &chromeos_acpi_chsw); 485 handle_single_int(po, &chromeos_acpi_chsw);
442 486 #endif
443 kfree(output.pointer); 487 kfree(output.pointer);
444 } 488 }
445 489
446 /* 490 /*
447 * chromeos_process_mlst() Evaluate the MLST method and add methods listed 491 * chromeos_process_mlst() Evaluate the MLST method and add methods listed
448 * in the response. 492 * in the response.
449 * 493 *
450 * @device: ACPI device 494 * @device: ACPI device
451 * 495 *
452 * Returns: 0 if successful, non-zero if error. 496 * Returns: 0 if successful, non-zero if error.
(...skipping 22 matching lines...) Expand all
475 kfree(output.pointer); 519 kfree(output.pointer);
476 return -EINVAL; 520 return -EINVAL;
477 } 521 }
478 522
479 for (j = 0; j < po->package.count; j++) { 523 for (j = 0; j < po->package.count; j++) {
480 union acpi_object *element = po->package.elements + j; 524 union acpi_object *element = po->package.elements + j;
481 int copy_size = 0; 525 int copy_size = 0;
482 char method[ACPI_NAME_SIZE + 1]; 526 char method[ACPI_NAME_SIZE + 1];
483 527
484 if (element->type == ACPI_TYPE_STRING) { 528 if (element->type == ACPI_TYPE_STRING) {
485 » » » copy_size = min(element->string.length, ACPI_NAME_SIZE); 529 » » » copy_size = min(element->string.length,
530 » » » » » (u32)ACPI_NAME_SIZE);
Olof Johansson 2011/03/14 21:24:32 Is this cast needed?
vb 2011/03/14 22:00:04 yes, for some weird reason min() operates with poi
Olof Johansson 2011/03/14 22:28:47 Ah, yes, it's trying to be type safe. Ok.
486 memcpy(method, element->string.pointer, copy_size); 531 memcpy(method, element->string.pointer, copy_size);
487 method[copy_size] = '\0'; 532 method[copy_size] = '\0';
488 add_acpi_method(device, method); 533 add_acpi_method(device, method);
489 } else { 534 } else {
490 pr_debug(MY_LOGPREFIX "ignoring type %d\n", 535 pr_debug(MY_LOGPREFIX "ignoring type %d\n",
491 element->type); 536 element->type);
492 } 537 }
493 } 538 }
494 539
495 kfree(output.pointer); 540 kfree(output.pointer);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 } 576 }
532 577
533 ret = acpi_bus_register_driver(&chromeos_acpi_driver); 578 ret = acpi_bus_register_driver(&chromeos_acpi_driver);
534 if (ret < 0) { 579 if (ret < 0) {
535 printk(MY_ERR "failed to register driver (%d)\n", ret); 580 printk(MY_ERR "failed to register driver (%d)\n", ret);
536 platform_device_unregister(chromeos_acpi.p_dev); 581 platform_device_unregister(chromeos_acpi.p_dev);
537 chromeos_acpi.p_dev = NULL; 582 chromeos_acpi.p_dev = NULL;
538 return ret; 583 return ret;
539 } 584 }
540 585
586 #ifdef CONFIG_CHROMEOS
541 chromeos_acpi_available = true; 587 chromeos_acpi_available = true;
542 588 #endif
543 return 0; 589 return 0;
544 } 590 }
545 subsys_initcall(chromeos_acpi_init); 591
592 static void chromeos_acpi_exit(void)
593 {
594 » acpi_bus_unregister_driver(&chromeos_acpi_driver);
595
596 » while (chromeos_acpi.groups) {
597 » » struct acpi_attribute_group *aag;
598 » » aag = chromeos_acpi.groups;
599 » » chromeos_acpi.groups = aag->next_acpi_attr_group;
600 » » sysfs_remove_group(&chromeos_acpi.p_dev->dev.kobj, &aag->ag);
601 » » kfree(aag);
602 » }
603
604 » while (chromeos_acpi.attributes) {
605 » » struct acpi_attribute *aa = chromeos_acpi.attributes;
606 » » chromeos_acpi.attributes = aa->next_acpi_attr;
607 » » device_remove_file(&chromeos_acpi.p_dev->dev, &aa->dev_attr);
608 » » kfree(aa);
609 » }
610
611 » platform_device_unregister(chromeos_acpi.p_dev);
612 » printk(MY_INFO "removed\n");
Olof Johansson 2011/03/14 21:24:32 Shouldn't there be a chromeos_acpi_available=false
vb 2011/03/14 22:00:04 good point, added.
613 }
614
615 module_init(chromeos_acpi_init);
616 module_exit(chromeos_acpi_exit);
Olof Johansson 2011/03/14 21:24:32 You need a MODULE_LICENSE, MODULE_AUTHOR, etc here
vb 2011/03/14 22:00:04 They are there in the top of the file. You mean th
Olof Johansson 2011/03/14 22:28:47 Oops, missed them. Please move them to the bottom
vb 2011/03/14 22:55:25 Done.
617
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698