diff options
| -rw-r--r-- | drivers/acpi/scan.c | 388 |
1 files changed, 232 insertions, 156 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index bbca7830e18a..d2e3c3e3f9c9 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -114,7 +114,12 @@ int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler, | |||
| 114 | return 0; | 114 | return 0; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | /* | 117 | /** |
| 118 | * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent | ||
| 119 | * @acpi_dev: ACPI device object. | ||
| 120 | * @modalias: Buffer to print into. | ||
| 121 | * @size: Size of the buffer. | ||
| 122 | * | ||
| 118 | * Creates hid/cid(s) string needed for modalias and uevent | 123 | * Creates hid/cid(s) string needed for modalias and uevent |
| 119 | * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: | 124 | * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: |
| 120 | * char *modalias: "acpi:IBM0001:ACPI0001" | 125 | * char *modalias: "acpi:IBM0001:ACPI0001" |
| @@ -122,68 +127,98 @@ int acpi_scan_add_handler_with_hotplug(struct acpi_scan_handler *handler, | |||
| 122 | * -EINVAL: output error | 127 | * -EINVAL: output error |
| 123 | * -ENOMEM: output is truncated | 128 | * -ENOMEM: output is truncated |
| 124 | */ | 129 | */ |
| 125 | static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | 130 | static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias, |
| 126 | int size) | 131 | int size) |
| 127 | { | 132 | { |
| 128 | int len; | 133 | int len; |
| 129 | int count; | 134 | int count; |
| 130 | struct acpi_hardware_id *id; | 135 | struct acpi_hardware_id *id; |
| 131 | 136 | ||
| 132 | if (list_empty(&acpi_dev->pnp.ids)) | ||
| 133 | return 0; | ||
| 134 | |||
| 135 | /* | 137 | /* |
| 136 | * If the device has PRP0001 we expose DT compatible modalias | 138 | * Since we skip PRP0001 from the modalias below, 0 should be returned |
| 137 | * instead in form of of:NnameTCcompatible. | 139 | * if PRP0001 is the only ACPI/PNP ID in the device's list. |
| 138 | */ | 140 | */ |
| 139 | if (acpi_dev->data.of_compatible) { | 141 | count = 0; |
| 140 | struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; | 142 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) |
| 141 | const union acpi_object *of_compatible, *obj; | 143 | if (strcmp(id->id, "PRP0001")) |
| 142 | int i, nval; | 144 | count++; |
| 143 | char *c; | ||
| 144 | |||
| 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 | 145 | ||
| 176 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) { | 146 | if (!count) |
| 177 | count = snprintf(&modalias[len], size, "%s:", id->id); | 147 | return 0; |
| 178 | if (count < 0) | 148 | |
| 179 | return -EINVAL; | 149 | len = snprintf(modalias, size, "acpi:"); |
| 180 | if (count >= size) | 150 | if (len <= 0) |
| 181 | return -ENOMEM; | 151 | return len; |
| 182 | len += count; | 152 | |
| 183 | size -= count; | 153 | size -= len; |
| 184 | } | 154 | |
| 155 | list_for_each_entry(id, &acpi_dev->pnp.ids, list) { | ||
| 156 | if (!strcmp(id->id, "PRP0001")) | ||
| 157 | continue; | ||
| 158 | |||
| 159 | count = snprintf(&modalias[len], size, "%s:", id->id); | ||
| 160 | if (count < 0) | ||
| 161 | return -EINVAL; | ||
| 162 | |||
| 163 | if (count >= size) | ||
| 164 | return -ENOMEM; | ||
| 165 | |||
| 166 | len += count; | ||
| 167 | size -= count; | ||
| 185 | } | 168 | } |
| 169 | modalias[len] = '\0'; | ||
| 170 | return len; | ||
| 171 | } | ||
| 186 | 172 | ||
| 173 | /** | ||
| 174 | * create_of_modalias - Creates DT compatible string for modalias and uevent | ||
| 175 | * @acpi_dev: ACPI device object. | ||
| 176 | * @modalias: Buffer to print into. | ||
| 177 | * @size: Size of the buffer. | ||
| 178 | * | ||
| 179 | * Expose DT compatible modalias as of:NnameTCcompatible. This function should | ||
| 180 | * only be called for devices having PRP0001 in their list of ACPI/PNP IDs. | ||
| 181 | */ | ||
| 182 | static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias, | ||
| 183 | int size) | ||
| 184 | { | ||
| 185 | struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; | ||
| 186 | const union acpi_object *of_compatible, *obj; | ||
| 187 | int len, count; | ||
| 188 | int i, nval; | ||
| 189 | char *c; | ||
| 190 | |||
| 191 | acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf); | ||
| 192 | /* DT strings are all in lower case */ | ||
| 193 | for (c = buf.pointer; *c != '\0'; c++) | ||
| 194 | *c = tolower(*c); | ||
| 195 | |||
| 196 | len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer); | ||
| 197 | ACPI_FREE(buf.pointer); | ||
| 198 | |||
| 199 | if (len <= 0) | ||
| 200 | return len; | ||
| 201 | |||
| 202 | of_compatible = acpi_dev->data.of_compatible; | ||
| 203 | if (of_compatible->type == ACPI_TYPE_PACKAGE) { | ||
| 204 | nval = of_compatible->package.count; | ||
| 205 | obj = of_compatible->package.elements; | ||
| 206 | } else { /* Must be ACPI_TYPE_STRING. */ | ||
| 207 | nval = 1; | ||
| 208 | obj = of_compatible; | ||
| 209 | } | ||
| 210 | for (i = 0; i < nval; i++, obj++) { | ||
| 211 | count = snprintf(&modalias[len], size, "C%s", | ||
| 212 | obj->string.pointer); | ||
| 213 | if (count < 0) | ||
| 214 | return -EINVAL; | ||
| 215 | |||
| 216 | if (count >= size) | ||
| 217 | return -ENOMEM; | ||
| 218 | |||
| 219 | len += count; | ||
| 220 | size -= count; | ||
| 221 | } | ||
| 187 | modalias[len] = '\0'; | 222 | modalias[len] = '\0'; |
| 188 | return len; | 223 | return len; |
| 189 | } | 224 | } |
| @@ -194,7 +229,8 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
| 194 | * | 229 | * |
| 195 | * Check if the given device has an ACPI companion and if that companion has | 230 | * Check if the given device has an ACPI companion and if that companion has |
| 196 | * a valid list of PNP IDs, and if the device is the first (primary) physical | 231 | * a valid list of PNP IDs, and if the device is the first (primary) physical |
| 197 | * device associated with it. | 232 | * device associated with it. Return the companion pointer if that's the case |
| 233 | * or NULL otherwise. | ||
| 198 | * | 234 | * |
| 199 | * If multiple physical devices are attached to a single ACPI companion, we need | 235 | * If multiple physical devices are attached to a single ACPI companion, we need |
| 200 | * to be careful. The usage scenario for this kind of relationship is that all | 236 | * to be careful. The usage scenario for this kind of relationship is that all |
| @@ -208,88 +244,127 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
| 208 | * resources available from it but they will be matched normally using functions | 244 | * resources available from it but they will be matched normally using functions |
| 209 | * provided by their bus types (and analogously for their modalias). | 245 | * provided by their bus types (and analogously for their modalias). |
| 210 | */ | 246 | */ |
| 211 | static bool acpi_companion_match(const struct device *dev) | 247 | static struct acpi_device *acpi_companion_match(const struct device *dev) |
| 212 | { | 248 | { |
| 213 | struct acpi_device *adev; | 249 | struct acpi_device *adev; |
| 214 | bool ret; | ||
| 215 | 250 | ||
| 216 | adev = ACPI_COMPANION(dev); | 251 | adev = ACPI_COMPANION(dev); |
| 217 | if (!adev) | 252 | if (!adev) |
| 218 | return false; | 253 | return NULL; |
| 219 | 254 | ||
| 220 | if (list_empty(&adev->pnp.ids)) | 255 | if (list_empty(&adev->pnp.ids)) |
| 221 | return false; | 256 | return NULL; |
| 222 | 257 | ||
| 223 | mutex_lock(&adev->physical_node_lock); | 258 | mutex_lock(&adev->physical_node_lock); |
| 224 | if (list_empty(&adev->physical_node_list)) { | 259 | if (list_empty(&adev->physical_node_list)) { |
| 225 | ret = false; | 260 | adev = NULL; |
| 226 | } else { | 261 | } else { |
| 227 | const struct acpi_device_physical_node *node; | 262 | const struct acpi_device_physical_node *node; |
| 228 | 263 | ||
| 229 | node = list_first_entry(&adev->physical_node_list, | 264 | node = list_first_entry(&adev->physical_node_list, |
| 230 | struct acpi_device_physical_node, node); | 265 | struct acpi_device_physical_node, node); |
| 231 | ret = node->dev == dev; | 266 | if (node->dev != dev) |
| 267 | adev = NULL; | ||
| 232 | } | 268 | } |
| 233 | mutex_unlock(&adev->physical_node_lock); | 269 | mutex_unlock(&adev->physical_node_lock); |
| 234 | 270 | ||
| 235 | return ret; | 271 | return adev; |
| 236 | } | 272 | } |
| 237 | 273 | ||
| 238 | /* | 274 | static int __acpi_device_uevent_modalias(struct acpi_device *adev, |
| 239 | * Creates uevent modalias field for ACPI enumerated devices. | 275 | struct kobj_uevent_env *env) |
| 240 | * Because the other buses does not support ACPI HIDs & CIDs. | ||
| 241 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: | ||
| 242 | * "acpi:IBM0001:ACPI0001" | ||
| 243 | */ | ||
| 244 | int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) | ||
| 245 | { | 276 | { |
| 246 | int len; | 277 | int len; |
| 247 | 278 | ||
| 248 | if (!acpi_companion_match(dev)) | 279 | if (!adev) |
| 249 | return -ENODEV; | 280 | return -ENODEV; |
| 250 | 281 | ||
| 282 | if (list_empty(&adev->pnp.ids)) | ||
| 283 | return 0; | ||
| 284 | |||
| 251 | if (add_uevent_var(env, "MODALIAS=")) | 285 | if (add_uevent_var(env, "MODALIAS=")) |
| 252 | return -ENOMEM; | 286 | return -ENOMEM; |
| 253 | len = create_modalias(ACPI_COMPANION(dev), &env->buf[env->buflen - 1], | 287 | |
| 254 | sizeof(env->buf) - env->buflen); | 288 | len = create_pnp_modalias(adev, &env->buf[env->buflen - 1], |
| 255 | if (len <= 0) | 289 | sizeof(env->buf) - env->buflen); |
| 290 | if (len < 0) | ||
| 291 | return len; | ||
| 292 | |||
| 293 | env->buflen += len; | ||
| 294 | if (!adev->data.of_compatible) | ||
| 295 | return 0; | ||
| 296 | |||
| 297 | if (len > 0 && add_uevent_var(env, "MODALIAS=")) | ||
| 298 | return -ENOMEM; | ||
| 299 | |||
| 300 | len = create_of_modalias(adev, &env->buf[env->buflen - 1], | ||
| 301 | sizeof(env->buf) - env->buflen); | ||
| 302 | if (len < 0) | ||
| 256 | return len; | 303 | return len; |
| 304 | |||
| 257 | env->buflen += len; | 305 | env->buflen += len; |
| 306 | |||
| 258 | return 0; | 307 | return 0; |
| 259 | } | 308 | } |
| 260 | EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias); | ||
| 261 | 309 | ||
| 262 | /* | 310 | /* |
| 263 | * Creates modalias sysfs attribute for ACPI enumerated devices. | 311 | * Creates uevent modalias field for ACPI enumerated devices. |
| 264 | * Because the other buses does not support ACPI HIDs & CIDs. | 312 | * Because the other buses does not support ACPI HIDs & CIDs. |
| 265 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: | 313 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: |
| 266 | * "acpi:IBM0001:ACPI0001" | 314 | * "acpi:IBM0001:ACPI0001" |
| 267 | */ | 315 | */ |
| 268 | int acpi_device_modalias(struct device *dev, char *buf, int size) | 316 | int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) |
| 269 | { | 317 | { |
| 270 | int len; | 318 | return __acpi_device_uevent_modalias(acpi_companion_match(dev), env); |
| 319 | } | ||
| 320 | EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias); | ||
| 321 | |||
| 322 | static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size) | ||
| 323 | { | ||
| 324 | int len, count; | ||
| 271 | 325 | ||
| 272 | if (!acpi_companion_match(dev)) | 326 | if (!adev) |
| 273 | return -ENODEV; | 327 | return -ENODEV; |
| 274 | 328 | ||
| 275 | len = create_modalias(ACPI_COMPANION(dev), buf, size -1); | 329 | if (list_empty(&adev->pnp.ids)) |
| 276 | if (len <= 0) | 330 | return 0; |
| 331 | |||
| 332 | len = create_pnp_modalias(adev, buf, size - 1); | ||
| 333 | if (len < 0) { | ||
| 334 | return len; | ||
| 335 | } else if (len > 0) { | ||
| 336 | buf[len++] = '\n'; | ||
| 337 | size -= len; | ||
| 338 | } | ||
| 339 | if (!adev->data.of_compatible) | ||
| 277 | return len; | 340 | return len; |
| 278 | buf[len++] = '\n'; | 341 | |
| 342 | count = create_of_modalias(adev, buf + len, size - 1); | ||
| 343 | if (count < 0) { | ||
| 344 | return count; | ||
| 345 | } else if (count > 0) { | ||
| 346 | len += count; | ||
| 347 | buf[len++] = '\n'; | ||
| 348 | } | ||
| 349 | |||
| 279 | return len; | 350 | return len; |
| 280 | } | 351 | } |
| 352 | |||
| 353 | /* | ||
| 354 | * Creates modalias sysfs attribute for ACPI enumerated devices. | ||
| 355 | * Because the other buses does not support ACPI HIDs & CIDs. | ||
| 356 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: | ||
| 357 | * "acpi:IBM0001:ACPI0001" | ||
| 358 | */ | ||
| 359 | int acpi_device_modalias(struct device *dev, char *buf, int size) | ||
| 360 | { | ||
| 361 | return __acpi_device_modalias(acpi_companion_match(dev), buf, size); | ||
| 362 | } | ||
| 281 | EXPORT_SYMBOL_GPL(acpi_device_modalias); | 363 | EXPORT_SYMBOL_GPL(acpi_device_modalias); |
| 282 | 364 | ||
| 283 | static ssize_t | 365 | static ssize_t |
| 284 | acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { | 366 | acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { |
| 285 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 367 | return __acpi_device_modalias(to_acpi_device(dev), buf, 1024); |
| 286 | int len; | ||
| 287 | |||
| 288 | len = create_modalias(acpi_dev, buf, 1024); | ||
| 289 | if (len <= 0) | ||
| 290 | return len; | ||
| 291 | buf[len++] = '\n'; | ||
| 292 | return len; | ||
| 293 | } | 368 | } |
| 294 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); | 369 | static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); |
| 295 | 370 | ||
| @@ -894,8 +969,51 @@ static void acpi_device_remove_files(struct acpi_device *dev) | |||
| 894 | ACPI Bus operations | 969 | ACPI Bus operations |
| 895 | -------------------------------------------------------------------------- */ | 970 | -------------------------------------------------------------------------- */ |
| 896 | 971 | ||
| 972 | /** | ||
| 973 | * acpi_of_match_device - Match device object using the "compatible" property. | ||
| 974 | * @adev: ACPI device object to match. | ||
| 975 | * @of_match_table: List of device IDs to match against. | ||
| 976 | * | ||
| 977 | * If @dev has an ACPI companion which has the special PRP0001 device ID in its | ||
| 978 | * list of identifiers and a _DSD object with the "compatible" property, use | ||
| 979 | * that property to match against the given list of identifiers. | ||
| 980 | */ | ||
| 981 | static bool acpi_of_match_device(struct acpi_device *adev, | ||
| 982 | const struct of_device_id *of_match_table) | ||
| 983 | { | ||
| 984 | const union acpi_object *of_compatible, *obj; | ||
| 985 | int i, nval; | ||
| 986 | |||
| 987 | if (!adev) | ||
| 988 | return false; | ||
| 989 | |||
| 990 | of_compatible = adev->data.of_compatible; | ||
| 991 | if (!of_match_table || !of_compatible) | ||
| 992 | return false; | ||
| 993 | |||
| 994 | if (of_compatible->type == ACPI_TYPE_PACKAGE) { | ||
| 995 | nval = of_compatible->package.count; | ||
| 996 | obj = of_compatible->package.elements; | ||
| 997 | } else { /* Must be ACPI_TYPE_STRING. */ | ||
| 998 | nval = 1; | ||
| 999 | obj = of_compatible; | ||
| 1000 | } | ||
| 1001 | /* Now we can look for the driver DT compatible strings */ | ||
| 1002 | for (i = 0; i < nval; i++, obj++) { | ||
| 1003 | const struct of_device_id *id; | ||
| 1004 | |||
| 1005 | for (id = of_match_table; id->compatible[0]; id++) | ||
| 1006 | if (!strcasecmp(obj->string.pointer, id->compatible)) | ||
| 1007 | return true; | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | return false; | ||
| 1011 | } | ||
| 1012 | |||
| 897 | static const struct acpi_device_id *__acpi_match_device( | 1013 | static const struct acpi_device_id *__acpi_match_device( |
| 898 | struct acpi_device *device, const struct acpi_device_id *ids) | 1014 | struct acpi_device *device, |
| 1015 | const struct acpi_device_id *ids, | ||
| 1016 | const struct of_device_id *of_ids) | ||
| 899 | { | 1017 | { |
| 900 | const struct acpi_device_id *id; | 1018 | const struct acpi_device_id *id; |
| 901 | struct acpi_hardware_id *hwid; | 1019 | struct acpi_hardware_id *hwid; |
| @@ -904,14 +1022,27 @@ static const struct acpi_device_id *__acpi_match_device( | |||
| 904 | * If the device is not present, it is unnecessary to load device | 1022 | * If the device is not present, it is unnecessary to load device |
| 905 | * driver for it. | 1023 | * driver for it. |
| 906 | */ | 1024 | */ |
| 907 | if (!device->status.present) | 1025 | if (!device || !device->status.present) |
| 908 | return NULL; | 1026 | return NULL; |
| 909 | 1027 | ||
| 910 | for (id = ids; id->id[0]; id++) | 1028 | list_for_each_entry(hwid, &device->pnp.ids, list) { |
| 911 | list_for_each_entry(hwid, &device->pnp.ids, list) | 1029 | /* First, check the ACPI/PNP IDs provided by the caller. */ |
| 1030 | for (id = ids; id->id[0]; id++) | ||
| 912 | if (!strcmp((char *) id->id, hwid->id)) | 1031 | if (!strcmp((char *) id->id, hwid->id)) |
| 913 | return id; | 1032 | return id; |
| 914 | 1033 | ||
| 1034 | /* | ||
| 1035 | * Next, check the special "PRP0001" ID and try to match the | ||
| 1036 | * "compatible" property if found. | ||
| 1037 | * | ||
| 1038 | * The id returned by the below is not valid, but the only | ||
| 1039 | * caller passing non-NULL of_ids here is only interested in | ||
| 1040 | * whether or not the return value is NULL. | ||
| 1041 | */ | ||
| 1042 | if (!strcmp("PRP0001", hwid->id) | ||
| 1043 | && acpi_of_match_device(device, of_ids)) | ||
| 1044 | return id; | ||
| 1045 | } | ||
| 915 | return NULL; | 1046 | return NULL; |
| 916 | } | 1047 | } |
| 917 | 1048 | ||
| @@ -929,68 +1060,26 @@ static const struct acpi_device_id *__acpi_match_device( | |||
| 929 | const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, | 1060 | const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, |
| 930 | const struct device *dev) | 1061 | const struct device *dev) |
| 931 | { | 1062 | { |
| 932 | struct acpi_device *adev; | 1063 | return __acpi_match_device(acpi_companion_match(dev), ids, NULL); |
| 933 | acpi_handle handle = ACPI_HANDLE(dev); | ||
| 934 | |||
| 935 | if (!ids || !handle || acpi_bus_get_device(handle, &adev)) | ||
| 936 | return NULL; | ||
| 937 | |||
| 938 | if (!acpi_companion_match(dev)) | ||
| 939 | return NULL; | ||
| 940 | |||
| 941 | return __acpi_match_device(adev, ids); | ||
| 942 | } | 1064 | } |
| 943 | EXPORT_SYMBOL_GPL(acpi_match_device); | 1065 | EXPORT_SYMBOL_GPL(acpi_match_device); |
| 944 | 1066 | ||
| 945 | int acpi_match_device_ids(struct acpi_device *device, | 1067 | int acpi_match_device_ids(struct acpi_device *device, |
| 946 | const struct acpi_device_id *ids) | 1068 | const struct acpi_device_id *ids) |
| 947 | { | 1069 | { |
| 948 | return __acpi_match_device(device, ids) ? 0 : -ENOENT; | 1070 | return __acpi_match_device(device, ids, NULL) ? 0 : -ENOENT; |
| 949 | } | 1071 | } |
| 950 | EXPORT_SYMBOL(acpi_match_device_ids); | 1072 | EXPORT_SYMBOL(acpi_match_device_ids); |
| 951 | 1073 | ||
| 952 | /* Performs match against special "PRP0001" shoehorn ACPI ID */ | ||
| 953 | static 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 | |||
| 987 | bool acpi_driver_match_device(struct device *dev, | 1074 | bool acpi_driver_match_device(struct device *dev, |
| 988 | const struct device_driver *drv) | 1075 | const struct device_driver *drv) |
| 989 | { | 1076 | { |
| 990 | if (!drv->acpi_match_table) | 1077 | if (!drv->acpi_match_table) |
| 991 | return acpi_of_driver_match_device(dev, drv); | 1078 | return acpi_of_match_device(ACPI_COMPANION(dev), |
| 1079 | drv->of_match_table); | ||
| 992 | 1080 | ||
| 993 | return !!acpi_match_device(drv->acpi_match_table, dev); | 1081 | return !!__acpi_match_device(acpi_companion_match(dev), |
| 1082 | drv->acpi_match_table, drv->of_match_table); | ||
| 994 | } | 1083 | } |
| 995 | EXPORT_SYMBOL_GPL(acpi_driver_match_device); | 1084 | EXPORT_SYMBOL_GPL(acpi_driver_match_device); |
| 996 | 1085 | ||
| @@ -1031,20 +1120,7 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv) | |||
| 1031 | 1120 | ||
| 1032 | static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) | 1121 | static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 1033 | { | 1122 | { |
| 1034 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 1123 | return __acpi_device_uevent_modalias(to_acpi_device(dev), env); |
| 1035 | int len; | ||
| 1036 | |||
| 1037 | if (list_empty(&acpi_dev->pnp.ids)) | ||
| 1038 | return 0; | ||
| 1039 | |||
| 1040 | if (add_uevent_var(env, "MODALIAS=")) | ||
| 1041 | return -ENOMEM; | ||
| 1042 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], | ||
| 1043 | sizeof(env->buf) - env->buflen); | ||
| 1044 | if (len <= 0) | ||
| 1045 | return len; | ||
| 1046 | env->buflen += len; | ||
| 1047 | return 0; | ||
| 1048 | } | 1124 | } |
| 1049 | 1125 | ||
| 1050 | static void acpi_device_notify(acpi_handle handle, u32 event, void *data) | 1126 | static void acpi_device_notify(acpi_handle handle, u32 event, void *data) |
| @@ -1062,10 +1138,10 @@ static void acpi_device_notify_fixed(void *data) | |||
| 1062 | acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device); | 1138 | acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device); |
| 1063 | } | 1139 | } |
| 1064 | 1140 | ||
| 1065 | static acpi_status acpi_device_fixed_event(void *data) | 1141 | static u32 acpi_device_fixed_event(void *data) |
| 1066 | { | 1142 | { |
| 1067 | acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data); | 1143 | acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data); |
| 1068 | return AE_OK; | 1144 | return ACPI_INTERRUPT_HANDLED; |
| 1069 | } | 1145 | } |
| 1070 | 1146 | ||
| 1071 | static int acpi_device_install_notify_handler(struct acpi_device *device) | 1147 | static int acpi_device_install_notify_handler(struct acpi_device *device) |
