linux/drivers/pnp/core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * core.c - contains all core device and protocol registration functions
   4 *
   5 * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
   6 */
   7
   8#include <linux/pnp.h>
   9#include <linux/types.h>
  10#include <linux/list.h>
  11#include <linux/device.h>
  12#include <linux/module.h>
  13#include <linux/mutex.h>
  14#include <linux/init.h>
  15#include <linux/string.h>
  16#include <linux/slab.h>
  17#include <linux/errno.h>
  18#include <linux/dma-mapping.h>
  19
  20#include "base.h"
  21
  22static LIST_HEAD(pnp_protocols);
  23LIST_HEAD(pnp_global);
  24DEFINE_MUTEX(pnp_lock);
  25
  26/*
  27 * ACPI or PNPBIOS should tell us about all platform devices, so we can
  28 * skip some blind probes.  ISAPNP typically enumerates only plug-in ISA
  29 * devices, not built-in things like COM ports.
  30 */
  31int pnp_platform_devices;
  32EXPORT_SYMBOL(pnp_platform_devices);
  33
  34static void pnp_remove_protocol(struct pnp_protocol *protocol)
  35{
  36        mutex_lock(&pnp_lock);
  37        list_del(&protocol->protocol_list);
  38        mutex_unlock(&pnp_lock);
  39}
  40
  41/**
  42 * pnp_register_protocol - adds a pnp protocol to the pnp layer
  43 * @protocol: pointer to the corresponding pnp_protocol structure
  44 *
  45 *  Ex protocols: ISAPNP, PNPBIOS, etc
  46 */
  47int pnp_register_protocol(struct pnp_protocol *protocol)
  48{
  49        struct list_head *pos;
  50        int nodenum, ret;
  51
  52        INIT_LIST_HEAD(&protocol->devices);
  53        INIT_LIST_HEAD(&protocol->cards);
  54        nodenum = 0;
  55
  56        mutex_lock(&pnp_lock);
  57
  58        /* assign the lowest unused number */
  59        list_for_each(pos, &pnp_protocols) {
  60                struct pnp_protocol *cur = to_pnp_protocol(pos);
  61                if (cur->number == nodenum) {
  62                        pos = &pnp_protocols;
  63                        nodenum++;
  64                }
  65        }
  66
  67        protocol->number = nodenum;
  68        dev_set_name(&protocol->dev, "pnp%d", nodenum);
  69
  70        list_add_tail(&protocol->protocol_list, &pnp_protocols);
  71
  72        mutex_unlock(&pnp_lock);
  73
  74        ret = device_register(&protocol->dev);
  75        if (ret)
  76                pnp_remove_protocol(protocol);
  77
  78        return ret;
  79}
  80
  81/**
  82 * pnp_unregister_protocol - removes a pnp protocol from the pnp layer
  83 * @protocol: pointer to the corresponding pnp_protocol structure
  84 */
  85void pnp_unregister_protocol(struct pnp_protocol *protocol)
  86{
  87        pnp_remove_protocol(protocol);
  88        device_unregister(&protocol->dev);
  89}
  90
  91static void pnp_free_ids(struct pnp_dev *dev)
  92{
  93        struct pnp_id *id;
  94        struct pnp_id *next;
  95
  96        id = dev->id;
  97        while (id) {
  98                next = id->next;
  99                kfree(id);
 100                id = next;
 101        }
 102}
 103
 104void pnp_free_resource(struct pnp_resource *pnp_res)
 105{
 106        list_del(&pnp_res->list);
 107        kfree(pnp_res);
 108}
 109
 110void pnp_free_resources(struct pnp_dev *dev)
 111{
 112        struct pnp_resource *pnp_res, *tmp;
 113
 114        list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) {
 115                pnp_free_resource(pnp_res);
 116        }
 117}
 118
 119static void pnp_release_device(struct device *dmdev)
 120{
 121        struct pnp_dev *dev = to_pnp_dev(dmdev);
 122
 123        pnp_free_ids(dev);
 124        pnp_free_resources(dev);
 125        pnp_free_options(dev);
 126        kfree(dev);
 127}
 128
 129struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id,
 130                              const char *pnpid)
 131{
 132        struct pnp_dev *dev;
 133        struct pnp_id *dev_id;
 134
 135        dev = kzalloc(sizeof(struct pnp_dev), GFP_KERNEL);
 136        if (!dev)
 137                return NULL;
 138
 139        INIT_LIST_HEAD(&dev->resources);
 140        INIT_LIST_HEAD(&dev->options);
 141        dev->protocol = protocol;
 142        dev->number = id;
 143        dev->dma_mask = DMA_BIT_MASK(24);
 144
 145        dev->dev.parent = &dev->protocol->dev;
 146        dev->dev.bus = &pnp_bus_type;
 147        dev->dev.dma_mask = &dev->dma_mask;
 148        dev->dev.coherent_dma_mask = dev->dma_mask;
 149        dev->dev.release = &pnp_release_device;
 150
 151        dev_set_name(&dev->dev, "%02x:%02x", dev->protocol->number, dev->number);
 152
 153        dev_id = pnp_add_id(dev, pnpid);
 154        if (!dev_id) {
 155                kfree(dev);
 156                return NULL;
 157        }
 158
 159        return dev;
 160}
 161
 162static void pnp_delist_device(struct pnp_dev *dev)
 163{
 164        mutex_lock(&pnp_lock);
 165        list_del(&dev->global_list);
 166        list_del(&dev->protocol_list);
 167        mutex_unlock(&pnp_lock);
 168}
 169
 170int __pnp_add_device(struct pnp_dev *dev)
 171{
 172        int ret;
 173
 174        pnp_fixup_device(dev);
 175        dev->status = PNP_READY;
 176
 177        mutex_lock(&pnp_lock);
 178
 179        list_add_tail(&dev->global_list, &pnp_global);
 180        list_add_tail(&dev->protocol_list, &dev->protocol->devices);
 181
 182        mutex_unlock(&pnp_lock);
 183
 184        ret = device_register(&dev->dev);
 185        if (ret)
 186                pnp_delist_device(dev);
 187        else if (dev->protocol->can_wakeup)
 188                device_set_wakeup_capable(&dev->dev,
 189                                dev->protocol->can_wakeup(dev));
 190
 191        return ret;
 192}
 193
 194/*
 195 * pnp_add_device - adds a pnp device to the pnp layer
 196 * @dev: pointer to dev to add
 197 *
 198 *  adds to driver model, name database, fixups, interface, etc.
 199 */
 200int pnp_add_device(struct pnp_dev *dev)
 201{
 202        int ret;
 203        char buf[128];
 204        int len = 0;
 205        struct pnp_id *id;
 206
 207        if (dev->card)
 208                return -EINVAL;
 209
 210        ret = __pnp_add_device(dev);
 211        if (ret)
 212                return ret;
 213
 214        buf[0] = '\0';
 215        for (id = dev->id; id; id = id->next)
 216                len += scnprintf(buf + len, sizeof(buf) - len, " %s", id->id);
 217
 218        dev_dbg(&dev->dev, "%s device, IDs%s (%s)\n", dev->protocol->name, buf,
 219                dev->active ? "active" : "disabled");
 220        return 0;
 221}
 222
 223void __pnp_remove_device(struct pnp_dev *dev)
 224{
 225        pnp_delist_device(dev);
 226        device_unregister(&dev->dev);
 227}
 228
 229static int __init pnp_init(void)
 230{
 231        return bus_register(&pnp_bus_type);
 232}
 233
 234subsys_initcall(pnp_init);
 235
 236int pnp_debug;
 237
 238#if defined(CONFIG_PNP_DEBUG_MESSAGES)
 239module_param_named(debug, pnp_debug, int, 0644);
 240#endif
 241