aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c97
1 files changed, 60 insertions, 37 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 2b6c21d86b98..29ef505c487b 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -705,54 +705,85 @@ static int acpi_bus_get_perf_flags(struct acpi_device *device)
705} 705}
706 706
707static acpi_status 707static acpi_status
708acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device, 708acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
709 union acpi_object *package) 709 struct acpi_device_wakeup *wakeup)
710{ 710{
711 int i = 0; 711 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
712 union acpi_object *package = NULL;
712 union acpi_object *element = NULL; 713 union acpi_object *element = NULL;
714 acpi_status status;
715 int i = 0;
713 716
714 if (!device || !package || (package->package.count < 2)) 717 if (!wakeup)
715 return AE_BAD_PARAMETER; 718 return AE_BAD_PARAMETER;
716 719
720 /* _PRW */
721 status = acpi_evaluate_object(handle, "_PRW", NULL, &buffer);
722 if (ACPI_FAILURE(status)) {
723 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW"));
724 return status;
725 }
726
727 package = (union acpi_object *)buffer.pointer;
728
729 if (!package || (package->package.count < 2)) {
730 status = AE_BAD_DATA;
731 goto out;
732 }
733
717 element = &(package->package.elements[0]); 734 element = &(package->package.elements[0]);
718 if (!element) 735 if (!element) {
719 return AE_BAD_PARAMETER; 736 status = AE_BAD_DATA;
737 goto out;
738 }
720 if (element->type == ACPI_TYPE_PACKAGE) { 739 if (element->type == ACPI_TYPE_PACKAGE) {
721 if ((element->package.count < 2) || 740 if ((element->package.count < 2) ||
722 (element->package.elements[0].type != 741 (element->package.elements[0].type !=
723 ACPI_TYPE_LOCAL_REFERENCE) 742 ACPI_TYPE_LOCAL_REFERENCE)
724 || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) 743 || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) {
725 return AE_BAD_DATA; 744 status = AE_BAD_DATA;
726 device->wakeup.gpe_device = 745 goto out;
746 }
747 wakeup->gpe_device =
727 element->package.elements[0].reference.handle; 748 element->package.elements[0].reference.handle;
728 device->wakeup.gpe_number = 749 wakeup->gpe_number =
729 (u32) element->package.elements[1].integer.value; 750 (u32) element->package.elements[1].integer.value;
730 } else if (element->type == ACPI_TYPE_INTEGER) { 751 } else if (element->type == ACPI_TYPE_INTEGER) {
731 device->wakeup.gpe_number = element->integer.value; 752 wakeup->gpe_device = NULL;
732 } else 753 wakeup->gpe_number = element->integer.value;
733 return AE_BAD_DATA; 754 } else {
755 status = AE_BAD_DATA;
756 goto out;
757 }
734 758
735 element = &(package->package.elements[1]); 759 element = &(package->package.elements[1]);
736 if (element->type != ACPI_TYPE_INTEGER) { 760 if (element->type != ACPI_TYPE_INTEGER) {
737 return AE_BAD_DATA; 761 status = AE_BAD_DATA;
762 goto out;
738 } 763 }
739 device->wakeup.sleep_state = element->integer.value; 764 wakeup->sleep_state = element->integer.value;
740 765
741 if ((package->package.count - 2) > ACPI_MAX_HANDLES) { 766 if ((package->package.count - 2) > ACPI_MAX_HANDLES) {
742 return AE_NO_MEMORY; 767 status = AE_NO_MEMORY;
768 goto out;
743 } 769 }
744 device->wakeup.resources.count = package->package.count - 2; 770 wakeup->resources.count = package->package.count - 2;
745 for (i = 0; i < device->wakeup.resources.count; i++) { 771 for (i = 0; i < wakeup->resources.count; i++) {
746 element = &(package->package.elements[i + 2]); 772 element = &(package->package.elements[i + 2]);
747 if (element->type != ACPI_TYPE_LOCAL_REFERENCE) 773 if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
748 return AE_BAD_DATA; 774 status = AE_BAD_DATA;
775 goto out;
776 }
749 777
750 device->wakeup.resources.handles[i] = element->reference.handle; 778 wakeup->resources.handles[i] = element->reference.handle;
751 } 779 }
752 780
753 acpi_gpe_can_wake(device->wakeup.gpe_device, device->wakeup.gpe_number); 781 acpi_gpe_can_wake(wakeup->gpe_device, wakeup->gpe_number);
754 782
755 return AE_OK; 783 out:
784 kfree(buffer.pointer);
785
786 return status;
756} 787}
757 788
758static void acpi_bus_set_run_wake_flags(struct acpi_device *device) 789static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
@@ -787,26 +818,15 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
787static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device) 818static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
788{ 819{
789 acpi_status status = 0; 820 acpi_status status = 0;
790 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
791 union acpi_object *package = NULL;
792 int psw_error; 821 int psw_error;
793 822
794 /* _PRW */ 823 status = acpi_bus_extract_wakeup_device_power_package(device->handle,
795 status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer); 824 &device->wakeup);
796 if (ACPI_FAILURE(status)) {
797 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW"));
798 goto end;
799 }
800
801 package = (union acpi_object *)buffer.pointer;
802 status = acpi_bus_extract_wakeup_device_power_package(device, package);
803 if (ACPI_FAILURE(status)) { 825 if (ACPI_FAILURE(status)) {
804 ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package")); 826 ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));
805 goto end; 827 goto end;
806 } 828 }
807 829
808 kfree(buffer.pointer);
809
810 device->wakeup.flags.valid = 1; 830 device->wakeup.flags.valid = 1;
811 device->wakeup.prepare_count = 0; 831 device->wakeup.prepare_count = 0;
812 acpi_bus_set_run_wake_flags(device); 832 acpi_bus_set_run_wake_flags(device);
@@ -1351,6 +1371,7 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
1351 struct acpi_bus_ops *ops = context; 1371 struct acpi_bus_ops *ops = context;
1352 int type; 1372 int type;
1353 unsigned long long sta; 1373 unsigned long long sta;
1374 struct acpi_device_wakeup wakeup;
1354 struct acpi_device *device; 1375 struct acpi_device *device;
1355 acpi_status status; 1376 acpi_status status;
1356 int result; 1377 int result;
@@ -1360,8 +1381,10 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
1360 return AE_OK; 1381 return AE_OK;
1361 1382
1362 if (!(sta & ACPI_STA_DEVICE_PRESENT) && 1383 if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
1363 !(sta & ACPI_STA_DEVICE_FUNCTIONING)) 1384 !(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
1385 acpi_bus_extract_wakeup_device_power_package(handle, &wakeup);
1364 return AE_CTRL_DEPTH; 1386 return AE_CTRL_DEPTH;
1387 }
1365 1388
1366 /* 1389 /*
1367 * We may already have an acpi_device from a previous enumeration. If 1390 * We may already have an acpi_device from a previous enumeration. If