diff options
Diffstat (limited to 'drivers/pnp/core.c')
| -rw-r--r-- | drivers/pnp/core.c | 92 |
1 files changed, 46 insertions, 46 deletions
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index cb6ce42f8e77..ac48db6dcfe3 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * core.c - contains all core device and protocol registration functions * @@ -9,6 +10,7 @@ #include <linux/list.h> #include <linux/device.h> #include <linux/module.h> +#include <linux/mutex.h> #include <linux/init.h> #include <linux/string.h> #include <linux/slab.h> @@ -19,7 +21,7 @@ static LIST_HEAD(pnp_protocols); LIST_HEAD(pnp_global); -DEFINE_SPINLOCK(pnp_lock); +DEFINE_MUTEX(pnp_lock); /* * ACPI or PNPBIOS should tell us about all platform devices, so we can @@ -29,33 +31,29 @@ DEFINE_SPINLOCK(pnp_lock); int pnp_platform_devices; EXPORT_SYMBOL(pnp_platform_devices); -void *pnp_alloc(long size) +static void pnp_remove_protocol(struct pnp_protocol *protocol) { - void *result; - - result = kzalloc(size, GFP_KERNEL); - if (!result) { - printk(KERN_ERR "pnp: Out of Memory\n"); - return NULL; - } - return result; + mutex_lock(&pnp_lock); + list_del(&protocol->protocol_list); + mutex_unlock(&pnp_lock); } /** - * pnp_protocol_register - adds a pnp protocol to the pnp layer + * pnp_register_protocol - adds a pnp protocol to the pnp layer * @protocol: pointer to the corresponding pnp_protocol structure * * Ex protocols: ISAPNP, PNPBIOS, etc */ int pnp_register_protocol(struct pnp_protocol *protocol) { - int nodenum; struct list_head *pos; + int nodenum, ret; INIT_LIST_HEAD(&protocol->devices); INIT_LIST_HEAD(&protocol->cards); nodenum = 0; - spin_lock(&pnp_lock); + + mutex_lock(&pnp_lock); /* assign the lowest unused number */ list_for_each(pos, &pnp_protocols) { @@ -66,24 +64,18 @@ int pnp_register_protocol(struct pnp_protocol *protocol) } } - list_add_tail(&protocol->protocol_list, &pnp_protocols); - spin_unlock(&pnp_lock); - protocol->number = nodenum; dev_set_name(&protocol->dev, "pnp%d", nodenum); - return device_register(&protocol->dev); -} -/** - * pnp_protocol_unregister - removes a pnp protocol from the pnp layer - * @protocol: pointer to the corresponding pnp_protocol structure - */ -void pnp_unregister_protocol(struct pnp_protocol *protocol) -{ - spin_lock(&pnp_lock); - list_del(&protocol->protocol_list); - spin_unlock(&pnp_lock); - device_unregister(&protocol->dev); + list_add_tail(&protocol->protocol_list, &pnp_protocols); + + mutex_unlock(&pnp_lock); + + ret = device_register(&protocol->dev); + if (ret) + pnp_remove_protocol(protocol); + + return ret; } static void pnp_free_ids(struct pnp_dev *dev) @@ -146,29 +138,47 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, dev->dev.coherent_dma_mask = dev->dma_mask; dev->dev.release = &pnp_release_device; - dev_set_name(&dev->dev, "%02x:%02x", dev->protocol->number, dev->number); - dev_id = pnp_add_id(dev, pnpid); if (!dev_id) { kfree(dev); return NULL; } + dev_set_name(&dev->dev, "%02x:%02x", dev->protocol->number, dev->number); + return dev; } +static void pnp_delist_device(struct pnp_dev *dev) +{ + mutex_lock(&pnp_lock); + list_del(&dev->global_list); + list_del(&dev->protocol_list); + mutex_unlock(&pnp_lock); +} + int __pnp_add_device(struct pnp_dev *dev) { + int ret; + pnp_fixup_device(dev); dev->status = PNP_READY; - spin_lock(&pnp_lock); + + mutex_lock(&pnp_lock); + list_add_tail(&dev->global_list, &pnp_global); list_add_tail(&dev->protocol_list, &dev->protocol->devices); - spin_unlock(&pnp_lock); - if (dev->protocol->can_wakeup) + + mutex_unlock(&pnp_lock); + + ret = device_register(&dev->dev); + if (ret) + pnp_delist_device(dev); + else if (dev->protocol->can_wakeup) device_set_wakeup_capable(&dev->dev, dev->protocol->can_wakeup(dev)); - return device_register(&dev->dev); + + return ret; } /* @@ -195,21 +205,11 @@ int pnp_add_device(struct pnp_dev *dev) for (id = dev->id; id; id = id->next) len += scnprintf(buf + len, sizeof(buf) - len, " %s", id->id); - dev_printk(KERN_DEBUG, &dev->dev, "%s device, IDs%s (%s)\n", - dev->protocol->name, buf, - dev->active ? "active" : "disabled"); + dev_dbg(&dev->dev, "%s device, IDs%s (%s)\n", dev->protocol->name, buf, + dev->active ? "active" : "disabled"); return 0; } -void __pnp_remove_device(struct pnp_dev *dev) -{ - spin_lock(&pnp_lock); - list_del(&dev->global_list); - list_del(&dev->protocol_list); - spin_unlock(&pnp_lock); - device_unregister(&dev->dev); -} - static int __init pnp_init(void) { return bus_register(&pnp_bus_type); |
