Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Link physical devices with ACPI devices support
0004  *
0005  * Copyright (c) 2005 David Shaohua Li <shaohua.li@intel.com>
0006  * Copyright (c) 2005 Intel Corp.
0007  */
0008 
0009 #define pr_fmt(fmt) "ACPI: " fmt
0010 
0011 #include <linux/acpi_iort.h>
0012 #include <linux/export.h>
0013 #include <linux/init.h>
0014 #include <linux/list.h>
0015 #include <linux/device.h>
0016 #include <linux/slab.h>
0017 #include <linux/rwsem.h>
0018 #include <linux/acpi.h>
0019 #include <linux/dma-mapping.h>
0020 #include <linux/pci.h>
0021 #include <linux/pci-acpi.h>
0022 #include <linux/platform_device.h>
0023 
0024 #include "internal.h"
0025 
0026 static LIST_HEAD(bus_type_list);
0027 static DECLARE_RWSEM(bus_type_sem);
0028 
0029 #define PHYSICAL_NODE_STRING "physical_node"
0030 #define PHYSICAL_NODE_NAME_SIZE (sizeof(PHYSICAL_NODE_STRING) + 10)
0031 
0032 int register_acpi_bus_type(struct acpi_bus_type *type)
0033 {
0034     if (acpi_disabled)
0035         return -ENODEV;
0036     if (type && type->match && type->find_companion) {
0037         down_write(&bus_type_sem);
0038         list_add_tail(&type->list, &bus_type_list);
0039         up_write(&bus_type_sem);
0040         pr_info("bus type %s registered\n", type->name);
0041         return 0;
0042     }
0043     return -ENODEV;
0044 }
0045 EXPORT_SYMBOL_GPL(register_acpi_bus_type);
0046 
0047 int unregister_acpi_bus_type(struct acpi_bus_type *type)
0048 {
0049     if (acpi_disabled)
0050         return 0;
0051     if (type) {
0052         down_write(&bus_type_sem);
0053         list_del_init(&type->list);
0054         up_write(&bus_type_sem);
0055         pr_info("bus type %s unregistered\n", type->name);
0056         return 0;
0057     }
0058     return -ENODEV;
0059 }
0060 EXPORT_SYMBOL_GPL(unregister_acpi_bus_type);
0061 
0062 static struct acpi_bus_type *acpi_get_bus_type(struct device *dev)
0063 {
0064     struct acpi_bus_type *tmp, *ret = NULL;
0065 
0066     down_read(&bus_type_sem);
0067     list_for_each_entry(tmp, &bus_type_list, list) {
0068         if (tmp->match(dev)) {
0069             ret = tmp;
0070             break;
0071         }
0072     }
0073     up_read(&bus_type_sem);
0074     return ret;
0075 }
0076 
0077 #define FIND_CHILD_MIN_SCORE    1
0078 #define FIND_CHILD_MAX_SCORE    2
0079 
0080 static int match_any(struct acpi_device *adev, void *not_used)
0081 {
0082     return 1;
0083 }
0084 
0085 static bool acpi_dev_has_children(struct acpi_device *adev)
0086 {
0087     return acpi_dev_for_each_child(adev, match_any, NULL) > 0;
0088 }
0089 
0090 static int find_child_checks(struct acpi_device *adev, bool check_children)
0091 {
0092     unsigned long long sta;
0093     acpi_status status;
0094 
0095     if (check_children && !acpi_dev_has_children(adev))
0096         return -ENODEV;
0097 
0098     status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta);
0099     if (status == AE_NOT_FOUND)
0100         return FIND_CHILD_MIN_SCORE;
0101 
0102     if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_ENABLED))
0103         return -ENODEV;
0104 
0105     /*
0106      * If the device has a _HID returning a valid ACPI/PNP device ID, it is
0107      * better to make it look less attractive here, so that the other device
0108      * with the same _ADR value (that may not have a valid device ID) can be
0109      * matched going forward.  [This means a second spec violation in a row,
0110      * so whatever we do here is best effort anyway.]
0111      */
0112     if (adev->pnp.type.platform_id)
0113         return FIND_CHILD_MIN_SCORE;
0114 
0115     return FIND_CHILD_MAX_SCORE;
0116 }
0117 
0118 struct find_child_walk_data {
0119     struct acpi_device *adev;
0120     u64 address;
0121     int score;
0122     bool check_sta;
0123     bool check_children;
0124 };
0125 
0126 static int check_one_child(struct acpi_device *adev, void *data)
0127 {
0128     struct find_child_walk_data *wd = data;
0129     int score;
0130 
0131     if (!adev->pnp.type.bus_address || acpi_device_adr(adev) != wd->address)
0132         return 0;
0133 
0134     if (!wd->adev) {
0135         /*
0136          * This is the first matching object, so save it.  If it is not
0137          * necessary to look for any other matching objects, stop the
0138          * search.
0139          */
0140         wd->adev = adev;
0141         return !(wd->check_sta || wd->check_children);
0142     }
0143 
0144     /*
0145      * There is more than one matching device object with the same _ADR
0146      * value.  That really is unexpected, so we are kind of beyond the scope
0147      * of the spec here.  We have to choose which one to return, though.
0148      *
0149      * First, get the score for the previously found object and terminate
0150      * the walk if it is maximum.
0151     */
0152     if (!wd->score) {
0153         score = find_child_checks(wd->adev, wd->check_children);
0154         if (score == FIND_CHILD_MAX_SCORE)
0155             return 1;
0156 
0157         wd->score = score;
0158     }
0159     /*
0160      * Second, if the object that has just been found has a better score,
0161      * replace the previously found one with it and terminate the walk if
0162      * the new score is maximum.
0163      */
0164     score = find_child_checks(adev, wd->check_children);
0165     if (score > wd->score) {
0166         wd->adev = adev;
0167         if (score == FIND_CHILD_MAX_SCORE)
0168             return 1;
0169 
0170         wd->score = score;
0171     }
0172 
0173     /* Continue, because there may be better matches. */
0174     return 0;
0175 }
0176 
0177 static struct acpi_device *acpi_find_child(struct acpi_device *parent,
0178                        u64 address, bool check_children,
0179                        bool check_sta)
0180 {
0181     struct find_child_walk_data wd = {
0182         .address = address,
0183         .check_children = check_children,
0184         .check_sta = check_sta,
0185         .adev = NULL,
0186         .score = 0,
0187     };
0188 
0189     if (parent)
0190         acpi_dev_for_each_child(parent, check_one_child, &wd);
0191 
0192     return wd.adev;
0193 }
0194 
0195 struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
0196                        u64 address, bool check_children)
0197 {
0198     return acpi_find_child(parent, address, check_children, true);
0199 }
0200 EXPORT_SYMBOL_GPL(acpi_find_child_device);
0201 
0202 struct acpi_device *acpi_find_child_by_adr(struct acpi_device *adev,
0203                        acpi_bus_address adr)
0204 {
0205     return acpi_find_child(adev, adr, false, false);
0206 }
0207 EXPORT_SYMBOL_GPL(acpi_find_child_by_adr);
0208 
0209 static void acpi_physnode_link_name(char *buf, unsigned int node_id)
0210 {
0211     if (node_id > 0)
0212         snprintf(buf, PHYSICAL_NODE_NAME_SIZE,
0213              PHYSICAL_NODE_STRING "%u", node_id);
0214     else
0215         strcpy(buf, PHYSICAL_NODE_STRING);
0216 }
0217 
0218 int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
0219 {
0220     struct acpi_device_physical_node *physical_node, *pn;
0221     char physical_node_name[PHYSICAL_NODE_NAME_SIZE];
0222     struct list_head *physnode_list;
0223     unsigned int node_id;
0224     int retval = -EINVAL;
0225 
0226     if (has_acpi_companion(dev)) {
0227         if (acpi_dev) {
0228             dev_warn(dev, "ACPI companion already set\n");
0229             return -EINVAL;
0230         } else {
0231             acpi_dev = ACPI_COMPANION(dev);
0232         }
0233     }
0234     if (!acpi_dev)
0235         return -EINVAL;
0236 
0237     acpi_dev_get(acpi_dev);
0238     get_device(dev);
0239     physical_node = kzalloc(sizeof(*physical_node), GFP_KERNEL);
0240     if (!physical_node) {
0241         retval = -ENOMEM;
0242         goto err;
0243     }
0244 
0245     mutex_lock(&acpi_dev->physical_node_lock);
0246 
0247     /*
0248      * Keep the list sorted by node_id so that the IDs of removed nodes can
0249      * be recycled easily.
0250      */
0251     physnode_list = &acpi_dev->physical_node_list;
0252     node_id = 0;
0253     list_for_each_entry(pn, &acpi_dev->physical_node_list, node) {
0254         /* Sanity check. */
0255         if (pn->dev == dev) {
0256             mutex_unlock(&acpi_dev->physical_node_lock);
0257 
0258             dev_warn(dev, "Already associated with ACPI node\n");
0259             kfree(physical_node);
0260             if (ACPI_COMPANION(dev) != acpi_dev)
0261                 goto err;
0262 
0263             put_device(dev);
0264             acpi_dev_put(acpi_dev);
0265             return 0;
0266         }
0267         if (pn->node_id == node_id) {
0268             physnode_list = &pn->node;
0269             node_id++;
0270         }
0271     }
0272 
0273     physical_node->node_id = node_id;
0274     physical_node->dev = dev;
0275     list_add(&physical_node->node, physnode_list);
0276     acpi_dev->physical_node_count++;
0277 
0278     if (!has_acpi_companion(dev))
0279         ACPI_COMPANION_SET(dev, acpi_dev);
0280 
0281     acpi_physnode_link_name(physical_node_name, node_id);
0282     retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
0283                    physical_node_name);
0284     if (retval)
0285         dev_err(&acpi_dev->dev, "Failed to create link %s (%d)\n",
0286             physical_node_name, retval);
0287 
0288     retval = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
0289                    "firmware_node");
0290     if (retval)
0291         dev_err(dev, "Failed to create link firmware_node (%d)\n",
0292             retval);
0293 
0294     mutex_unlock(&acpi_dev->physical_node_lock);
0295 
0296     if (acpi_dev->wakeup.flags.valid)
0297         device_set_wakeup_capable(dev, true);
0298 
0299     return 0;
0300 
0301  err:
0302     ACPI_COMPANION_SET(dev, NULL);
0303     put_device(dev);
0304     acpi_dev_put(acpi_dev);
0305     return retval;
0306 }
0307 EXPORT_SYMBOL_GPL(acpi_bind_one);
0308 
0309 int acpi_unbind_one(struct device *dev)
0310 {
0311     struct acpi_device *acpi_dev = ACPI_COMPANION(dev);
0312     struct acpi_device_physical_node *entry;
0313 
0314     if (!acpi_dev)
0315         return 0;
0316 
0317     mutex_lock(&acpi_dev->physical_node_lock);
0318 
0319     list_for_each_entry(entry, &acpi_dev->physical_node_list, node)
0320         if (entry->dev == dev) {
0321             char physnode_name[PHYSICAL_NODE_NAME_SIZE];
0322 
0323             list_del(&entry->node);
0324             acpi_dev->physical_node_count--;
0325 
0326             acpi_physnode_link_name(physnode_name, entry->node_id);
0327             sysfs_remove_link(&acpi_dev->dev.kobj, physnode_name);
0328             sysfs_remove_link(&dev->kobj, "firmware_node");
0329             ACPI_COMPANION_SET(dev, NULL);
0330             /* Drop references taken by acpi_bind_one(). */
0331             put_device(dev);
0332             acpi_dev_put(acpi_dev);
0333             kfree(entry);
0334             break;
0335         }
0336 
0337     mutex_unlock(&acpi_dev->physical_node_lock);
0338     return 0;
0339 }
0340 EXPORT_SYMBOL_GPL(acpi_unbind_one);
0341 
0342 void acpi_device_notify(struct device *dev)
0343 {
0344     struct acpi_device *adev;
0345     int ret;
0346 
0347     ret = acpi_bind_one(dev, NULL);
0348     if (ret) {
0349         struct acpi_bus_type *type = acpi_get_bus_type(dev);
0350 
0351         if (!type)
0352             goto err;
0353 
0354         adev = type->find_companion(dev);
0355         if (!adev) {
0356             dev_dbg(dev, "ACPI companion not found\n");
0357             goto err;
0358         }
0359         ret = acpi_bind_one(dev, adev);
0360         if (ret)
0361             goto err;
0362 
0363         if (type->setup) {
0364             type->setup(dev);
0365             goto done;
0366         }
0367     } else {
0368         adev = ACPI_COMPANION(dev);
0369 
0370         if (dev_is_pci(dev)) {
0371             pci_acpi_setup(dev, adev);
0372             goto done;
0373         } else if (dev_is_platform(dev)) {
0374             acpi_configure_pmsi_domain(dev);
0375         }
0376     }
0377 
0378     if (adev->handler && adev->handler->bind)
0379         adev->handler->bind(dev);
0380 
0381 done:
0382     acpi_handle_debug(ACPI_HANDLE(dev), "Bound to device %s\n",
0383               dev_name(dev));
0384 
0385     return;
0386 
0387 err:
0388     dev_dbg(dev, "No ACPI support\n");
0389 }
0390 
0391 void acpi_device_notify_remove(struct device *dev)
0392 {
0393     struct acpi_device *adev = ACPI_COMPANION(dev);
0394 
0395     if (!adev)
0396         return;
0397 
0398     if (dev_is_pci(dev))
0399         pci_acpi_cleanup(dev, adev);
0400     else if (adev->handler && adev->handler->unbind)
0401         adev->handler->unbind(dev);
0402 
0403     acpi_unbind_one(dev);
0404 }