aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pnp/core.c')
-rw-r--r--drivers/pnp/core.c64
1 files changed, 46 insertions, 18 deletions
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index cb6ce42f8e77..b54620e53830 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -9,6 +9,7 @@
9#include <linux/list.h> 9#include <linux/list.h>
10#include <linux/device.h> 10#include <linux/device.h>
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/mutex.h>
12#include <linux/init.h> 13#include <linux/init.h>
13#include <linux/string.h> 14#include <linux/string.h>
14#include <linux/slab.h> 15#include <linux/slab.h>
@@ -19,7 +20,7 @@
19 20
20static LIST_HEAD(pnp_protocols); 21static LIST_HEAD(pnp_protocols);
21LIST_HEAD(pnp_global); 22LIST_HEAD(pnp_global);
22DEFINE_SPINLOCK(pnp_lock); 23DEFINE_MUTEX(pnp_lock);
23 24
24/* 25/*
25 * ACPI or PNPBIOS should tell us about all platform devices, so we can 26 * ACPI or PNPBIOS should tell us about all platform devices, so we can
@@ -41,6 +42,13 @@ void *pnp_alloc(long size)
41 return result; 42 return result;
42} 43}
43 44
45static void pnp_remove_protocol(struct pnp_protocol *protocol)
46{
47 mutex_lock(&pnp_lock);
48 list_del(&protocol->protocol_list);
49 mutex_unlock(&pnp_lock);
50}
51
44/** 52/**
45 * pnp_protocol_register - adds a pnp protocol to the pnp layer 53 * pnp_protocol_register - adds a pnp protocol to the pnp layer
46 * @protocol: pointer to the corresponding pnp_protocol structure 54 * @protocol: pointer to the corresponding pnp_protocol structure
@@ -49,13 +57,14 @@ void *pnp_alloc(long size)
49 */ 57 */
50int pnp_register_protocol(struct pnp_protocol *protocol) 58int pnp_register_protocol(struct pnp_protocol *protocol)
51{ 59{
52 int nodenum;
53 struct list_head *pos; 60 struct list_head *pos;
61 int nodenum, ret;
54 62
55 INIT_LIST_HEAD(&protocol->devices); 63 INIT_LIST_HEAD(&protocol->devices);
56 INIT_LIST_HEAD(&protocol->cards); 64 INIT_LIST_HEAD(&protocol->cards);
57 nodenum = 0; 65 nodenum = 0;
58 spin_lock(&pnp_lock); 66
67 mutex_lock(&pnp_lock);
59 68
60 /* assign the lowest unused number */ 69 /* assign the lowest unused number */
61 list_for_each(pos, &pnp_protocols) { 70 list_for_each(pos, &pnp_protocols) {
@@ -66,12 +75,18 @@ int pnp_register_protocol(struct pnp_protocol *protocol)
66 } 75 }
67 } 76 }
68 77
69 list_add_tail(&protocol->protocol_list, &pnp_protocols);
70 spin_unlock(&pnp_lock);
71
72 protocol->number = nodenum; 78 protocol->number = nodenum;
73 dev_set_name(&protocol->dev, "pnp%d", nodenum); 79 dev_set_name(&protocol->dev, "pnp%d", nodenum);
74 return device_register(&protocol->dev); 80
81 list_add_tail(&protocol->protocol_list, &pnp_protocols);
82
83 mutex_unlock(&pnp_lock);
84
85 ret = device_register(&protocol->dev);
86 if (ret)
87 pnp_remove_protocol(protocol);
88
89 return ret;
75} 90}
76 91
77/** 92/**
@@ -80,9 +95,7 @@ int pnp_register_protocol(struct pnp_protocol *protocol)
80 */ 95 */
81void pnp_unregister_protocol(struct pnp_protocol *protocol) 96void pnp_unregister_protocol(struct pnp_protocol *protocol)
82{ 97{
83 spin_lock(&pnp_lock); 98 pnp_remove_protocol(protocol);
84 list_del(&protocol->protocol_list);
85 spin_unlock(&pnp_lock);
86 device_unregister(&protocol->dev); 99 device_unregister(&protocol->dev);
87} 100}
88 101
@@ -157,18 +170,36 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id,
157 return dev; 170 return dev;
158} 171}
159 172
173static void pnp_delist_device(struct pnp_dev *dev)
174{
175 mutex_lock(&pnp_lock);
176 list_del(&dev->global_list);
177 list_del(&dev->protocol_list);
178 mutex_unlock(&pnp_lock);
179}
180
160int __pnp_add_device(struct pnp_dev *dev) 181int __pnp_add_device(struct pnp_dev *dev)
161{ 182{
183 int ret;
184
162 pnp_fixup_device(dev); 185 pnp_fixup_device(dev);
163 dev->status = PNP_READY; 186 dev->status = PNP_READY;
164 spin_lock(&pnp_lock); 187
188 mutex_lock(&pnp_lock);
189
165 list_add_tail(&dev->global_list, &pnp_global); 190 list_add_tail(&dev->global_list, &pnp_global);
166 list_add_tail(&dev->protocol_list, &dev->protocol->devices); 191 list_add_tail(&dev->protocol_list, &dev->protocol->devices);
167 spin_unlock(&pnp_lock); 192
168 if (dev->protocol->can_wakeup) 193 mutex_unlock(&pnp_lock);
194
195 ret = device_register(&dev->dev);
196 if (ret)
197 pnp_delist_device(dev);
198 else if (dev->protocol->can_wakeup)
169 device_set_wakeup_capable(&dev->dev, 199 device_set_wakeup_capable(&dev->dev,
170 dev->protocol->can_wakeup(dev)); 200 dev->protocol->can_wakeup(dev));
171 return device_register(&dev->dev); 201
202 return ret;
172} 203}
173 204
174/* 205/*
@@ -203,10 +234,7 @@ int pnp_add_device(struct pnp_dev *dev)
203 234
204void __pnp_remove_device(struct pnp_dev *dev) 235void __pnp_remove_device(struct pnp_dev *dev)
205{ 236{
206 spin_lock(&pnp_lock); 237 pnp_delist_device(dev);
207 list_del(&dev->global_list);
208 list_del(&dev->protocol_list);
209 spin_unlock(&pnp_lock);
210 device_unregister(&dev->dev); 238 device_unregister(&dev->dev);
211} 239}
212 240