diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 115 |
1 files changed, 65 insertions, 50 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b4d5549265ed..8f3adf924e83 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -895,8 +895,51 @@ static void acpi_device_remove_files(struct acpi_device *dev) | |||
895 | ACPI Bus operations | 895 | ACPI Bus operations |
896 | -------------------------------------------------------------------------- */ | 896 | -------------------------------------------------------------------------- */ |
897 | 897 | ||
898 | /** | ||
899 | * acpi_of_match_device - Match device object using the "compatible" property. | ||
900 | * @adev: ACPI device object to match. | ||
901 | * @of_match_table: List of device IDs to match against. | ||
902 | * | ||
903 | * If @dev has an ACPI companion which has the special PRP0001 device ID in its | ||
904 | * list of identifiers and a _DSD object with the "compatible" property, use | ||
905 | * that property to match against the given list of identifiers. | ||
906 | */ | ||
907 | static bool acpi_of_match_device(struct acpi_device *adev, | ||
908 | const struct of_device_id *of_match_table) | ||
909 | { | ||
910 | const union acpi_object *of_compatible, *obj; | ||
911 | int i, nval; | ||
912 | |||
913 | if (!adev) | ||
914 | return false; | ||
915 | |||
916 | of_compatible = adev->data.of_compatible; | ||
917 | if (!of_match_table || !of_compatible) | ||
918 | return false; | ||
919 | |||
920 | if (of_compatible->type == ACPI_TYPE_PACKAGE) { | ||
921 | nval = of_compatible->package.count; | ||
922 | obj = of_compatible->package.elements; | ||
923 | } else { /* Must be ACPI_TYPE_STRING. */ | ||
924 | nval = 1; | ||
925 | obj = of_compatible; | ||
926 | } | ||
927 | /* Now we can look for the driver DT compatible strings */ | ||
928 | for (i = 0; i < nval; i++, obj++) { | ||
929 | const struct of_device_id *id; | ||
930 | |||
931 | for (id = of_match_table; id->compatible[0]; id++) | ||
932 | if (!strcasecmp(obj->string.pointer, id->compatible)) | ||
933 | return true; | ||
934 | } | ||
935 | |||
936 | return false; | ||
937 | } | ||
938 | |||
898 | static const struct acpi_device_id *__acpi_match_device( | 939 | static const struct acpi_device_id *__acpi_match_device( |
899 | struct acpi_device *device, const struct acpi_device_id *ids) | 940 | struct acpi_device *device, |
941 | const struct acpi_device_id *ids, | ||
942 | const struct of_device_id *of_ids) | ||
900 | { | 943 | { |
901 | const struct acpi_device_id *id; | 944 | const struct acpi_device_id *id; |
902 | struct acpi_hardware_id *hwid; | 945 | struct acpi_hardware_id *hwid; |
@@ -908,11 +951,24 @@ static const struct acpi_device_id *__acpi_match_device( | |||
908 | if (!device || !device->status.present) | 951 | if (!device || !device->status.present) |
909 | return NULL; | 952 | return NULL; |
910 | 953 | ||
911 | for (id = ids; id->id[0]; id++) | 954 | list_for_each_entry(hwid, &device->pnp.ids, list) { |
912 | list_for_each_entry(hwid, &device->pnp.ids, list) | 955 | /* First, check the ACPI/PNP IDs provided by the caller. */ |
956 | for (id = ids; id->id[0]; id++) | ||
913 | if (!strcmp((char *) id->id, hwid->id)) | 957 | if (!strcmp((char *) id->id, hwid->id)) |
914 | return id; | 958 | return id; |
915 | 959 | ||
960 | /* | ||
961 | * Next, check the special "PRP0001" ID and try to match the | ||
962 | * "compatible" property if found. | ||
963 | * | ||
964 | * The id returned by the below is not valid, but the only | ||
965 | * caller passing non-NULL of_ids here is only interested in | ||
966 | * whether or not the return value is NULL. | ||
967 | */ | ||
968 | if (!strcmp("PRP0001", hwid->id) | ||
969 | && acpi_of_match_device(device, of_ids)) | ||
970 | return id; | ||
971 | } | ||
916 | return NULL; | 972 | return NULL; |
917 | } | 973 | } |
918 | 974 | ||
@@ -930,67 +986,26 @@ static const struct acpi_device_id *__acpi_match_device( | |||
930 | const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, | 986 | const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, |
931 | const struct device *dev) | 987 | const struct device *dev) |
932 | { | 988 | { |
933 | return __acpi_match_device(acpi_companion_match(dev), ids); | 989 | return __acpi_match_device(acpi_companion_match(dev), ids, NULL); |
934 | } | 990 | } |
935 | EXPORT_SYMBOL_GPL(acpi_match_device); | 991 | EXPORT_SYMBOL_GPL(acpi_match_device); |
936 | 992 | ||
937 | int acpi_match_device_ids(struct acpi_device *device, | 993 | int acpi_match_device_ids(struct acpi_device *device, |
938 | const struct acpi_device_id *ids) | 994 | const struct acpi_device_id *ids) |
939 | { | 995 | { |
940 | return __acpi_match_device(device, ids) ? 0 : -ENOENT; | 996 | return __acpi_match_device(device, ids, NULL) ? 0 : -ENOENT; |
941 | } | 997 | } |
942 | EXPORT_SYMBOL(acpi_match_device_ids); | 998 | EXPORT_SYMBOL(acpi_match_device_ids); |
943 | 999 | ||
944 | /** | ||
945 | * acpi_of_match_device - Match device using the "compatible" property. | ||
946 | * @dev: Device to match. | ||
947 | * @of_match_table: List of device IDs to match against. | ||
948 | * | ||
949 | * If @dev has an ACPI companion which has the special PRP0001 device ID in its | ||
950 | * list of identifiers and a _DSD object with the "compatible" property, use | ||
951 | * that property to match against the given list of identifiers. | ||
952 | */ | ||
953 | static bool acpi_of_match_device(struct device *dev, | ||
954 | const struct of_device_id *of_match_table) | ||
955 | { | ||
956 | const union acpi_object *of_compatible, *obj; | ||
957 | struct acpi_device *adev; | ||
958 | int i, nval; | ||
959 | |||
960 | adev = ACPI_COMPANION(dev); | ||
961 | if (!adev) | ||
962 | return false; | ||
963 | |||
964 | of_compatible = adev->data.of_compatible; | ||
965 | if (!of_match_table || !of_compatible) | ||
966 | return false; | ||
967 | |||
968 | if (of_compatible->type == ACPI_TYPE_PACKAGE) { | ||
969 | nval = of_compatible->package.count; | ||
970 | obj = of_compatible->package.elements; | ||
971 | } else { /* Must be ACPI_TYPE_STRING. */ | ||
972 | nval = 1; | ||
973 | obj = of_compatible; | ||
974 | } | ||
975 | /* Now we can look for the driver DT compatible strings */ | ||
976 | for (i = 0; i < nval; i++, obj++) { | ||
977 | const struct of_device_id *id; | ||
978 | |||
979 | for (id = of_match_table; id->compatible[0]; id++) | ||
980 | if (!strcasecmp(obj->string.pointer, id->compatible)) | ||
981 | return true; | ||
982 | } | ||
983 | |||
984 | return false; | ||
985 | } | ||
986 | |||
987 | bool acpi_driver_match_device(struct device *dev, | 1000 | bool acpi_driver_match_device(struct device *dev, |
988 | const struct device_driver *drv) | 1001 | const struct device_driver *drv) |
989 | { | 1002 | { |
990 | if (!drv->acpi_match_table) | 1003 | if (!drv->acpi_match_table) |
991 | return acpi_of_match_device(dev, drv->of_match_table); | 1004 | return acpi_of_match_device(ACPI_COMPANION(dev), |
1005 | drv->of_match_table); | ||
992 | 1006 | ||
993 | return !!acpi_match_device(drv->acpi_match_table, dev); | 1007 | return !!__acpi_match_device(acpi_companion_match(dev), |
1008 | drv->acpi_match_table, drv->of_match_table); | ||
994 | } | 1009 | } |
995 | EXPORT_SYMBOL_GPL(acpi_driver_match_device); | 1010 | EXPORT_SYMBOL_GPL(acpi_driver_match_device); |
996 | 1011 | ||