diff options
Diffstat (limited to 'arch/powerpc/sysdev/pmi.c')
-rw-r--r-- | arch/powerpc/sysdev/pmi.c | 51 |
1 files changed, 22 insertions, 29 deletions
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c index 85a7c99c1003..2f91b55b7754 100644 --- a/arch/powerpc/sysdev/pmi.c +++ b/arch/powerpc/sysdev/pmi.c | |||
@@ -48,15 +48,13 @@ struct pmi_data { | |||
48 | struct work_struct work; | 48 | struct work_struct work; |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static struct pmi_data *data; | ||
51 | 52 | ||
52 | static int pmi_irq_handler(int irq, void *dev_id) | 53 | static int pmi_irq_handler(int irq, void *dev_id) |
53 | { | 54 | { |
54 | struct pmi_data *data; | ||
55 | u8 type; | 55 | u8 type; |
56 | int rc; | 56 | int rc; |
57 | 57 | ||
58 | data = dev_id; | ||
59 | |||
60 | spin_lock(&data->pmi_spinlock); | 58 | spin_lock(&data->pmi_spinlock); |
61 | 59 | ||
62 | type = ioread8(data->pmi_reg + PMI_READ_TYPE); | 60 | type = ioread8(data->pmi_reg + PMI_READ_TYPE); |
@@ -111,16 +109,13 @@ MODULE_DEVICE_TABLE(of, pmi_match); | |||
111 | 109 | ||
112 | static void pmi_notify_handlers(struct work_struct *work) | 110 | static void pmi_notify_handlers(struct work_struct *work) |
113 | { | 111 | { |
114 | struct pmi_data *data; | ||
115 | struct pmi_handler *handler; | 112 | struct pmi_handler *handler; |
116 | 113 | ||
117 | data = container_of(work, struct pmi_data, work); | ||
118 | |||
119 | spin_lock(&data->handler_spinlock); | 114 | spin_lock(&data->handler_spinlock); |
120 | list_for_each_entry(handler, &data->handler, node) { | 115 | list_for_each_entry(handler, &data->handler, node) { |
121 | pr_debug(KERN_INFO "pmi: notifying handler %p\n", handler); | 116 | pr_debug(KERN_INFO "pmi: notifying handler %p\n", handler); |
122 | if (handler->type == data->msg.type) | 117 | if (handler->type == data->msg.type) |
123 | handler->handle_pmi_message(data->dev, data->msg); | 118 | handler->handle_pmi_message(data->msg); |
124 | } | 119 | } |
125 | spin_unlock(&data->handler_spinlock); | 120 | spin_unlock(&data->handler_spinlock); |
126 | } | 121 | } |
@@ -129,9 +124,14 @@ static int pmi_of_probe(struct of_device *dev, | |||
129 | const struct of_device_id *match) | 124 | const struct of_device_id *match) |
130 | { | 125 | { |
131 | struct device_node *np = dev->node; | 126 | struct device_node *np = dev->node; |
132 | struct pmi_data *data; | ||
133 | int rc; | 127 | int rc; |
134 | 128 | ||
129 | if (data) { | ||
130 | printk(KERN_ERR "pmi: driver has already been initialized.\n"); | ||
131 | rc = -EBUSY; | ||
132 | goto out; | ||
133 | } | ||
134 | |||
135 | data = kzalloc(sizeof(struct pmi_data), GFP_KERNEL); | 135 | data = kzalloc(sizeof(struct pmi_data), GFP_KERNEL); |
136 | if (!data) { | 136 | if (!data) { |
137 | printk(KERN_ERR "pmi: could not allocate memory.\n"); | 137 | printk(KERN_ERR "pmi: could not allocate memory.\n"); |
@@ -154,7 +154,6 @@ static int pmi_of_probe(struct of_device *dev, | |||
154 | 154 | ||
155 | INIT_WORK(&data->work, pmi_notify_handlers); | 155 | INIT_WORK(&data->work, pmi_notify_handlers); |
156 | 156 | ||
157 | dev->dev.driver_data = data; | ||
158 | data->dev = dev; | 157 | data->dev = dev; |
159 | 158 | ||
160 | data->irq = irq_of_parse_and_map(np, 0); | 159 | data->irq = irq_of_parse_and_map(np, 0); |
@@ -164,7 +163,7 @@ static int pmi_of_probe(struct of_device *dev, | |||
164 | goto error_cleanup_iomap; | 163 | goto error_cleanup_iomap; |
165 | } | 164 | } |
166 | 165 | ||
167 | rc = request_irq(data->irq, pmi_irq_handler, 0, "pmi", data); | 166 | rc = request_irq(data->irq, pmi_irq_handler, 0, "pmi", NULL); |
168 | if (rc) { | 167 | if (rc) { |
169 | printk(KERN_ERR "pmi: can't request IRQ %d: returned %d\n", | 168 | printk(KERN_ERR "pmi: can't request IRQ %d: returned %d\n", |
170 | data->irq, rc); | 169 | data->irq, rc); |
@@ -187,12 +186,9 @@ out: | |||
187 | 186 | ||
188 | static int pmi_of_remove(struct of_device *dev) | 187 | static int pmi_of_remove(struct of_device *dev) |
189 | { | 188 | { |
190 | struct pmi_data *data; | ||
191 | struct pmi_handler *handler, *tmp; | 189 | struct pmi_handler *handler, *tmp; |
192 | 190 | ||
193 | data = dev->dev.driver_data; | 191 | free_irq(data->irq, NULL); |
194 | |||
195 | free_irq(data->irq, data); | ||
196 | iounmap(data->pmi_reg); | 192 | iounmap(data->pmi_reg); |
197 | 193 | ||
198 | spin_lock(&data->handler_spinlock); | 194 | spin_lock(&data->handler_spinlock); |
@@ -202,7 +198,8 @@ static int pmi_of_remove(struct of_device *dev) | |||
202 | 198 | ||
203 | spin_unlock(&data->handler_spinlock); | 199 | spin_unlock(&data->handler_spinlock); |
204 | 200 | ||
205 | kfree(dev->dev.driver_data); | 201 | kfree(data); |
202 | data = NULL; | ||
206 | 203 | ||
207 | return 0; | 204 | return 0; |
208 | } | 205 | } |
@@ -226,13 +223,13 @@ static void __exit pmi_module_exit(void) | |||
226 | } | 223 | } |
227 | module_exit(pmi_module_exit); | 224 | module_exit(pmi_module_exit); |
228 | 225 | ||
229 | void pmi_send_message(struct of_device *device, pmi_message_t msg) | 226 | int pmi_send_message(pmi_message_t msg) |
230 | { | 227 | { |
231 | struct pmi_data *data; | ||
232 | unsigned long flags; | 228 | unsigned long flags; |
233 | DECLARE_COMPLETION_ONSTACK(completion); | 229 | DECLARE_COMPLETION_ONSTACK(completion); |
234 | 230 | ||
235 | data = device->dev.driver_data; | 231 | if (!data) |
232 | return -ENODEV; | ||
236 | 233 | ||
237 | mutex_lock(&data->msg_mutex); | 234 | mutex_lock(&data->msg_mutex); |
238 | 235 | ||
@@ -256,30 +253,26 @@ void pmi_send_message(struct of_device *device, pmi_message_t msg) | |||
256 | data->completion = NULL; | 253 | data->completion = NULL; |
257 | 254 | ||
258 | mutex_unlock(&data->msg_mutex); | 255 | mutex_unlock(&data->msg_mutex); |
256 | |||
257 | return 0; | ||
259 | } | 258 | } |
260 | EXPORT_SYMBOL_GPL(pmi_send_message); | 259 | EXPORT_SYMBOL_GPL(pmi_send_message); |
261 | 260 | ||
262 | void pmi_register_handler(struct of_device *device, | 261 | int pmi_register_handler(struct pmi_handler *handler) |
263 | struct pmi_handler *handler) | ||
264 | { | 262 | { |
265 | struct pmi_data *data; | ||
266 | data = device->dev.driver_data; | ||
267 | |||
268 | if (!data) | 263 | if (!data) |
269 | return; | 264 | return -ENODEV; |
270 | 265 | ||
271 | spin_lock(&data->handler_spinlock); | 266 | spin_lock(&data->handler_spinlock); |
272 | list_add_tail(&handler->node, &data->handler); | 267 | list_add_tail(&handler->node, &data->handler); |
273 | spin_unlock(&data->handler_spinlock); | 268 | spin_unlock(&data->handler_spinlock); |
269 | |||
270 | return 0; | ||
274 | } | 271 | } |
275 | EXPORT_SYMBOL_GPL(pmi_register_handler); | 272 | EXPORT_SYMBOL_GPL(pmi_register_handler); |
276 | 273 | ||
277 | void pmi_unregister_handler(struct of_device *device, | 274 | void pmi_unregister_handler(struct pmi_handler *handler) |
278 | struct pmi_handler *handler) | ||
279 | { | 275 | { |
280 | struct pmi_data *data; | ||
281 | data = device->dev.driver_data; | ||
282 | |||
283 | if (!data) | 276 | if (!data) |
284 | return; | 277 | return; |
285 | 278 | ||