diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-09-11 09:22:27 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-09-11 09:22:27 -0400 |
commit | 0a733e6effb4a429551d8b000aa02750cc7e04ba (patch) | |
tree | 72ca7e1a9080b424b985b7c5633f9e5404806a1d | |
parent | 1a7b0ecbbc1219895f48934ff5549a3594db3480 (diff) | |
parent | 11b88ee275ec8590a373396888c2460ee89364d6 (diff) |
Merge branch 'acpi-bind'
* acpi-bind:
ACPI / bind: Prefer device objects with _STA to those without it
-rw-r--r-- | drivers/acpi/glue.c | 35 |
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 94672297e1b1..10f0f40587bb 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -79,6 +79,9 @@ static struct acpi_bus_type *acpi_get_bus_type(struct device *dev) | |||
79 | return ret; | 79 | return ret; |
80 | } | 80 | } |
81 | 81 | ||
82 | #define FIND_CHILD_MIN_SCORE 1 | ||
83 | #define FIND_CHILD_MAX_SCORE 2 | ||
84 | |||
82 | static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used, | 85 | static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used, |
83 | void *not_used, void **ret_p) | 86 | void *not_used, void **ret_p) |
84 | { | 87 | { |
@@ -92,14 +95,17 @@ static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used, | |||
92 | return AE_OK; | 95 | return AE_OK; |
93 | } | 96 | } |
94 | 97 | ||
95 | static bool acpi_extra_checks_passed(acpi_handle handle, bool is_bridge) | 98 | static int do_find_child_checks(acpi_handle handle, bool is_bridge) |
96 | { | 99 | { |
100 | bool sta_present = true; | ||
97 | unsigned long long sta; | 101 | unsigned long long sta; |
98 | acpi_status status; | 102 | acpi_status status; |
99 | 103 | ||
100 | status = acpi_bus_get_status_handle(handle, &sta); | 104 | status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); |
101 | if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED)) | 105 | if (status == AE_NOT_FOUND) |
102 | return false; | 106 | sta_present = false; |
107 | else if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED)) | ||
108 | return -ENODEV; | ||
103 | 109 | ||
104 | if (is_bridge) { | 110 | if (is_bridge) { |
105 | void *test = NULL; | 111 | void *test = NULL; |
@@ -107,16 +113,17 @@ static bool acpi_extra_checks_passed(acpi_handle handle, bool is_bridge) | |||
107 | /* Check if this object has at least one child device. */ | 113 | /* Check if this object has at least one child device. */ |
108 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, | 114 | acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, |
109 | acpi_dev_present, NULL, NULL, &test); | 115 | acpi_dev_present, NULL, NULL, &test); |
110 | return !!test; | 116 | if (!test) |
117 | return -ENODEV; | ||
111 | } | 118 | } |
112 | return true; | 119 | return sta_present ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE; |
113 | } | 120 | } |
114 | 121 | ||
115 | struct find_child_context { | 122 | struct find_child_context { |
116 | u64 addr; | 123 | u64 addr; |
117 | bool is_bridge; | 124 | bool is_bridge; |
118 | acpi_handle ret; | 125 | acpi_handle ret; |
119 | bool ret_checked; | 126 | int ret_score; |
120 | }; | 127 | }; |
121 | 128 | ||
122 | static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used, | 129 | static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used, |
@@ -125,6 +132,7 @@ static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used, | |||
125 | struct find_child_context *context = data; | 132 | struct find_child_context *context = data; |
126 | unsigned long long addr; | 133 | unsigned long long addr; |
127 | acpi_status status; | 134 | acpi_status status; |
135 | int score; | ||
128 | 136 | ||
129 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr); | 137 | status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &addr); |
130 | if (ACPI_FAILURE(status) || addr != context->addr) | 138 | if (ACPI_FAILURE(status) || addr != context->addr) |
@@ -144,15 +152,20 @@ static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used, | |||
144 | * its handle if so. Second, check the same for the object that we've | 152 | * its handle if so. Second, check the same for the object that we've |
145 | * just found. | 153 | * just found. |
146 | */ | 154 | */ |
147 | if (!context->ret_checked) { | 155 | if (!context->ret_score) { |
148 | if (acpi_extra_checks_passed(context->ret, context->is_bridge)) | 156 | score = do_find_child_checks(context->ret, context->is_bridge); |
157 | if (score == FIND_CHILD_MAX_SCORE) | ||
149 | return AE_CTRL_TERMINATE; | 158 | return AE_CTRL_TERMINATE; |
150 | else | 159 | else |
151 | context->ret_checked = true; | 160 | context->ret_score = score; |
152 | } | 161 | } |
153 | if (acpi_extra_checks_passed(handle, context->is_bridge)) { | 162 | score = do_find_child_checks(handle, context->is_bridge); |
163 | if (score == FIND_CHILD_MAX_SCORE) { | ||
154 | context->ret = handle; | 164 | context->ret = handle; |
155 | return AE_CTRL_TERMINATE; | 165 | return AE_CTRL_TERMINATE; |
166 | } else if (score > context->ret_score) { | ||
167 | context->ret = handle; | ||
168 | context->ret_score = score; | ||
156 | } | 169 | } |
157 | return AE_OK; | 170 | return AE_OK; |
158 | } | 171 | } |