diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 129 |
1 files changed, 118 insertions, 11 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 0476e90b2091..9cb5cca3cfe3 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -124,17 +124,56 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
124 | if (list_empty(&acpi_dev->pnp.ids)) | 124 | if (list_empty(&acpi_dev->pnp.ids)) |
125 | return 0; | 125 | return 0; |
126 | 126 | ||
127 | len = snprintf(modalias, size, "acpi:"); | 127 | /* |
128 | size -= len; | 128 | * If the device has PRP0001 we expose DT compatible modalias |
129 | 129 | * instead in form of of:NnameTCcompatible. | |
130 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) { | 130 | */ |
131 | count = snprintf(&modalias[len], size, "%s:", id->id); | 131 | if (acpi_dev->data.of_compatible) { |
132 | if (count < 0) | 132 | struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; |
133 | return -EINVAL; | 133 | const union acpi_object *of_compatible, *obj; |
134 | if (count >= size) | 134 | int i, nval; |
135 | return -ENOMEM; | 135 | char *c; |
136 | len += count; | 136 | |
137 | size -= count; | 137 | acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf); |
138 | /* DT strings are all in lower case */ | ||
139 | for (c = buf.pointer; *c != '\0'; c++) | ||
140 | *c = tolower(*c); | ||
141 | |||
142 | len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer); | ||
143 | ACPI_FREE(buf.pointer); | ||
144 | |||
145 | of_compatible = acpi_dev->data.of_compatible; | ||
146 | if (of_compatible->type == ACPI_TYPE_PACKAGE) { | ||
147 | nval = of_compatible->package.count; | ||
148 | obj = of_compatible->package.elements; | ||
149 | } else { /* Must be ACPI_TYPE_STRING. */ | ||
150 | nval = 1; | ||
151 | obj = of_compatible; | ||
152 | } | ||
153 | for (i = 0; i < nval; i++, obj++) { | ||
154 | count = snprintf(&modalias[len], size, "C%s", | ||
155 | obj->string.pointer); | ||
156 | if (count < 0) | ||
157 | return -EINVAL; | ||
158 | if (count >= size) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | len += count; | ||
162 | size -= count; | ||
163 | } | ||
164 | } else { | ||
165 | len = snprintf(modalias, size, "acpi:"); | ||
166 | size -= len; | ||
167 | |||
168 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) { | ||
169 | count = snprintf(&modalias[len], size, "%s:", id->id); | ||
170 | if (count < 0) | ||
171 | return -EINVAL; | ||
172 | if (count >= size) | ||
173 | return -ENOMEM; | ||
174 | len += count; | ||
175 | size -= count; | ||
176 | } | ||
138 | } | 177 | } |
139 | 178 | ||
140 | modalias[len] = '\0'; | 179 | modalias[len] = '\0'; |
@@ -902,6 +941,51 @@ int acpi_match_device_ids(struct acpi_device *device, | |||
902 | } | 941 | } |
903 | EXPORT_SYMBOL(acpi_match_device_ids); | 942 | EXPORT_SYMBOL(acpi_match_device_ids); |
904 | 943 | ||
944 | /* Performs match against special "PRP0001" shoehorn ACPI ID */ | ||
945 | static bool acpi_of_driver_match_device(struct device *dev, | ||
946 | const struct device_driver *drv) | ||
947 | { | ||
948 | const union acpi_object *of_compatible, *obj; | ||
949 | struct acpi_device *adev; | ||
950 | int i, nval; | ||
951 | |||
952 | adev = ACPI_COMPANION(dev); | ||
953 | if (!adev) | ||
954 | return false; | ||
955 | |||
956 | of_compatible = adev->data.of_compatible; | ||
957 | if (!drv->of_match_table || !of_compatible) | ||
958 | return false; | ||
959 | |||
960 | if (of_compatible->type == ACPI_TYPE_PACKAGE) { | ||
961 | nval = of_compatible->package.count; | ||
962 | obj = of_compatible->package.elements; | ||
963 | } else { /* Must be ACPI_TYPE_STRING. */ | ||
964 | nval = 1; | ||
965 | obj = of_compatible; | ||
966 | } | ||
967 | /* Now we can look for the driver DT compatible strings */ | ||
968 | for (i = 0; i < nval; i++, obj++) { | ||
969 | const struct of_device_id *id; | ||
970 | |||
971 | for (id = drv->of_match_table; id->compatible[0]; id++) | ||
972 | if (!strcasecmp(obj->string.pointer, id->compatible)) | ||
973 | return true; | ||
974 | } | ||
975 | |||
976 | return false; | ||
977 | } | ||
978 | |||
979 | bool acpi_driver_match_device(struct device *dev, | ||
980 | const struct device_driver *drv) | ||
981 | { | ||
982 | if (!drv->acpi_match_table) | ||
983 | return acpi_of_driver_match_device(dev, drv); | ||
984 | |||
985 | return !!acpi_match_device(drv->acpi_match_table, dev); | ||
986 | } | ||
987 | EXPORT_SYMBOL_GPL(acpi_driver_match_device); | ||
988 | |||
905 | static void acpi_free_power_resources_lists(struct acpi_device *device) | 989 | static void acpi_free_power_resources_lists(struct acpi_device *device) |
906 | { | 990 | { |
907 | int i; | 991 | int i; |
@@ -922,6 +1006,7 @@ static void acpi_device_release(struct device *dev) | |||
922 | { | 1006 | { |
923 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 1007 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
924 | 1008 | ||
1009 | acpi_free_properties(acpi_dev); | ||
925 | acpi_free_pnp_ids(&acpi_dev->pnp); | 1010 | acpi_free_pnp_ids(&acpi_dev->pnp); |
926 | acpi_free_power_resources_lists(acpi_dev); | 1011 | acpi_free_power_resources_lists(acpi_dev); |
927 | kfree(acpi_dev); | 1012 | kfree(acpi_dev); |
@@ -1304,6 +1389,26 @@ int acpi_device_add(struct acpi_device *device, | |||
1304 | return result; | 1389 | return result; |
1305 | } | 1390 | } |
1306 | 1391 | ||
1392 | struct acpi_device *acpi_get_next_child(struct device *dev, | ||
1393 | struct acpi_device *child) | ||
1394 | { | ||
1395 | struct acpi_device *adev = ACPI_COMPANION(dev); | ||
1396 | struct list_head *head, *next; | ||
1397 | |||
1398 | if (!adev) | ||
1399 | return NULL; | ||
1400 | |||
1401 | head = &adev->children; | ||
1402 | if (list_empty(head)) | ||
1403 | return NULL; | ||
1404 | |||
1405 | if (!child) | ||
1406 | return list_first_entry(head, struct acpi_device, node); | ||
1407 | |||
1408 | next = child->node.next; | ||
1409 | return next == head ? NULL : list_entry(next, struct acpi_device, node); | ||
1410 | } | ||
1411 | |||
1307 | /* -------------------------------------------------------------------------- | 1412 | /* -------------------------------------------------------------------------- |
1308 | Driver Management | 1413 | Driver Management |
1309 | -------------------------------------------------------------------------- */ | 1414 | -------------------------------------------------------------------------- */ |
@@ -1923,9 +2028,11 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, | |||
1923 | device->device_type = type; | 2028 | device->device_type = type; |
1924 | device->handle = handle; | 2029 | device->handle = handle; |
1925 | device->parent = acpi_bus_get_parent(handle); | 2030 | device->parent = acpi_bus_get_parent(handle); |
2031 | device->fwnode.type = FWNODE_ACPI; | ||
1926 | acpi_set_device_status(device, sta); | 2032 | acpi_set_device_status(device, sta); |
1927 | acpi_device_get_busid(device); | 2033 | acpi_device_get_busid(device); |
1928 | acpi_set_pnp_ids(handle, &device->pnp, type); | 2034 | acpi_set_pnp_ids(handle, &device->pnp, type); |
2035 | acpi_init_properties(device); | ||
1929 | acpi_bus_get_flags(device); | 2036 | acpi_bus_get_flags(device); |
1930 | device->flags.match_driver = false; | 2037 | device->flags.match_driver = false; |
1931 | device->flags.initialized = true; | 2038 | device->flags.initialized = true; |