return NOTIFY_DONE;
}
-static acpi_status
-acpi_video_bus_match(acpi_handle handle, u32 level, void *context,
- void **return_value)
-{
- struct acpi_device *device = context;
- struct acpi_device *sibling;
-
- if (handle == device->handle)
- return AE_CTRL_TERMINATE;
-
- sibling = acpi_fetch_acpi_dev(handle);
- if (!sibling)
- return AE_OK;
-
- if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME))
- return AE_ALREADY_EXISTS;
-
- return AE_OK;
-}
-
static void acpi_video_dev_register_backlight(struct acpi_video_device *device)
{
struct backlight_properties props;
return 0;
}
+static int duplicate_dev_check(struct device *sibling, void *data)
+{
+ struct acpi_video_bus *video;
+
+ if (sibling == data || !dev_is_auxiliary(sibling))
+ return 0;
+
+ guard(mutex)(&video_list_lock);
+
+ list_for_each_entry(video, &video_bus_head, entry) {
+ if (video == dev_get_drvdata(sibling))
+ return -EEXIST;
+ }
+
+ return 0;
+}
+
+static bool acpi_video_bus_dev_is_duplicate(struct device *dev)
+{
+ return device_for_each_child(dev->parent, dev, duplicate_dev_check);
+}
+
static int instance;
static int acpi_video_bus_probe(struct auxiliary_device *aux_dev,
const struct auxiliary_device_id *id_unused)
{
struct acpi_device *device = ACPI_COMPANION(&aux_dev->dev);
+ static DEFINE_MUTEX(probe_lock);
struct acpi_video_bus *video;
bool auto_detect;
int error;
- acpi_status status;
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE,
- acpi_dev_parent(device)->handle, 1,
- acpi_video_bus_match, NULL,
- device, NULL);
- if (status == AE_ALREADY_EXISTS) {
+ /* Probe one video bus device at a time in case there are duplicates. */
+ guard(mutex)(&probe_lock);
+
+ if (!allow_duplicates && acpi_video_bus_dev_is_duplicate(&aux_dev->dev)) {
pr_info(FW_BUG
"Duplicate ACPI video bus devices for the"
" same VGA controller, please try module "
"parameter \"video.allow_duplicates=1\""
"if the current driver doesn't work.\n");
- if (!allow_duplicates)
- return -ENODEV;
+ return -ENODEV;
}
video = kzalloc_obj(struct acpi_video_bus);