diff options
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r-- | drivers/acpi/scan.c | 73 |
1 files changed, 56 insertions, 17 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index ae44d8654c82..0476e90b2091 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -142,6 +142,53 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
142 | } | 142 | } |
143 | 143 | ||
144 | /* | 144 | /* |
145 | * acpi_companion_match() - Can we match via ACPI companion device | ||
146 | * @dev: Device in question | ||
147 | * | ||
148 | * Check if the given device has an ACPI companion and if that companion has | ||
149 | * a valid list of PNP IDs, and if the device is the first (primary) physical | ||
150 | * device associated with it. | ||
151 | * | ||
152 | * If multiple physical devices are attached to a single ACPI companion, we need | ||
153 | * to be careful. The usage scenario for this kind of relationship is that all | ||
154 | * of the physical devices in question use resources provided by the ACPI | ||
155 | * companion. A typical case is an MFD device where all the sub-devices share | ||
156 | * the parent's ACPI companion. In such cases we can only allow the primary | ||
157 | * (first) physical device to be matched with the help of the companion's PNP | ||
158 | * IDs. | ||
159 | * | ||
160 | * Additional physical devices sharing the ACPI companion can still use | ||
161 | * resources available from it but they will be matched normally using functions | ||
162 | * provided by their bus types (and analogously for their modalias). | ||
163 | */ | ||
164 | static bool acpi_companion_match(const struct device *dev) | ||
165 | { | ||
166 | struct acpi_device *adev; | ||
167 | bool ret; | ||
168 | |||
169 | adev = ACPI_COMPANION(dev); | ||
170 | if (!adev) | ||
171 | return false; | ||
172 | |||
173 | if (list_empty(&adev->pnp.ids)) | ||
174 | return false; | ||
175 | |||
176 | mutex_lock(&adev->physical_node_lock); | ||
177 | if (list_empty(&adev->physical_node_list)) { | ||
178 | ret = false; | ||
179 | } else { | ||
180 | const struct acpi_device_physical_node *node; | ||
181 | |||
182 | node = list_first_entry(&adev->physical_node_list, | ||
183 | struct acpi_device_physical_node, node); | ||
184 | ret = node->dev == dev; | ||
185 | } | ||
186 | mutex_unlock(&adev->physical_node_lock); | ||
187 | |||
188 | return ret; | ||
189 | } | ||
190 | |||
191 | /* | ||
145 | * Creates uevent modalias field for ACPI enumerated devices. | 192 | * Creates uevent modalias field for ACPI enumerated devices. |
146 | * Because the other buses does not support ACPI HIDs & CIDs. | 193 | * Because the other buses does not support ACPI HIDs & CIDs. |
147 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: | 194 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: |
@@ -149,20 +196,14 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
149 | */ | 196 | */ |
150 | int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) | 197 | int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) |
151 | { | 198 | { |
152 | struct acpi_device *acpi_dev; | ||
153 | int len; | 199 | int len; |
154 | 200 | ||
155 | acpi_dev = ACPI_COMPANION(dev); | 201 | if (!acpi_companion_match(dev)) |
156 | if (!acpi_dev) | ||
157 | return -ENODEV; | ||
158 | |||
159 | /* Fall back to bus specific way of modalias exporting */ | ||
160 | if (list_empty(&acpi_dev->pnp.ids)) | ||
161 | return -ENODEV; | 202 | return -ENODEV; |
162 | 203 | ||
163 | if (add_uevent_var(env, "MODALIAS=")) | 204 | if (add_uevent_var(env, "MODALIAS=")) |
164 | return -ENOMEM; | 205 | return -ENOMEM; |
165 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], | 206 | len = create_modalias(ACPI_COMPANION(dev), &env->buf[env->buflen - 1], |
166 | sizeof(env->buf) - env->buflen); | 207 | sizeof(env->buf) - env->buflen); |
167 | if (len <= 0) | 208 | if (len <= 0) |
168 | return len; | 209 | return len; |
@@ -179,18 +220,12 @@ EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias); | |||
179 | */ | 220 | */ |
180 | int acpi_device_modalias(struct device *dev, char *buf, int size) | 221 | int acpi_device_modalias(struct device *dev, char *buf, int size) |
181 | { | 222 | { |
182 | struct acpi_device *acpi_dev; | ||
183 | int len; | 223 | int len; |
184 | 224 | ||
185 | acpi_dev = ACPI_COMPANION(dev); | 225 | if (!acpi_companion_match(dev)) |
186 | if (!acpi_dev) | ||
187 | return -ENODEV; | 226 | return -ENODEV; |
188 | 227 | ||
189 | /* Fall back to bus specific way of modalias exporting */ | 228 | len = create_modalias(ACPI_COMPANION(dev), buf, size -1); |
190 | if (list_empty(&acpi_dev->pnp.ids)) | ||
191 | return -ENODEV; | ||
192 | |||
193 | len = create_modalias(acpi_dev, buf, size -1); | ||
194 | if (len <= 0) | 229 | if (len <= 0) |
195 | return len; | 230 | return len; |
196 | buf[len++] = '\n'; | 231 | buf[len++] = '\n'; |
@@ -853,6 +888,9 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, | |||
853 | if (!ids || !handle || acpi_bus_get_device(handle, &adev)) | 888 | if (!ids || !handle || acpi_bus_get_device(handle, &adev)) |
854 | return NULL; | 889 | return NULL; |
855 | 890 | ||
891 | if (!acpi_companion_match(dev)) | ||
892 | return NULL; | ||
893 | |||
856 | return __acpi_match_device(adev, ids); | 894 | return __acpi_match_device(adev, ids); |
857 | } | 895 | } |
858 | EXPORT_SYMBOL_GPL(acpi_match_device); | 896 | EXPORT_SYMBOL_GPL(acpi_match_device); |
@@ -1470,7 +1508,7 @@ static void acpi_wakeup_gpe_init(struct acpi_device *device) | |||
1470 | if (ACPI_FAILURE(status)) | 1508 | if (ACPI_FAILURE(status)) |
1471 | return; | 1509 | return; |
1472 | 1510 | ||
1473 | wakeup->flags.run_wake = !!(event_status & ACPI_EVENT_FLAG_HANDLE); | 1511 | wakeup->flags.run_wake = !!(event_status & ACPI_EVENT_FLAG_HAS_HANDLER); |
1474 | } | 1512 | } |
1475 | 1513 | ||
1476 | static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) | 1514 | static void acpi_bus_get_wakeup_device_flags(struct acpi_device *device) |
@@ -2315,6 +2353,7 @@ int __init acpi_scan_init(void) | |||
2315 | acpi_container_init(); | 2353 | acpi_container_init(); |
2316 | acpi_memory_hotplug_init(); | 2354 | acpi_memory_hotplug_init(); |
2317 | acpi_pnp_init(); | 2355 | acpi_pnp_init(); |
2356 | acpi_int340x_thermal_init(); | ||
2318 | 2357 | ||
2319 | mutex_lock(&acpi_scan_lock); | 2358 | mutex_lock(&acpi_scan_lock); |
2320 | /* | 2359 | /* |