aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c214
1 files changed, 203 insertions, 11 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 0476e90b2091..16914cc30882 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -36,6 +36,8 @@ bool acpi_force_hot_remove;
36 36
37static const char *dummy_hid = "device"; 37static const char *dummy_hid = "device";
38 38
39static LIST_HEAD(acpi_dep_list);
40static DEFINE_MUTEX(acpi_dep_list_lock);
39static LIST_HEAD(acpi_bus_id_list); 41static LIST_HEAD(acpi_bus_id_list);
40static DEFINE_MUTEX(acpi_scan_lock); 42static DEFINE_MUTEX(acpi_scan_lock);
41static LIST_HEAD(acpi_scan_handlers_list); 43static LIST_HEAD(acpi_scan_handlers_list);
@@ -43,6 +45,12 @@ DEFINE_MUTEX(acpi_device_lock);
43LIST_HEAD(acpi_wakeup_device_list); 45LIST_HEAD(acpi_wakeup_device_list);
44static DEFINE_MUTEX(acpi_hp_context_lock); 46static DEFINE_MUTEX(acpi_hp_context_lock);
45 47
48struct acpi_dep_data {
49 struct list_head node;
50 acpi_handle master;
51 acpi_handle slave;
52};
53
46struct acpi_device_bus_id{ 54struct acpi_device_bus_id{
47 char bus_id[15]; 55 char bus_id[15];
48 unsigned int instance_no; 56 unsigned int instance_no;
@@ -124,17 +132,56 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
124 if (list_empty(&acpi_dev->pnp.ids)) 132 if (list_empty(&acpi_dev->pnp.ids))
125 return 0; 133 return 0;
126 134
127 len = snprintf(modalias, size, "acpi:"); 135 /*
128 size -= len; 136 * If the device has PRP0001 we expose DT compatible modalias
129 137 * instead in form of of:NnameTCcompatible.
130 list_for_each_entry(id, &acpi_dev->pnp.ids, list) { 138 */
131 count = snprintf(&modalias[len], size, "%s:", id->id); 139 if (acpi_dev->data.of_compatible) {
132 if (count < 0) 140 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
133 return -EINVAL; 141 const union acpi_object *of_compatible, *obj;
134 if (count >= size) 142 int i, nval;
135 return -ENOMEM; 143 char *c;
136 len += count; 144
137 size -= count; 145 acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
146 /* DT strings are all in lower case */
147 for (c = buf.pointer; *c != '\0'; c++)
148 *c = tolower(*c);
149
150 len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
151 ACPI_FREE(buf.pointer);
152
153 of_compatible = acpi_dev->data.of_compatible;
154 if (of_compatible->type == ACPI_TYPE_PACKAGE) {
155 nval = of_compatible->package.count;
156 obj = of_compatible->package.elements;
157 } else { /* Must be ACPI_TYPE_STRING. */
158 nval = 1;
159 obj = of_compatible;
160 }
161 for (i = 0; i < nval; i++, obj++) {
162 count = snprintf(&modalias[len], size, "C%s",
163 obj->string.pointer);
164 if (count < 0)
165 return -EINVAL;
166 if (count >= size)
167 return -ENOMEM;
168
169 len += count;
170 size -= count;
171 }
172 } else {
173 len = snprintf(modalias, size, "acpi:");
174 size -= len;
175
176 list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
177 count = snprintf(&modalias[len], size, "%s:", id->id);
178 if (count < 0)
179 return -EINVAL;
180 if (count >= size)
181 return -ENOMEM;
182 len += count;
183 size -= count;
184 }
138 } 185 }
139 186
140 modalias[len] = '\0'; 187 modalias[len] = '\0';
@@ -902,6 +949,51 @@ int acpi_match_device_ids(struct acpi_device *device,
902} 949}
903EXPORT_SYMBOL(acpi_match_device_ids); 950EXPORT_SYMBOL(acpi_match_device_ids);
904 951
952/* Performs match against special "PRP0001" shoehorn ACPI ID */
953static bool acpi_of_driver_match_device(struct device *dev,
954 const struct device_driver *drv)
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 (!drv->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 = drv->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
987bool acpi_driver_match_device(struct device *dev,
988 const struct device_driver *drv)
989{
990 if (!drv->acpi_match_table)
991 return acpi_of_driver_match_device(dev, drv);
992
993 return !!acpi_match_device(drv->acpi_match_table, dev);
994}
995EXPORT_SYMBOL_GPL(acpi_driver_match_device);
996
905static void acpi_free_power_resources_lists(struct acpi_device *device) 997static void acpi_free_power_resources_lists(struct acpi_device *device)
906{ 998{
907 int i; 999 int i;
@@ -922,6 +1014,7 @@ static void acpi_device_release(struct device *dev)
922{ 1014{
923 struct acpi_device *acpi_dev = to_acpi_device(dev); 1015 struct acpi_device *acpi_dev = to_acpi_device(dev);
924 1016
1017 acpi_free_properties(acpi_dev);
925 acpi_free_pnp_ids(&acpi_dev->pnp); 1018 acpi_free_pnp_ids(&acpi_dev->pnp);
926 acpi_free_power_resources_lists(acpi_dev); 1019 acpi_free_power_resources_lists(acpi_dev);
927 kfree(acpi_dev); 1020 kfree(acpi_dev);
@@ -1304,6 +1397,26 @@ int acpi_device_add(struct acpi_device *device,
1304 return result; 1397 return result;
1305} 1398}
1306 1399
1400struct acpi_device *acpi_get_next_child(struct device *dev,
1401 struct acpi_device *child)
1402{
1403 struct acpi_device *adev = ACPI_COMPANION(dev);
1404 struct list_head *head, *next;
1405
1406 if (!adev)
1407 return NULL;
1408
1409 head = &adev->children;
1410 if (list_empty(head))
1411 return NULL;
1412
1413 if (!child)
1414 return list_first_entry(head, struct acpi_device, node);
1415
1416 next = child->node.next;
1417 return next == head ? NULL : list_entry(next, struct acpi_device, node);
1418}
1419
1307/* -------------------------------------------------------------------------- 1420/* --------------------------------------------------------------------------
1308 Driver Management 1421 Driver Management
1309 -------------------------------------------------------------------------- */ 1422 -------------------------------------------------------------------------- */
@@ -1923,9 +2036,11 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
1923 device->device_type = type; 2036 device->device_type = type;
1924 device->handle = handle; 2037 device->handle = handle;
1925 device->parent = acpi_bus_get_parent(handle); 2038 device->parent = acpi_bus_get_parent(handle);
2039 device->fwnode.type = FWNODE_ACPI;
1926 acpi_set_device_status(device, sta); 2040 acpi_set_device_status(device, sta);
1927 acpi_device_get_busid(device); 2041 acpi_device_get_busid(device);
1928 acpi_set_pnp_ids(handle, &device->pnp, type); 2042 acpi_set_pnp_ids(handle, &device->pnp, type);
2043 acpi_init_properties(device);
1929 acpi_bus_get_flags(device); 2044 acpi_bus_get_flags(device);
1930 device->flags.match_driver = false; 2045 device->flags.match_driver = false;
1931 device->flags.initialized = true; 2046 device->flags.initialized = true;
@@ -2086,6 +2201,59 @@ static void acpi_scan_init_hotplug(struct acpi_device *adev)
2086 } 2201 }
2087} 2202}
2088 2203
2204static void acpi_device_dep_initialize(struct acpi_device *adev)
2205{
2206 struct acpi_dep_data *dep;
2207 struct acpi_handle_list dep_devices;
2208 acpi_status status;
2209 int i;
2210
2211 if (!acpi_has_method(adev->handle, "_DEP"))
2212 return;
2213
2214 status = acpi_evaluate_reference(adev->handle, "_DEP", NULL,
2215 &dep_devices);
2216 if (ACPI_FAILURE(status)) {
2217 dev_dbg(&adev->dev, "Failed to evaluate _DEP.\n");
2218 return;
2219 }
2220
2221 for (i = 0; i < dep_devices.count; i++) {
2222 struct acpi_device_info *info;
2223 int skip;
2224
2225 status = acpi_get_object_info(dep_devices.handles[i], &info);
2226 if (ACPI_FAILURE(status)) {
2227 dev_dbg(&adev->dev, "Error reading _DEP device info\n");
2228 continue;
2229 }
2230
2231 /*
2232 * Skip the dependency of Windows System Power
2233 * Management Controller
2234 */
2235 skip = info->valid & ACPI_VALID_HID &&
2236 !strcmp(info->hardware_id.string, "INT3396");
2237
2238 kfree(info);
2239
2240 if (skip)
2241 continue;
2242
2243 dep = kzalloc(sizeof(struct acpi_dep_data), GFP_KERNEL);
2244 if (!dep)
2245 return;
2246
2247 dep->master = dep_devices.handles[i];
2248 dep->slave = adev->handle;
2249 adev->dep_unmet++;
2250
2251 mutex_lock(&acpi_dep_list_lock);
2252 list_add_tail(&dep->node , &acpi_dep_list);
2253 mutex_unlock(&acpi_dep_list_lock);
2254 }
2255}
2256
2089static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used, 2257static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
2090 void *not_used, void **return_value) 2258 void *not_used, void **return_value)
2091{ 2259{
@@ -2112,6 +2280,7 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
2112 return AE_CTRL_DEPTH; 2280 return AE_CTRL_DEPTH;
2113 2281
2114 acpi_scan_init_hotplug(device); 2282 acpi_scan_init_hotplug(device);
2283 acpi_device_dep_initialize(device);
2115 2284
2116 out: 2285 out:
2117 if (!*return_value) 2286 if (!*return_value)
@@ -2232,6 +2401,29 @@ static void acpi_bus_attach(struct acpi_device *device)
2232 device->handler->hotplug.notify_online(device); 2401 device->handler->hotplug.notify_online(device);
2233} 2402}
2234 2403
2404void acpi_walk_dep_device_list(acpi_handle handle)
2405{
2406 struct acpi_dep_data *dep, *tmp;
2407 struct acpi_device *adev;
2408
2409 mutex_lock(&acpi_dep_list_lock);
2410 list_for_each_entry_safe(dep, tmp, &acpi_dep_list, node) {
2411 if (dep->master == handle) {
2412 acpi_bus_get_device(dep->slave, &adev);
2413 if (!adev)
2414 continue;
2415
2416 adev->dep_unmet--;
2417 if (!adev->dep_unmet)
2418 acpi_bus_attach(adev);
2419 list_del(&dep->node);
2420 kfree(dep);
2421 }
2422 }
2423 mutex_unlock(&acpi_dep_list_lock);
2424}
2425EXPORT_SYMBOL_GPL(acpi_walk_dep_device_list);
2426
2235/** 2427/**
2236 * acpi_bus_scan - Add ACPI device node objects in a given namespace scope. 2428 * acpi_bus_scan - Add ACPI device node objects in a given namespace scope.
2237 * @handle: Root of the namespace scope to scan. 2429 * @handle: Root of the namespace scope to scan.