diff options
author | Len Brown <len.brown@intel.com> | 2009-01-09 03:39:43 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-01-09 03:39:43 -0500 |
commit | b2576e1d4408e134e2188c967b1f28af39cd79d4 (patch) | |
tree | 004f3c82faab760f304ce031d6d2f572e7746a50 /drivers/pci/pci-acpi.c | |
parent | 3cc8a5f4ba91f67bbdb81a43a99281a26aab8d77 (diff) | |
parent | 2150edc6c5cf00f7adb54538b9ea2a3e9cedca3f (diff) |
Merge branch 'linus' into release
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r-- | drivers/pci/pci-acpi.c | 82 |
1 files changed, 38 insertions, 44 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 9d976d51d406..deea8a187eb8 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -22,13 +22,14 @@ struct acpi_osc_data { | |||
22 | acpi_handle handle; | 22 | acpi_handle handle; |
23 | u32 support_set; | 23 | u32 support_set; |
24 | u32 control_set; | 24 | u32 control_set; |
25 | u32 control_query; | ||
26 | int is_queried; | ||
25 | struct list_head sibiling; | 27 | struct list_head sibiling; |
26 | }; | 28 | }; |
27 | static LIST_HEAD(acpi_osc_data_list); | 29 | static LIST_HEAD(acpi_osc_data_list); |
28 | 30 | ||
29 | struct acpi_osc_args { | 31 | struct acpi_osc_args { |
30 | u32 capbuf[3]; | 32 | u32 capbuf[3]; |
31 | u32 ctrl_result; | ||
32 | }; | 33 | }; |
33 | 34 | ||
34 | static DEFINE_MUTEX(pci_acpi_lock); | 35 | static DEFINE_MUTEX(pci_acpi_lock); |
@@ -54,7 +55,7 @@ static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, | |||
54 | 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; | 55 | 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; |
55 | 56 | ||
56 | static acpi_status acpi_run_osc(acpi_handle handle, | 57 | static acpi_status acpi_run_osc(acpi_handle handle, |
57 | struct acpi_osc_args *osc_args) | 58 | struct acpi_osc_args *osc_args, u32 *retval) |
58 | { | 59 | { |
59 | acpi_status status; | 60 | acpi_status status; |
60 | struct acpi_object_list input; | 61 | struct acpi_object_list input; |
@@ -110,8 +111,7 @@ static acpi_status acpi_run_osc(acpi_handle handle, | |||
110 | goto out_kfree; | 111 | goto out_kfree; |
111 | } | 112 | } |
112 | out_success: | 113 | out_success: |
113 | osc_args->ctrl_result = | 114 | *retval = *((u32 *)(out_obj->buffer.pointer + 8)); |
114 | *((u32 *)(out_obj->buffer.pointer + 8)); | ||
115 | status = AE_OK; | 115 | status = AE_OK; |
116 | 116 | ||
117 | out_kfree: | 117 | out_kfree: |
@@ -119,11 +119,10 @@ out_kfree: | |||
119 | return status; | 119 | return status; |
120 | } | 120 | } |
121 | 121 | ||
122 | static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data, | 122 | static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data) |
123 | u32 *result) | ||
124 | { | 123 | { |
125 | acpi_status status; | 124 | acpi_status status; |
126 | u32 support_set; | 125 | u32 support_set, result; |
127 | struct acpi_osc_args osc_args; | 126 | struct acpi_osc_args osc_args; |
128 | 127 | ||
129 | /* do _OSC query for all possible controls */ | 128 | /* do _OSC query for all possible controls */ |
@@ -132,56 +131,45 @@ static acpi_status __acpi_query_osc(u32 flags, struct acpi_osc_data *osc_data, | |||
132 | osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set; | 131 | osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set; |
133 | osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; | 132 | osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; |
134 | 133 | ||
135 | status = acpi_run_osc(osc_data->handle, &osc_args); | 134 | status = acpi_run_osc(osc_data->handle, &osc_args, &result); |
136 | if (ACPI_SUCCESS(status)) { | 135 | if (ACPI_SUCCESS(status)) { |
137 | osc_data->support_set = support_set; | 136 | osc_data->support_set = support_set; |
138 | *result = osc_args.ctrl_result; | 137 | osc_data->control_query = result; |
138 | osc_data->is_queried = 1; | ||
139 | } | 139 | } |
140 | 140 | ||
141 | return status; | 141 | return status; |
142 | } | 142 | } |
143 | 143 | ||
144 | static acpi_status acpi_query_osc(acpi_handle handle, | 144 | /* |
145 | u32 level, void *context, void **retval) | 145 | * pci_acpi_osc_support: Invoke _OSC indicating support for the given feature |
146 | * @flags: Bitmask of flags to support | ||
147 | * | ||
148 | * See the ACPI spec for the definition of the flags | ||
149 | */ | ||
150 | int pci_acpi_osc_support(acpi_handle handle, u32 flags) | ||
146 | { | 151 | { |
147 | acpi_status status; | 152 | acpi_status status; |
148 | struct acpi_osc_data *osc_data; | ||
149 | u32 flags = (unsigned long)context, dummy; | ||
150 | acpi_handle tmp; | 153 | acpi_handle tmp; |
154 | struct acpi_osc_data *osc_data; | ||
155 | int rc = 0; | ||
151 | 156 | ||
152 | status = acpi_get_handle(handle, "_OSC", &tmp); | 157 | status = acpi_get_handle(handle, "_OSC", &tmp); |
153 | if (ACPI_FAILURE(status)) | 158 | if (ACPI_FAILURE(status)) |
154 | return AE_OK; | 159 | return -ENOTTY; |
155 | 160 | ||
156 | mutex_lock(&pci_acpi_lock); | 161 | mutex_lock(&pci_acpi_lock); |
157 | osc_data = acpi_get_osc_data(handle); | 162 | osc_data = acpi_get_osc_data(handle); |
158 | if (!osc_data) { | 163 | if (!osc_data) { |
159 | printk(KERN_ERR "acpi osc data array is full\n"); | 164 | printk(KERN_ERR "acpi osc data array is full\n"); |
165 | rc = -ENOMEM; | ||
160 | goto out; | 166 | goto out; |
161 | } | 167 | } |
162 | 168 | ||
163 | __acpi_query_osc(flags, osc_data, &dummy); | 169 | __acpi_query_osc(flags, osc_data); |
164 | out: | 170 | out: |
165 | mutex_unlock(&pci_acpi_lock); | 171 | mutex_unlock(&pci_acpi_lock); |
166 | return AE_OK; | 172 | return rc; |
167 | } | ||
168 | |||
169 | /** | ||
170 | * __pci_osc_support_set - register OS support to Firmware | ||
171 | * @flags: OS support bits | ||
172 | * @hid: hardware ID | ||
173 | * | ||
174 | * Update OS support fields and doing a _OSC Query to obtain an update | ||
175 | * from Firmware on supported control bits. | ||
176 | **/ | ||
177 | acpi_status __pci_osc_support_set(u32 flags, const char *hid) | ||
178 | { | ||
179 | if (!(flags & OSC_SUPPORT_MASKS)) | ||
180 | return AE_TYPE; | ||
181 | |||
182 | acpi_get_devices(hid, acpi_query_osc, | ||
183 | (void *)(unsigned long)flags, NULL); | ||
184 | return AE_OK; | ||
185 | } | 173 | } |
186 | 174 | ||
187 | /** | 175 | /** |
@@ -194,7 +182,7 @@ acpi_status __pci_osc_support_set(u32 flags, const char *hid) | |||
194 | acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) | 182 | acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) |
195 | { | 183 | { |
196 | acpi_status status; | 184 | acpi_status status; |
197 | u32 ctrlset, control_set, result; | 185 | u32 control_req, control_set, result; |
198 | acpi_handle tmp; | 186 | acpi_handle tmp; |
199 | struct acpi_osc_data *osc_data; | 187 | struct acpi_osc_data *osc_data; |
200 | struct acpi_osc_args osc_args; | 188 | struct acpi_osc_args osc_args; |
@@ -211,28 +199,34 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) | |||
211 | goto out; | 199 | goto out; |
212 | } | 200 | } |
213 | 201 | ||
214 | ctrlset = (flags & OSC_CONTROL_MASKS); | 202 | control_req = (flags & OSC_CONTROL_MASKS); |
215 | if (!ctrlset) { | 203 | if (!control_req) { |
216 | status = AE_TYPE; | 204 | status = AE_TYPE; |
217 | goto out; | 205 | goto out; |
218 | } | 206 | } |
219 | 207 | ||
220 | status = __acpi_query_osc(osc_data->support_set, osc_data, &result); | 208 | /* No need to evaluate _OSC if the control was already granted. */ |
221 | if (ACPI_FAILURE(status)) | 209 | if ((osc_data->control_set & control_req) == control_req) |
222 | goto out; | 210 | goto out; |
223 | 211 | ||
224 | if ((result & ctrlset) != ctrlset) { | 212 | if (!osc_data->is_queried) { |
213 | status = __acpi_query_osc(osc_data->support_set, osc_data); | ||
214 | if (ACPI_FAILURE(status)) | ||
215 | goto out; | ||
216 | } | ||
217 | |||
218 | if ((osc_data->control_query & control_req) != control_req) { | ||
225 | status = AE_SUPPORT; | 219 | status = AE_SUPPORT; |
226 | goto out; | 220 | goto out; |
227 | } | 221 | } |
228 | 222 | ||
229 | control_set = osc_data->control_set | ctrlset; | 223 | control_set = osc_data->control_set | control_req; |
230 | osc_args.capbuf[OSC_QUERY_TYPE] = 0; | 224 | osc_args.capbuf[OSC_QUERY_TYPE] = 0; |
231 | osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set; | 225 | osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set; |
232 | osc_args.capbuf[OSC_CONTROL_TYPE] = control_set; | 226 | osc_args.capbuf[OSC_CONTROL_TYPE] = control_set; |
233 | status = acpi_run_osc(handle, &osc_args); | 227 | status = acpi_run_osc(handle, &osc_args, &result); |
234 | if (ACPI_SUCCESS(status)) | 228 | if (ACPI_SUCCESS(status)) |
235 | osc_data->control_set = control_set; | 229 | osc_data->control_set = result; |
236 | out: | 230 | out: |
237 | mutex_unlock(&pci_acpi_lock); | 231 | mutex_unlock(&pci_acpi_lock); |
238 | return status; | 232 | return status; |
@@ -373,7 +367,7 @@ static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle) | |||
373 | * The string should be the same as root bridge's name | 367 | * The string should be the same as root bridge's name |
374 | * Please look at 'pci_scan_bus_parented' | 368 | * Please look at 'pci_scan_bus_parented' |
375 | */ | 369 | */ |
376 | num = sscanf(dev->bus_id, "pci%04x:%02x", &seg, &bus); | 370 | num = sscanf(dev_name(dev), "pci%04x:%02x", &seg, &bus); |
377 | if (num != 2) | 371 | if (num != 2) |
378 | return -ENODEV; | 372 | return -ENODEV; |
379 | *handle = acpi_get_pci_rootbridge_handle(seg, bus); | 373 | *handle = acpi_get_pci_rootbridge_handle(seg, bus); |