aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-09-11 09:22:27 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-09-11 09:22:27 -0400
commit0a733e6effb4a429551d8b000aa02750cc7e04ba (patch)
tree72ca7e1a9080b424b985b7c5633f9e5404806a1d
parent1a7b0ecbbc1219895f48934ff5549a3594db3480 (diff)
parent11b88ee275ec8590a373396888c2460ee89364d6 (diff)
Merge branch 'acpi-bind'
* acpi-bind: ACPI / bind: Prefer device objects with _STA to those without it
-rw-r--r--drivers/acpi/glue.c35
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
82static acpi_status acpi_dev_present(acpi_handle handle, u32 lvl_not_used, 85static 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
95static bool acpi_extra_checks_passed(acpi_handle handle, bool is_bridge) 98static 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
115struct find_child_context { 122struct 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
122static acpi_status do_find_child(acpi_handle handle, u32 lvl_not_used, 129static 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}