diff options
| -rw-r--r-- | drivers/pnp/core.c | 53 |
1 files changed, 40 insertions, 13 deletions
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index ef2f59c4e57c..b54620e53830 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c | |||
| @@ -42,6 +42,13 @@ void *pnp_alloc(long size) | |||
| 42 | return result; | 42 | return result; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | static 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 | |||
| 45 | /** | 52 | /** |
| 46 | * pnp_protocol_register - adds a pnp protocol to the pnp layer | 53 | * pnp_protocol_register - adds a pnp protocol to the pnp layer |
| 47 | * @protocol: pointer to the corresponding pnp_protocol structure | 54 | * @protocol: pointer to the corresponding pnp_protocol structure |
| @@ -50,12 +57,13 @@ void *pnp_alloc(long size) | |||
| 50 | */ | 57 | */ |
| 51 | int pnp_register_protocol(struct pnp_protocol *protocol) | 58 | int pnp_register_protocol(struct pnp_protocol *protocol) |
| 52 | { | 59 | { |
| 53 | int nodenum; | ||
| 54 | struct list_head *pos; | 60 | struct list_head *pos; |
| 61 | int nodenum, ret; | ||
| 55 | 62 | ||
| 56 | INIT_LIST_HEAD(&protocol->devices); | 63 | INIT_LIST_HEAD(&protocol->devices); |
| 57 | INIT_LIST_HEAD(&protocol->cards); | 64 | INIT_LIST_HEAD(&protocol->cards); |
| 58 | nodenum = 0; | 65 | nodenum = 0; |
| 66 | |||
| 59 | mutex_lock(&pnp_lock); | 67 | mutex_lock(&pnp_lock); |
| 60 | 68 | ||
| 61 | /* assign the lowest unused number */ | 69 | /* assign the lowest unused number */ |
| @@ -67,12 +75,18 @@ int pnp_register_protocol(struct pnp_protocol *protocol) | |||
| 67 | } | 75 | } |
| 68 | } | 76 | } |
| 69 | 77 | ||
| 78 | protocol->number = nodenum; | ||
| 79 | dev_set_name(&protocol->dev, "pnp%d", nodenum); | ||
| 80 | |||
| 70 | list_add_tail(&protocol->protocol_list, &pnp_protocols); | 81 | list_add_tail(&protocol->protocol_list, &pnp_protocols); |
| 82 | |||
| 71 | mutex_unlock(&pnp_lock); | 83 | mutex_unlock(&pnp_lock); |
| 72 | 84 | ||
| 73 | protocol->number = nodenum; | 85 | ret = device_register(&protocol->dev); |
| 74 | dev_set_name(&protocol->dev, "pnp%d", nodenum); | 86 | if (ret) |
| 75 | return device_register(&protocol->dev); | 87 | pnp_remove_protocol(protocol); |
| 88 | |||
| 89 | return ret; | ||
| 76 | } | 90 | } |
| 77 | 91 | ||
| 78 | /** | 92 | /** |
| @@ -81,9 +95,7 @@ int pnp_register_protocol(struct pnp_protocol *protocol) | |||
| 81 | */ | 95 | */ |
| 82 | void pnp_unregister_protocol(struct pnp_protocol *protocol) | 96 | void pnp_unregister_protocol(struct pnp_protocol *protocol) |
| 83 | { | 97 | { |
| 84 | mutex_lock(&pnp_lock); | 98 | pnp_remove_protocol(protocol); |
| 85 | list_del(&protocol->protocol_list); | ||
| 86 | mutex_unlock(&pnp_lock); | ||
| 87 | device_unregister(&protocol->dev); | 99 | device_unregister(&protocol->dev); |
| 88 | } | 100 | } |
| 89 | 101 | ||
| @@ -158,18 +170,36 @@ struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, | |||
| 158 | return dev; | 170 | return dev; |
| 159 | } | 171 | } |
| 160 | 172 | ||
| 173 | static 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 | |||
| 161 | int __pnp_add_device(struct pnp_dev *dev) | 181 | int __pnp_add_device(struct pnp_dev *dev) |
| 162 | { | 182 | { |
| 183 | int ret; | ||
| 184 | |||
| 163 | pnp_fixup_device(dev); | 185 | pnp_fixup_device(dev); |
| 164 | dev->status = PNP_READY; | 186 | dev->status = PNP_READY; |
| 187 | |||
| 165 | mutex_lock(&pnp_lock); | 188 | mutex_lock(&pnp_lock); |
| 189 | |||
| 166 | list_add_tail(&dev->global_list, &pnp_global); | 190 | list_add_tail(&dev->global_list, &pnp_global); |
| 167 | list_add_tail(&dev->protocol_list, &dev->protocol->devices); | 191 | list_add_tail(&dev->protocol_list, &dev->protocol->devices); |
| 192 | |||
| 168 | mutex_unlock(&pnp_lock); | 193 | mutex_unlock(&pnp_lock); |
| 169 | if (dev->protocol->can_wakeup) | 194 | |
| 195 | ret = device_register(&dev->dev); | ||
| 196 | if (ret) | ||
| 197 | pnp_delist_device(dev); | ||
| 198 | else if (dev->protocol->can_wakeup) | ||
| 170 | device_set_wakeup_capable(&dev->dev, | 199 | device_set_wakeup_capable(&dev->dev, |
| 171 | dev->protocol->can_wakeup(dev)); | 200 | dev->protocol->can_wakeup(dev)); |
| 172 | return device_register(&dev->dev); | 201 | |
| 202 | return ret; | ||
| 173 | } | 203 | } |
| 174 | 204 | ||
| 175 | /* | 205 | /* |
| @@ -204,10 +234,7 @@ int pnp_add_device(struct pnp_dev *dev) | |||
| 204 | 234 | ||
| 205 | void __pnp_remove_device(struct pnp_dev *dev) | 235 | void __pnp_remove_device(struct pnp_dev *dev) |
| 206 | { | 236 | { |
| 207 | mutex_lock(&pnp_lock); | 237 | pnp_delist_device(dev); |
| 208 | list_del(&dev->global_list); | ||
| 209 | list_del(&dev->protocol_list); | ||
| 210 | mutex_unlock(&pnp_lock); | ||
| 211 | device_unregister(&dev->dev); | 238 | device_unregister(&dev->dev); |
| 212 | } | 239 | } |
| 213 | 240 | ||
