Merge branch 'acpi-scan' into acpi-pm
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 29 Jul 2015 21:57:51 +0000 (23:57 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 29 Jul 2015 21:57:51 +0000 (23:57 +0200)
Conflicts:
drivers/acpi/scan.c

The conflict is resolved by moving the just introduced
acpi_device_is_first_physical_node() to bus.c and using
the existing acpi_companion_match() from there.

There will be an additional commit to combine the two.

1  2 
drivers/acpi/bus.c
drivers/acpi/internal.h
drivers/acpi/scan.c

index 513e7230e3d04bbf8e7fd9ded2cc4300c938c58e,7a3ad929f09573894dd20cc038fd2840aed5483e..a23903c8bea93b8cc2aa7ab05972e0dc202a1ebf
@@@ -423,6 -423,384 +423,413 @@@ static void acpi_bus_notify(acpi_handl
        acpi_evaluate_ost(handle, type, ost_code, NULL);
  }
  
+ static void acpi_device_notify(acpi_handle handle, u32 event, void *data)
+ {
+       struct acpi_device *device = data;
+       device->driver->ops.notify(device, event);
+ }
+ static void acpi_device_notify_fixed(void *data)
+ {
+       struct acpi_device *device = data;
+       /* Fixed hardware devices have no handles */
+       acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
+ }
+ static u32 acpi_device_fixed_event(void *data)
+ {
+       acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data);
+       return ACPI_INTERRUPT_HANDLED;
+ }
+ static int acpi_device_install_notify_handler(struct acpi_device *device)
+ {
+       acpi_status status;
+       if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
+               status =
+                   acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+                                                    acpi_device_fixed_event,
+                                                    device);
+       else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
+               status =
+                   acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+                                                    acpi_device_fixed_event,
+                                                    device);
+       else
+               status = acpi_install_notify_handler(device->handle,
+                                                    ACPI_DEVICE_NOTIFY,
+                                                    acpi_device_notify,
+                                                    device);
+       if (ACPI_FAILURE(status))
+               return -EINVAL;
+       return 0;
+ }
+ static void acpi_device_remove_notify_handler(struct acpi_device *device)
+ {
+       if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
+               acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
+                                               acpi_device_fixed_event);
+       else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
+               acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
+                                               acpi_device_fixed_event);
+       else
+               acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
+                                          acpi_device_notify);
+ }
+ /* --------------------------------------------------------------------------
+                              Device Matching
+    -------------------------------------------------------------------------- */
++/**
++ * acpi_device_is_first_physical_node - Is given dev first physical node
++ * @adev: ACPI companion device
++ * @dev: Physical device to check
++ *
++ * Function checks if given @dev is the first physical devices attached to
++ * the ACPI companion device. This distinction is needed in some cases
++ * where the same companion device is shared between many physical devices.
++ *
++ * Note that the caller have to provide valid @adev pointer.
++ */
++bool acpi_device_is_first_physical_node(struct acpi_device *adev,
++                                      const struct device *dev)
++{
++      bool ret = false;
++
++      mutex_lock(&adev->physical_node_lock);
++      if (!list_empty(&adev->physical_node_list)) {
++              const struct acpi_device_physical_node *node;
++
++              node = list_first_entry(&adev->physical_node_list,
++                                      struct acpi_device_physical_node, node);
++              ret = node->dev == dev;
++      }
++      mutex_unlock(&adev->physical_node_lock);
++
++      return ret;
++}
++
+ /*
+  * acpi_companion_match() - Can we match via ACPI companion device
+  * @dev: Device in question
+  *
+  * Check if the given device has an ACPI companion and if that companion has
+  * a valid list of PNP IDs, and if the device is the first (primary) physical
+  * device associated with it.  Return the companion pointer if that's the case
+  * or NULL otherwise.
+  *
+  * If multiple physical devices are attached to a single ACPI companion, we need
+  * to be careful.  The usage scenario for this kind of relationship is that all
+  * of the physical devices in question use resources provided by the ACPI
+  * companion.  A typical case is an MFD device where all the sub-devices share
+  * the parent's ACPI companion.  In such cases we can only allow the primary
+  * (first) physical device to be matched with the help of the companion's PNP
+  * IDs.
+  *
+  * Additional physical devices sharing the ACPI companion can still use
+  * resources available from it but they will be matched normally using functions
+  * provided by their bus types (and analogously for their modalias).
+  */
+ struct acpi_device *acpi_companion_match(const struct device *dev)
+ {
+       struct acpi_device *adev;
+       struct mutex *physical_node_lock;
+       adev = ACPI_COMPANION(dev);
+       if (!adev)
+               return NULL;
+       if (list_empty(&adev->pnp.ids))
+               return NULL;
+       physical_node_lock = &adev->physical_node_lock;
+       mutex_lock(physical_node_lock);
+       if (list_empty(&adev->physical_node_list)) {
+               adev = NULL;
+       } else {
+               const struct acpi_device_physical_node *node;
+               node = list_first_entry(&adev->physical_node_list,
+                                       struct acpi_device_physical_node, node);
+               if (node->dev != dev)
+                       adev = NULL;
+       }
+       mutex_unlock(physical_node_lock);
+       return adev;
+ }
+ /**
+  * acpi_of_match_device - Match device object using the "compatible" property.
+  * @adev: ACPI device object to match.
+  * @of_match_table: List of device IDs to match against.
+  *
+  * If @dev has an ACPI companion which has ACPI_DT_NAMESPACE_HID in its list of
+  * identifiers and a _DSD object with the "compatible" property, use that
+  * property to match against the given list of identifiers.
+  */
+ static bool acpi_of_match_device(struct acpi_device *adev,
+                                const struct of_device_id *of_match_table)
+ {
+       const union acpi_object *of_compatible, *obj;
+       int i, nval;
+       if (!adev)
+               return false;
+       of_compatible = adev->data.of_compatible;
+       if (!of_match_table || !of_compatible)
+               return false;
+       if (of_compatible->type == ACPI_TYPE_PACKAGE) {
+               nval = of_compatible->package.count;
+               obj = of_compatible->package.elements;
+       } else { /* Must be ACPI_TYPE_STRING. */
+               nval = 1;
+               obj = of_compatible;
+       }
+       /* Now we can look for the driver DT compatible strings */
+       for (i = 0; i < nval; i++, obj++) {
+               const struct of_device_id *id;
+               for (id = of_match_table; id->compatible[0]; id++)
+                       if (!strcasecmp(obj->string.pointer, id->compatible))
+                               return true;
+       }
+       return false;
+ }
+ static bool __acpi_match_device_cls(const struct acpi_device_id *id,
+                                   struct acpi_hardware_id *hwid)
+ {
+       int i, msk, byte_shift;
+       char buf[3];
+       if (!id->cls)
+               return false;
+       /* Apply class-code bitmask, before checking each class-code byte */
+       for (i = 1; i <= 3; i++) {
+               byte_shift = 8 * (3 - i);
+               msk = (id->cls_msk >> byte_shift) & 0xFF;
+               if (!msk)
+                       continue;
+               sprintf(buf, "%02x", (id->cls >> byte_shift) & msk);
+               if (strncmp(buf, &hwid->id[(i - 1) * 2], 2))
+                       return false;
+       }
+       return true;
+ }
+ static const struct acpi_device_id *__acpi_match_device(
+       struct acpi_device *device,
+       const struct acpi_device_id *ids,
+       const struct of_device_id *of_ids)
+ {
+       const struct acpi_device_id *id;
+       struct acpi_hardware_id *hwid;
+       /*
+        * If the device is not present, it is unnecessary to load device
+        * driver for it.
+        */
+       if (!device || !device->status.present)
+               return NULL;
+       list_for_each_entry(hwid, &device->pnp.ids, list) {
+               /* First, check the ACPI/PNP IDs provided by the caller. */
+               for (id = ids; id->id[0] || id->cls; id++) {
+                       if (id->id[0] && !strcmp((char *) id->id, hwid->id))
+                               return id;
+                       else if (id->cls && __acpi_match_device_cls(id, hwid))
+                               return id;
+               }
+               /*
+                * Next, check ACPI_DT_NAMESPACE_HID and try to match the
+                * "compatible" property if found.
+                *
+                * The id returned by the below is not valid, but the only
+                * caller passing non-NULL of_ids here is only interested in
+                * whether or not the return value is NULL.
+                */
+               if (!strcmp(ACPI_DT_NAMESPACE_HID, hwid->id)
+                   && acpi_of_match_device(device, of_ids))
+                       return id;
+       }
+       return NULL;
+ }
+ /**
+  * acpi_match_device - Match a struct device against a given list of ACPI IDs
+  * @ids: Array of struct acpi_device_id object to match against.
+  * @dev: The device structure to match.
+  *
+  * Check if @dev has a valid ACPI handle and if there is a struct acpi_device
+  * object for that handle and use that object to match against a given list of
+  * device IDs.
+  *
+  * Return a pointer to the first matching ID on success or %NULL on failure.
+  */
+ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
+                                              const struct device *dev)
+ {
+       return __acpi_match_device(acpi_companion_match(dev), ids, NULL);
+ }
+ EXPORT_SYMBOL_GPL(acpi_match_device);
+ int acpi_match_device_ids(struct acpi_device *device,
+                         const struct acpi_device_id *ids)
+ {
+       return __acpi_match_device(device, ids, NULL) ? 0 : -ENOENT;
+ }
+ EXPORT_SYMBOL(acpi_match_device_ids);
+ bool acpi_driver_match_device(struct device *dev,
+                             const struct device_driver *drv)
+ {
+       if (!drv->acpi_match_table)
+               return acpi_of_match_device(ACPI_COMPANION(dev),
+                                           drv->of_match_table);
+       return !!__acpi_match_device(acpi_companion_match(dev),
+                                    drv->acpi_match_table, drv->of_match_table);
+ }
+ EXPORT_SYMBOL_GPL(acpi_driver_match_device);
+ /* --------------------------------------------------------------------------
+                               ACPI Driver Management
+    -------------------------------------------------------------------------- */
+ /**
+  * acpi_bus_register_driver - register a driver with the ACPI bus
+  * @driver: driver being registered
+  *
+  * Registers a driver with the ACPI bus.  Searches the namespace for all
+  * devices that match the driver's criteria and binds.  Returns zero for
+  * success or a negative error status for failure.
+  */
+ int acpi_bus_register_driver(struct acpi_driver *driver)
+ {
+       int ret;
+       if (acpi_disabled)
+               return -ENODEV;
+       driver->drv.name = driver->name;
+       driver->drv.bus = &acpi_bus_type;
+       driver->drv.owner = driver->owner;
+       ret = driver_register(&driver->drv);
+       return ret;
+ }
+ EXPORT_SYMBOL(acpi_bus_register_driver);
+ /**
+  * acpi_bus_unregister_driver - unregisters a driver with the ACPI bus
+  * @driver: driver to unregister
+  *
+  * Unregisters a driver with the ACPI bus.  Searches the namespace for all
+  * devices that match the driver's criteria and unbinds.
+  */
+ void acpi_bus_unregister_driver(struct acpi_driver *driver)
+ {
+       driver_unregister(&driver->drv);
+ }
+ EXPORT_SYMBOL(acpi_bus_unregister_driver);
+ /* --------------------------------------------------------------------------
+                               ACPI Bus operations
+    -------------------------------------------------------------------------- */
+ 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_dev->flags.match_driver
+               && !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
+ }
+ static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+ {
+       return __acpi_device_uevent_modalias(to_acpi_device(dev), env);
+ }
+ static int acpi_device_probe(struct device *dev)
+ {
+       struct acpi_device *acpi_dev = to_acpi_device(dev);
+       struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
+       int ret;
+       if (acpi_dev->handler && !acpi_is_pnp_device(acpi_dev))
+               return -EINVAL;
+       if (!acpi_drv->ops.add)
+               return -ENOSYS;
+       ret = acpi_drv->ops.add(acpi_dev);
+       if (ret)
+               return ret;
+       acpi_dev->driver = acpi_drv;
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                         "Driver [%s] successfully bound to device [%s]\n",
+                         acpi_drv->name, acpi_dev->pnp.bus_id));
+       if (acpi_drv->ops.notify) {
+               ret = acpi_device_install_notify_handler(acpi_dev);
+               if (ret) {
+                       if (acpi_drv->ops.remove)
+                               acpi_drv->ops.remove(acpi_dev);
+                       acpi_dev->driver = NULL;
+                       acpi_dev->driver_data = NULL;
+                       return ret;
+               }
+       }
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
+                         acpi_drv->name, acpi_dev->pnp.bus_id));
+       get_device(dev);
+       return 0;
+ }
+ static int acpi_device_remove(struct device * dev)
+ {
+       struct acpi_device *acpi_dev = to_acpi_device(dev);
+       struct acpi_driver *acpi_drv = acpi_dev->driver;
+       if (acpi_drv) {
+               if (acpi_drv->ops.notify)
+                       acpi_device_remove_notify_handler(acpi_dev);
+               if (acpi_drv->ops.remove)
+                       acpi_drv->ops.remove(acpi_dev);
+       }
+       acpi_dev->driver = NULL;
+       acpi_dev->driver_data = NULL;
+       put_device(dev);
+       return 0;
+ }
+ struct bus_type acpi_bus_type = {
+       .name           = "acpi",
+       .match          = acpi_bus_match,
+       .probe          = acpi_device_probe,
+       .remove         = acpi_device_remove,
+       .uevent         = acpi_device_uevent,
+ };
  /* --------------------------------------------------------------------------
                               Initialization/Cleanup
     -------------------------------------------------------------------------- */
index f6aefe984941de5a7f8fde3d15f2b38d199cf21e,c529454532dc7fb796aeb102af0e260ee4989b3e..df7f7aff327bf7fc1410661d1e9ed066476236a8
@@@ -97,9 -99,14 +99,16 @@@ void acpi_device_add_finalize(struct ac
  void acpi_free_pnp_ids(struct acpi_device_pnp *pnp);
  bool acpi_device_is_present(struct acpi_device *adev);
  bool acpi_device_is_battery(struct acpi_device *adev);
 +bool acpi_device_is_first_physical_node(struct acpi_device *adev,
 +                                      const struct device *dev);
  
+ /* --------------------------------------------------------------------------
+                      Device Matching and Notification
+    -------------------------------------------------------------------------- */
+ struct acpi_device *acpi_companion_match(const struct device *dev);
+ int __acpi_device_uevent_modalias(struct acpi_device *adev,
+                                 struct kobj_uevent_env *env);
  /* --------------------------------------------------------------------------
                                    Power Resource
     -------------------------------------------------------------------------- */
index 89ff6d2eef8a00bd5352c9f06d1b0e14d1ff5d11,2fe5a37c385c31e921de3a5b3a874e80fa365601..01136b8790381ccff5afc259e47643c338914740
@@@ -115,278 -115,7 +115,6 @@@ int acpi_scan_add_handler_with_hotplug(
        return 0;
  }
  
- /**
-  * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent
-  * @acpi_dev: ACPI device object.
-  * @modalias: Buffer to print into.
-  * @size: Size of the buffer.
-  *
-  * Creates hid/cid(s) string needed for modalias and uevent
-  * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
-  * char *modalias: "acpi:IBM0001:ACPI0001"
-  * Return: 0: no _HID and no _CID
-  *         -EINVAL: output error
-  *         -ENOMEM: output is truncated
- */
- static int create_pnp_modalias(struct acpi_device *acpi_dev, char *modalias,
-                              int size)
- {
-       int len;
-       int count;
-       struct acpi_hardware_id *id;
-       /*
-        * Since we skip ACPI_DT_NAMESPACE_HID from the modalias below, 0 should
-        * be returned if ACPI_DT_NAMESPACE_HID is the only ACPI/PNP ID in the
-        * device's list.
-        */
-       count = 0;
-       list_for_each_entry(id, &acpi_dev->pnp.ids, list)
-               if (strcmp(id->id, ACPI_DT_NAMESPACE_HID))
-                       count++;
-       if (!count)
-               return 0;
-       len = snprintf(modalias, size, "acpi:");
-       if (len <= 0)
-               return len;
-       size -= len;
-       list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
-               if (!strcmp(id->id, ACPI_DT_NAMESPACE_HID))
-                       continue;
-               count = snprintf(&modalias[len], size, "%s:", id->id);
-               if (count < 0)
-                       return -EINVAL;
-               if (count >= size)
-                       return -ENOMEM;
-               len += count;
-               size -= count;
-       }
-       modalias[len] = '\0';
-       return len;
- }
- /**
-  * create_of_modalias - Creates DT compatible string for modalias and uevent
-  * @acpi_dev: ACPI device object.
-  * @modalias: Buffer to print into.
-  * @size: Size of the buffer.
-  *
-  * Expose DT compatible modalias as of:NnameTCcompatible.  This function should
-  * only be called for devices having ACPI_DT_NAMESPACE_HID in their list of
-  * ACPI/PNP IDs.
-  */
- static int create_of_modalias(struct acpi_device *acpi_dev, char *modalias,
-                             int size)
- {
-       struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
-       const union acpi_object *of_compatible, *obj;
-       int len, count;
-       int i, nval;
-       char *c;
-       acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
-       /* DT strings are all in lower case */
-       for (c = buf.pointer; *c != '\0'; c++)
-               *c = tolower(*c);
-       len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
-       ACPI_FREE(buf.pointer);
-       if (len <= 0)
-               return len;
-       of_compatible = acpi_dev->data.of_compatible;
-       if (of_compatible->type == ACPI_TYPE_PACKAGE) {
-               nval = of_compatible->package.count;
-               obj = of_compatible->package.elements;
-       } else { /* Must be ACPI_TYPE_STRING. */
-               nval = 1;
-               obj = of_compatible;
-       }
-       for (i = 0; i < nval; i++, obj++) {
-               count = snprintf(&modalias[len], size, "C%s",
-                                obj->string.pointer);
-               if (count < 0)
-                       return -EINVAL;
-               if (count >= size)
-                       return -ENOMEM;
-               len += count;
-               size -= count;
-       }
-       modalias[len] = '\0';
-       return len;
- }
- /**
-  * acpi_device_is_first_physical_node - Is given dev first physical node
-  * @adev: ACPI companion device
-  * @dev: Physical device to check
-  *
-  * Function checks if given @dev is the first physical devices attached to
-  * the ACPI companion device. This distinction is needed in some cases
-  * where the same companion device is shared between many physical devices.
-  *
-  * Note that the caller have to provide valid @adev pointer.
-  */
- bool acpi_device_is_first_physical_node(struct acpi_device *adev,
-                                       const struct device *dev)
- {
-       bool ret = false;
-       mutex_lock(&adev->physical_node_lock);
-       if (!list_empty(&adev->physical_node_list)) {
-               const struct acpi_device_physical_node *node;
-               node = list_first_entry(&adev->physical_node_list,
-                                       struct acpi_device_physical_node, node);
-               ret = node->dev == dev;
-       }
-       mutex_unlock(&adev->physical_node_lock);
-       return ret;
- }
- /*
-  * acpi_companion_match() - Can we match via ACPI companion device
-  * @dev: Device in question
-  *
-  * Check if the given device has an ACPI companion and if that companion has
-  * a valid list of PNP IDs, and if the device is the first (primary) physical
-  * device associated with it.  Return the companion pointer if that's the case
-  * or NULL otherwise.
-  *
-  * If multiple physical devices are attached to a single ACPI companion, we need
-  * to be careful.  The usage scenario for this kind of relationship is that all
-  * of the physical devices in question use resources provided by the ACPI
-  * companion.  A typical case is an MFD device where all the sub-devices share
-  * the parent's ACPI companion.  In such cases we can only allow the primary
-  * (first) physical device to be matched with the help of the companion's PNP
-  * IDs.
-  *
-  * Additional physical devices sharing the ACPI companion can still use
-  * resources available from it but they will be matched normally using functions
-  * provided by their bus types (and analogously for their modalias).
-  */
- static struct acpi_device *acpi_companion_match(const struct device *dev)
- {
-       struct acpi_device *adev;
-       adev = ACPI_COMPANION(dev);
-       if (!adev)
-               return NULL;
-       if (list_empty(&adev->pnp.ids))
-               return NULL;
-       return acpi_device_is_first_physical_node(adev, dev) ? adev : NULL;
- }
- static int __acpi_device_uevent_modalias(struct acpi_device *adev,
-                                        struct kobj_uevent_env *env)
- {
-       int len;
-       if (!adev)
-               return -ENODEV;
-       if (list_empty(&adev->pnp.ids))
-               return 0;
-       if (add_uevent_var(env, "MODALIAS="))
-               return -ENOMEM;
-       len = create_pnp_modalias(adev, &env->buf[env->buflen - 1],
-                                 sizeof(env->buf) - env->buflen);
-       if (len < 0)
-               return len;
-       env->buflen += len;
-       if (!adev->data.of_compatible)
-               return 0;
-       if (len > 0 && add_uevent_var(env, "MODALIAS="))
-               return -ENOMEM;
-       len = create_of_modalias(adev, &env->buf[env->buflen - 1],
-                                sizeof(env->buf) - env->buflen);
-       if (len < 0)
-               return len;
-       env->buflen += len;
-       return 0;
- }
- /*
-  * Creates uevent modalias field for ACPI enumerated devices.
-  * Because the other buses does not support ACPI HIDs & CIDs.
-  * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get:
-  * "acpi:IBM0001:ACPI0001"
-  */
- int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
- {
-       return __acpi_device_uevent_modalias(acpi_companion_match(dev), env);
- }
- EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias);
- static int __acpi_device_modalias(struct acpi_device *adev, char *buf, int size)
- {
-       int len, count;
-       if (!adev)
-               return -ENODEV;
-       if (list_empty(&adev->pnp.ids))
-               return 0;
-       len = create_pnp_modalias(adev, buf, size - 1);
-       if (len < 0) {
-               return len;
-       } else if (len > 0) {
-               buf[len++] = '\n';
-               size -= len;
-       }
-       if (!adev->data.of_compatible)
-               return len;
-       count = create_of_modalias(adev, buf + len, size - 1);
-       if (count < 0) {
-               return count;
-       } else if (count > 0) {
-               len += count;
-               buf[len++] = '\n';
-       }
-       return len;
- }
- /*
-  * Creates modalias sysfs attribute for ACPI enumerated devices.
-  * Because the other buses does not support ACPI HIDs & CIDs.
-  * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get:
-  * "acpi:IBM0001:ACPI0001"
-  */
- int acpi_device_modalias(struct device *dev, char *buf, int size)
- {
-       return __acpi_device_modalias(acpi_companion_match(dev), buf, size);
- }
- EXPORT_SYMBOL_GPL(acpi_device_modalias);
- static ssize_t
- acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {
-       return __acpi_device_modalias(to_acpi_device(dev), buf, 1024);
- }
- static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
--
  bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent)
  {
        struct acpi_device_physical_node *pn;