diff options
author | Jiang Liu <jiang.liu@linux.intel.com> | 2013-12-19 07:38:13 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-01-05 10:07:14 -0500 |
commit | 1d0fcef732832432aee47cb75bf4a2cb3107be64 (patch) | |
tree | 2dbd9c1017342f1b39618ebb8b9bf74c9c846aa4 /drivers/pci | |
parent | 54e5bb46597e5eba63e460a1f96eb2021dc71fec (diff) |
ACPI / PCI: replace open-coded _DSM code with helper functions
Use helper functions to simplify _DSM related code in pci-label driver.
Also enforce more strict checks on objects returned by _DSM method.
Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pci-label.c | 121 |
1 files changed, 34 insertions, 87 deletions
diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c index f6e01a500d79..f12dcd1dc208 100644 --- a/drivers/pci/pci-label.c +++ b/drivers/pci/pci-label.c | |||
@@ -195,80 +195,58 @@ enum acpi_attr_enum { | |||
195 | static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf) | 195 | static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf) |
196 | { | 196 | { |
197 | int len; | 197 | int len; |
198 | len = utf16s_to_utf8s((const wchar_t *)obj-> | 198 | len = utf16s_to_utf8s((const wchar_t *)obj->string.pointer, |
199 | package.elements[1].string.pointer, | 199 | obj->string.length, |
200 | obj->package.elements[1].string.length, | ||
201 | UTF16_LITTLE_ENDIAN, | 200 | UTF16_LITTLE_ENDIAN, |
202 | buf, PAGE_SIZE); | 201 | buf, PAGE_SIZE); |
203 | buf[len] = '\n'; | 202 | buf[len] = '\n'; |
204 | } | 203 | } |
205 | 204 | ||
206 | static int | 205 | static int |
207 | dsm_get_label(acpi_handle handle, int func, | 206 | dsm_get_label(struct device *dev, char *buf, enum acpi_attr_enum attr) |
208 | struct acpi_buffer *output, | ||
209 | char *buf, enum acpi_attr_enum attribute) | ||
210 | { | 207 | { |
211 | struct acpi_object_list input; | 208 | acpi_handle handle; |
212 | union acpi_object params[4]; | 209 | union acpi_object *obj, *tmp; |
213 | union acpi_object *obj; | 210 | int len = -1; |
214 | int len = 0; | 211 | |
215 | 212 | handle = ACPI_HANDLE(dev); | |
216 | int err; | 213 | if (!handle) |
217 | |||
218 | input.count = 4; | ||
219 | input.pointer = params; | ||
220 | params[0].type = ACPI_TYPE_BUFFER; | ||
221 | params[0].buffer.length = sizeof(device_label_dsm_uuid); | ||
222 | params[0].buffer.pointer = (char *)device_label_dsm_uuid; | ||
223 | params[1].type = ACPI_TYPE_INTEGER; | ||
224 | params[1].integer.value = 0x02; | ||
225 | params[2].type = ACPI_TYPE_INTEGER; | ||
226 | params[2].integer.value = func; | ||
227 | params[3].type = ACPI_TYPE_PACKAGE; | ||
228 | params[3].package.count = 0; | ||
229 | params[3].package.elements = NULL; | ||
230 | |||
231 | err = acpi_evaluate_object(handle, "_DSM", &input, output); | ||
232 | if (err) | ||
233 | return -1; | 214 | return -1; |
234 | 215 | ||
235 | obj = (union acpi_object *)output->pointer; | 216 | obj = acpi_evaluate_dsm(handle, device_label_dsm_uuid, 0x2, |
236 | if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2) { | 217 | DEVICE_LABEL_DSM, NULL); |
237 | len = obj->package.elements[0].integer.value; | 218 | if (!obj) |
219 | return -1; | ||
220 | |||
221 | tmp = obj->package.elements; | ||
222 | if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2 && | ||
223 | tmp[0].type == ACPI_TYPE_INTEGER && | ||
224 | tmp[1].type == ACPI_TYPE_STRING) { | ||
225 | len = tmp[0].integer.value; | ||
238 | if (buf) { | 226 | if (buf) { |
239 | if (attribute == ACPI_ATTR_INDEX_SHOW) | 227 | /* |
228 | * This second string element is optional even when | ||
229 | * this _DSM is implemented; when not implemented, | ||
230 | * this entry must return a null string. | ||
231 | */ | ||
232 | if (attr == ACPI_ATTR_INDEX_SHOW) | ||
240 | scnprintf(buf, PAGE_SIZE, "%llu\n", | 233 | scnprintf(buf, PAGE_SIZE, "%llu\n", |
241 | obj->package.elements[0].integer.value); | 234 | tmp->integer.value); |
242 | else if (attribute == ACPI_ATTR_LABEL_SHOW) | 235 | else if (attr == ACPI_ATTR_LABEL_SHOW) |
243 | dsm_label_utf16s_to_utf8s(obj, buf); | 236 | dsm_label_utf16s_to_utf8s(tmp + 1, buf); |
244 | kfree(output->pointer); | 237 | len = strlen(buf) > 0 ? strlen(buf) : -1; |
245 | return strlen(buf); | ||
246 | } | 238 | } |
247 | kfree(output->pointer); | ||
248 | return len; | ||
249 | } | 239 | } |
250 | 240 | ||
251 | kfree(output->pointer); | 241 | ACPI_FREE(obj); |
252 | 242 | ||
253 | return -1; | 243 | return len; |
254 | } | 244 | } |
255 | 245 | ||
256 | static bool | 246 | static bool |
257 | device_has_dsm(struct device *dev) | 247 | device_has_dsm(struct device *dev) |
258 | { | 248 | { |
259 | acpi_handle handle; | 249 | return dsm_get_label(dev, NULL, ACPI_ATTR_NONE) > 0; |
260 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
261 | |||
262 | handle = ACPI_HANDLE(dev); | ||
263 | |||
264 | if (!handle) | ||
265 | return FALSE; | ||
266 | |||
267 | if (dsm_get_label(handle, DEVICE_LABEL_DSM, &output, NULL, | ||
268 | ACPI_ATTR_NONE) > 0) | ||
269 | return TRUE; | ||
270 | |||
271 | return FALSE; | ||
272 | } | 250 | } |
273 | 251 | ||
274 | static umode_t | 252 | static umode_t |
@@ -287,44 +265,13 @@ acpi_index_string_exist(struct kobject *kobj, struct attribute *attr, int n) | |||
287 | static ssize_t | 265 | static ssize_t |
288 | acpilabel_show(struct device *dev, struct device_attribute *attr, char *buf) | 266 | acpilabel_show(struct device *dev, struct device_attribute *attr, char *buf) |
289 | { | 267 | { |
290 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | 268 | return dsm_get_label(dev, buf, ACPI_ATTR_LABEL_SHOW); |
291 | acpi_handle handle; | ||
292 | int length; | ||
293 | |||
294 | handle = ACPI_HANDLE(dev); | ||
295 | |||
296 | if (!handle) | ||
297 | return -1; | ||
298 | |||
299 | length = dsm_get_label(handle, DEVICE_LABEL_DSM, | ||
300 | &output, buf, ACPI_ATTR_LABEL_SHOW); | ||
301 | |||
302 | if (length < 1) | ||
303 | return -1; | ||
304 | |||
305 | return length; | ||
306 | } | 269 | } |
307 | 270 | ||
308 | static ssize_t | 271 | static ssize_t |
309 | acpiindex_show(struct device *dev, struct device_attribute *attr, char *buf) | 272 | acpiindex_show(struct device *dev, struct device_attribute *attr, char *buf) |
310 | { | 273 | { |
311 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | 274 | return dsm_get_label(dev, buf, ACPI_ATTR_INDEX_SHOW); |
312 | acpi_handle handle; | ||
313 | int length; | ||
314 | |||
315 | handle = ACPI_HANDLE(dev); | ||
316 | |||
317 | if (!handle) | ||
318 | return -1; | ||
319 | |||
320 | length = dsm_get_label(handle, DEVICE_LABEL_DSM, | ||
321 | &output, buf, ACPI_ATTR_INDEX_SHOW); | ||
322 | |||
323 | if (length < 0) | ||
324 | return -1; | ||
325 | |||
326 | return length; | ||
327 | |||
328 | } | 275 | } |
329 | 276 | ||
330 | static struct device_attribute acpi_attr_label = { | 277 | static struct device_attribute acpi_attr_label = { |