diff options
author | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2008-07-21 08:15:51 -0400 |
---|---|---|
committer | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 2008-07-21 08:15:51 -0400 |
commit | bf20e740a4bcc686de02e2fd1c1810a58872f46e (patch) | |
tree | a3fccedd9c0da2ccdd2088de42e986430c1a4d83 /drivers/misc | |
parent | 490673dc98adfc7de1703cc88508902bd10f446b (diff) |
ACPI: thinkpad-acpi: don't misdetect in get_thinkpad_model_data() on -ENOMEM
Explicitly check for memory allocation failures, and return status to
indicate that we could not collect data due to errors.
This lets the driver have a far more predictable failure mode on ENOMEM in
that codepath: it will refuse to load. This is far better than trying to
proceed with missing data which is used to detect quirks, etc.
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/thinkpad_acpi.c | 47 |
1 files changed, 33 insertions, 14 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 3eb01afe4306..d3eb7903c346 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
@@ -6340,13 +6340,18 @@ err_out: | |||
6340 | 6340 | ||
6341 | /* Probing */ | 6341 | /* Probing */ |
6342 | 6342 | ||
6343 | static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) | 6343 | /* returns 0 - probe ok, or < 0 - probe error. |
6344 | * Probe ok doesn't mean thinkpad found. | ||
6345 | * On error, kfree() cleanup on tp->* is not performed, caller must do it */ | ||
6346 | static int __must_check __init get_thinkpad_model_data( | ||
6347 | struct thinkpad_id_data *tp) | ||
6344 | { | 6348 | { |
6345 | const struct dmi_device *dev = NULL; | 6349 | const struct dmi_device *dev = NULL; |
6346 | char ec_fw_string[18]; | 6350 | char ec_fw_string[18]; |
6351 | char const *s; | ||
6347 | 6352 | ||
6348 | if (!tp) | 6353 | if (!tp) |
6349 | return; | 6354 | return -EINVAL; |
6350 | 6355 | ||
6351 | memset(tp, 0, sizeof(*tp)); | 6356 | memset(tp, 0, sizeof(*tp)); |
6352 | 6357 | ||
@@ -6355,12 +6360,14 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) | |||
6355 | else if (dmi_name_in_vendors("LENOVO")) | 6360 | else if (dmi_name_in_vendors("LENOVO")) |
6356 | tp->vendor = PCI_VENDOR_ID_LENOVO; | 6361 | tp->vendor = PCI_VENDOR_ID_LENOVO; |
6357 | else | 6362 | else |
6358 | return; | 6363 | return 0; |
6359 | 6364 | ||
6360 | tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION), | 6365 | s = dmi_get_system_info(DMI_BIOS_VERSION); |
6361 | GFP_KERNEL); | 6366 | tp->bios_version_str = kstrdup(s, GFP_KERNEL); |
6367 | if (s && !tp->bios_version_str) | ||
6368 | return -ENOMEM; | ||
6362 | if (!tp->bios_version_str) | 6369 | if (!tp->bios_version_str) |
6363 | return; | 6370 | return 0; |
6364 | tp->bios_model = tp->bios_version_str[0] | 6371 | tp->bios_model = tp->bios_version_str[0] |
6365 | | (tp->bios_version_str[1] << 8); | 6372 | | (tp->bios_version_str[1] << 8); |
6366 | 6373 | ||
@@ -6379,21 +6386,27 @@ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) | |||
6379 | ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; | 6386 | ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; |
6380 | 6387 | ||
6381 | tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); | 6388 | tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); |
6389 | if (!tp->ec_version_str) | ||
6390 | return -ENOMEM; | ||
6382 | tp->ec_model = ec_fw_string[0] | 6391 | tp->ec_model = ec_fw_string[0] |
6383 | | (ec_fw_string[1] << 8); | 6392 | | (ec_fw_string[1] << 8); |
6384 | break; | 6393 | break; |
6385 | } | 6394 | } |
6386 | } | 6395 | } |
6387 | 6396 | ||
6388 | tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION), | 6397 | s = dmi_get_system_info(DMI_PRODUCT_VERSION); |
6389 | GFP_KERNEL); | 6398 | if (s && !strnicmp(s, "ThinkPad", 8)) { |
6390 | if (tp->model_str && strnicmp(tp->model_str, "ThinkPad", 8) != 0) { | 6399 | tp->model_str = kstrdup(s, GFP_KERNEL); |
6391 | kfree(tp->model_str); | 6400 | if (!tp->model_str) |
6392 | tp->model_str = NULL; | 6401 | return -ENOMEM; |
6393 | } | 6402 | } |
6394 | 6403 | ||
6395 | tp->nummodel_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_NAME), | 6404 | s = dmi_get_system_info(DMI_PRODUCT_NAME); |
6396 | GFP_KERNEL); | 6405 | tp->nummodel_str = kstrdup(s, GFP_KERNEL); |
6406 | if (s && !tp->nummodel_str) | ||
6407 | return -ENOMEM; | ||
6408 | |||
6409 | return 0; | ||
6397 | } | 6410 | } |
6398 | 6411 | ||
6399 | static int __init probe_for_thinkpad(void) | 6412 | static int __init probe_for_thinkpad(void) |
@@ -6656,7 +6669,13 @@ static int __init thinkpad_acpi_module_init(void) | |||
6656 | 6669 | ||
6657 | /* Driver-level probe */ | 6670 | /* Driver-level probe */ |
6658 | 6671 | ||
6659 | get_thinkpad_model_data(&thinkpad_id); | 6672 | ret = get_thinkpad_model_data(&thinkpad_id); |
6673 | if (ret) { | ||
6674 | printk(TPACPI_ERR | ||
6675 | "unable to get DMI data: %d\n", ret); | ||
6676 | thinkpad_acpi_module_exit(); | ||
6677 | return ret; | ||
6678 | } | ||
6660 | ret = probe_for_thinkpad(); | 6679 | ret = probe_for_thinkpad(); |
6661 | if (ret) { | 6680 | if (ret) { |
6662 | thinkpad_acpi_module_exit(); | 6681 | thinkpad_acpi_module_exit(); |