ACPI: Replace struct acpi_bus_ops with enum type
[cascardo/linux.git] / drivers / acpi / scan.c
index 53502d1..7082d11 100644 (file)
@@ -494,7 +494,8 @@ static int acpi_bus_match(struct device *dev, struct device_driver *drv)
        struct acpi_device *acpi_dev = to_acpi_device(dev);
        struct acpi_driver *acpi_drv = to_acpi_driver(drv);
 
-       return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
+       return acpi_dev->add_type >= ACPI_BUS_ADD_MATCH
+               && !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
 }
 
 static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
@@ -579,7 +580,7 @@ static int acpi_device_probe(struct device * dev)
 
        ret = acpi_bus_driver_init(acpi_dev, acpi_drv);
        if (!ret) {
-               if (acpi_dev->bus_ops.acpi_op_start)
+               if (acpi_dev->add_type == ACPI_BUS_ADD_START)
                        acpi_start_single_object(acpi_dev);
 
                if (acpi_drv->ops.notify) {
@@ -1418,10 +1419,21 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
        return 0;
 }
 
+/*
+ * acpi_hot_add_bind - Bind _ADR-based devices on hot-add.
+ * @device: ACPI device node to bind.
+ */
+static void acpi_hot_add_bind(struct acpi_device *device)
+{
+       if (device->flags.bus_address
+           && device->parent && device->parent->ops.bind)
+               device->parent->ops.bind(device);
+}
+
 static int acpi_add_single_object(struct acpi_device **child,
                                  acpi_handle handle, int type,
                                  unsigned long long sta,
-                                 struct acpi_bus_ops *ops)
+                                 enum acpi_bus_add_type add_type)
 {
        int result;
        struct acpi_device *device;
@@ -1437,7 +1449,7 @@ static int acpi_add_single_object(struct acpi_device **child,
        device->device_type = type;
        device->handle = handle;
        device->parent = acpi_bus_get_parent(handle);
-       device->bus_ops = *ops; /* workround for not call .start */
+       device->add_type = add_type;
        STRUCT_TO_INT(device->status) = sta;
 
        acpi_device_get_busid(device);
@@ -1490,13 +1502,8 @@ static int acpi_add_single_object(struct acpi_device **child,
 
        result = acpi_device_register(device);
 
-       /*
-        * Bind _ADR-Based Devices when hot add
-        */
-       if (device->flags.bus_address) {
-               if (device->parent && device->parent->ops.bind)
-                       device->parent->ops.bind(device);
-       }
+       if (device->add_type >= ACPI_BUS_ADD_MATCH)
+               acpi_hot_add_bind(device);
 
 end:
        if (!result) {
@@ -1519,16 +1526,12 @@ end:
 
 static void acpi_bus_add_power_resource(acpi_handle handle)
 {
-       struct acpi_bus_ops ops = {
-               .acpi_op_add = 1,
-               .acpi_op_start = 1,
-       };
        struct acpi_device *device = NULL;
 
        acpi_bus_get_device(handle, &device);
        if (!device)
                acpi_add_single_object(&device, handle, ACPI_BUS_TYPE_POWER,
-                                       ACPI_STA_DEFAULT, &ops);
+                                       ACPI_STA_DEFAULT, ACPI_BUS_ADD_START);
 }
 
 static int acpi_bus_type_and_status(acpi_handle handle, int *type,
@@ -1573,10 +1576,9 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type,
 static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
                                      void *context, void **return_value)
 {
-       struct acpi_bus_ops *ops = context;
+       struct acpi_device *device = NULL;
        int type;
        unsigned long long sta;
-       struct acpi_device *device;
        acpi_status status;
        int result;
 
@@ -1596,52 +1598,78 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
                return AE_CTRL_DEPTH;
        }
 
-       /*
-        * We may already have an acpi_device from a previous enumeration.  If
-        * so, we needn't add it again, but we may still have to start it.
-        */
-       device = NULL;
        acpi_bus_get_device(handle, &device);
-       if (ops->acpi_op_add && !device) {
-               acpi_add_single_object(&device, handle, type, sta, ops);
-               /* Is the device a known good platform device? */
-               if (device
-                   && !acpi_match_device_ids(device, acpi_platform_device_ids))
-                       acpi_create_platform_device(device);
-       }
-
-       if (!device)
-               return AE_CTRL_DEPTH;
-
-       if (ops->acpi_op_start && !(ops->acpi_op_add)) {
-               status = acpi_start_single_object(device);
-               if (ACPI_FAILURE(status))
+       if (!device) {
+               acpi_add_single_object(&device, handle, type, sta,
+                                      ACPI_BUS_ADD_BASIC);
+               if (!device)
                        return AE_CTRL_DEPTH;
+
+               device->add_type = context ?
+                                       ACPI_BUS_ADD_START : ACPI_BUS_ADD_MATCH;
+               acpi_hot_add_bind(device);
        }
 
        if (!*return_value)
                *return_value = device;
+
        return AE_OK;
 }
 
-static int acpi_bus_scan(acpi_handle handle, struct acpi_bus_ops *ops,
+static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
+                                         void *not_used, void **ret_not_used)
+{
+       acpi_status status = AE_OK;
+       struct acpi_device *device;
+       unsigned long long sta_not_used;
+       int type_not_used;
+
+       /*
+        * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
+        * namespace walks prematurely.
+        */
+       if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
+               return AE_OK;
+
+       if (acpi_bus_get_device(handle, &device))
+               return AE_CTRL_DEPTH;
+
+       if (!acpi_match_device_ids(device, acpi_platform_device_ids)) {
+               /* This is a known good platform device. */
+               acpi_create_platform_device(device);
+       } else if (device_attach(&device->dev)) {
+               status = AE_CTRL_DEPTH;
+       }
+       return status;
+}
+
+static int acpi_bus_scan(acpi_handle handle, bool start,
                         struct acpi_device **child)
 {
-       acpi_status status;
        void *device = NULL;
+       acpi_status status;
+       int ret = -ENODEV;
+
+       status = acpi_bus_check_add(handle, 0, (void *)start, &device);
+       if (ACPI_SUCCESS(status))
+               acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
+                                   acpi_bus_check_add, NULL, (void *)start,
+                                   &device);
+
+       if (!device)
+               goto out;
 
-       status = acpi_bus_check_add(handle, 0, ops, &device);
+       ret = 0;
+       status = acpi_bus_device_attach(handle, 0, NULL, NULL);
        if (ACPI_SUCCESS(status))
                acpi_walk_namespace(ACPI_TYPE_ANY, handle, ACPI_UINT32_MAX,
-                                   acpi_bus_check_add, NULL, ops, &device);
+                                   acpi_bus_device_attach, NULL, NULL, NULL);
 
+ out:
        if (child)
                *child = device;
 
-       if (device)
-               return 0;
-       else
-               return -ENODEV;
+       return ret;
 }
 
 /*
@@ -1660,31 +1688,42 @@ int
 acpi_bus_add(struct acpi_device **child,
             struct acpi_device *parent, acpi_handle handle, int type)
 {
-       struct acpi_bus_ops ops;
+       return acpi_bus_scan(handle, false, child);
+}
+EXPORT_SYMBOL(acpi_bus_add);
 
-       memset(&ops, 0, sizeof(ops));
-       ops.acpi_op_add = 1;
+static acpi_status acpi_bus_start_device(acpi_handle handle, u32 lvl,
+                                        void *not_used, void **ret_not_used)
+{
+       struct acpi_device *device;
+       unsigned long long sta_not_used;
+       int type_not_used;
+
+       /*
+        * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
+        * namespace walks prematurely.
+        */
+       if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
+               return AE_OK;
 
-       return acpi_bus_scan(handle, &ops, child);
+       if (acpi_bus_get_device(handle, &device))
+               return AE_CTRL_DEPTH;
+
+       return acpi_start_single_object(device);
 }
-EXPORT_SYMBOL(acpi_bus_add);
 
 int acpi_bus_start(struct acpi_device *device)
 {
-       struct acpi_bus_ops ops;
-       int result;
-
        if (!device)
                return -EINVAL;
 
-       memset(&ops, 0, sizeof(ops));
-       ops.acpi_op_start = 1;
-
-       result = acpi_bus_scan(device->handle, &ops, NULL);
+       if (ACPI_SUCCESS(acpi_start_single_object(device)))
+               acpi_walk_namespace(ACPI_TYPE_ANY, device->handle,
+                                   ACPI_UINT32_MAX, acpi_bus_start_device,
+                                   NULL, NULL, NULL);
 
        acpi_update_all_gpes();
-
-       return result;
+       return 0;
 }
 EXPORT_SYMBOL(acpi_bus_start);
 
@@ -1747,11 +1786,6 @@ static int acpi_bus_scan_fixed(void)
 {
        int result = 0;
        struct acpi_device *device = NULL;
-       struct acpi_bus_ops ops;
-
-       memset(&ops, 0, sizeof(ops));
-       ops.acpi_op_add = 1;
-       ops.acpi_op_start = 1;
 
        /*
         * Enumerate all fixed-feature devices.
@@ -1760,7 +1794,7 @@ static int acpi_bus_scan_fixed(void)
                result = acpi_add_single_object(&device, NULL,
                                                ACPI_BUS_TYPE_POWER_BUTTON,
                                                ACPI_STA_DEFAULT,
-                                               &ops);
+                                               ACPI_BUS_ADD_START);
                device_init_wakeup(&device->dev, true);
        }
 
@@ -1768,7 +1802,7 @@ static int acpi_bus_scan_fixed(void)
                result = acpi_add_single_object(&device, NULL,
                                                ACPI_BUS_TYPE_SLEEP_BUTTON,
                                                ACPI_STA_DEFAULT,
-                                               &ops);
+                                               ACPI_BUS_ADD_START);
        }
 
        return result;
@@ -1777,11 +1811,6 @@ static int acpi_bus_scan_fixed(void)
 int __init acpi_scan_init(void)
 {
        int result;
-       struct acpi_bus_ops ops;
-
-       memset(&ops, 0, sizeof(ops));
-       ops.acpi_op_add = 1;
-       ops.acpi_op_start = 1;
 
        result = bus_register(&acpi_bus_type);
        if (result) {
@@ -1790,11 +1819,12 @@ int __init acpi_scan_init(void)
        }
 
        acpi_power_init();
+       acpi_pci_root_init();
 
        /*
         * Enumerate devices in the ACPI namespace.
         */
-       result = acpi_bus_scan(ACPI_ROOT_OBJECT, &ops, &acpi_root);
+       result = acpi_bus_scan(ACPI_ROOT_OBJECT, true, &acpi_root);
 
        if (!result)
                result = acpi_bus_scan_fixed();