diff options
Diffstat (limited to 'arch/arm/plat-omap/mailbox.c')
-rw-r--r-- | arch/arm/plat-omap/mailbox.c | 284 |
1 files changed, 51 insertions, 233 deletions
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 40424edae939..8e90633e4cb9 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c | |||
@@ -26,55 +26,12 @@ | |||
26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | 28 | ||
29 | #include <mach/mailbox.h> | 29 | #include <plat/mailbox.h> |
30 | |||
31 | static int enable_seq_bit; | ||
32 | module_param(enable_seq_bit, bool, 0); | ||
33 | MODULE_PARM_DESC(enable_seq_bit, "Enable sequence bit checking."); | ||
34 | 30 | ||
35 | static struct omap_mbox *mboxes; | 31 | static struct omap_mbox *mboxes; |
36 | static DEFINE_RWLOCK(mboxes_lock); | 32 | static DEFINE_RWLOCK(mboxes_lock); |
37 | 33 | ||
38 | /* | 34 | static int mbox_configured; |
39 | * Mailbox sequence bit API | ||
40 | */ | ||
41 | |||
42 | /* seq_rcv should be initialized with any value other than | ||
43 | * 0 and 1 << 31, to allow either value for the first | ||
44 | * message. */ | ||
45 | static inline void mbox_seq_init(struct omap_mbox *mbox) | ||
46 | { | ||
47 | if (!enable_seq_bit) | ||
48 | return; | ||
49 | |||
50 | /* any value other than 0 and 1 << 31 */ | ||
51 | mbox->seq_rcv = 0xffffffff; | ||
52 | } | ||
53 | |||
54 | static inline void mbox_seq_toggle(struct omap_mbox *mbox, mbox_msg_t * msg) | ||
55 | { | ||
56 | if (!enable_seq_bit) | ||
57 | return; | ||
58 | |||
59 | /* add seq_snd to msg */ | ||
60 | *msg = (*msg & 0x7fffffff) | mbox->seq_snd; | ||
61 | /* flip seq_snd */ | ||
62 | mbox->seq_snd ^= 1 << 31; | ||
63 | } | ||
64 | |||
65 | static inline int mbox_seq_test(struct omap_mbox *mbox, mbox_msg_t msg) | ||
66 | { | ||
67 | mbox_msg_t seq; | ||
68 | |||
69 | if (!enable_seq_bit) | ||
70 | return 0; | ||
71 | |||
72 | seq = msg & (1 << 31); | ||
73 | if (seq == mbox->seq_rcv) | ||
74 | return -1; | ||
75 | mbox->seq_rcv = seq; | ||
76 | return 0; | ||
77 | } | ||
78 | 35 | ||
79 | /* Mailbox FIFO handle functions */ | 36 | /* Mailbox FIFO handle functions */ |
80 | static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) | 37 | static inline mbox_msg_t mbox_fifo_read(struct omap_mbox *mbox) |
@@ -95,14 +52,6 @@ static inline int mbox_fifo_full(struct omap_mbox *mbox) | |||
95 | } | 52 | } |
96 | 53 | ||
97 | /* Mailbox IRQ handle functions */ | 54 | /* Mailbox IRQ handle functions */ |
98 | static inline void enable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) | ||
99 | { | ||
100 | mbox->ops->enable_irq(mbox, irq); | ||
101 | } | ||
102 | static inline void disable_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) | ||
103 | { | ||
104 | mbox->ops->disable_irq(mbox, irq); | ||
105 | } | ||
106 | static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) | 55 | static inline void ack_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) |
107 | { | 56 | { |
108 | if (mbox->ops->ack_irq) | 57 | if (mbox->ops->ack_irq) |
@@ -113,17 +62,10 @@ static inline int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) | |||
113 | return mbox->ops->is_irq(mbox, irq); | 62 | return mbox->ops->is_irq(mbox, irq); |
114 | } | 63 | } |
115 | 64 | ||
116 | /* Mailbox Sequence Bit function */ | ||
117 | void omap_mbox_init_seq(struct omap_mbox *mbox) | ||
118 | { | ||
119 | mbox_seq_init(mbox); | ||
120 | } | ||
121 | EXPORT_SYMBOL(omap_mbox_init_seq); | ||
122 | |||
123 | /* | 65 | /* |
124 | * message sender | 66 | * message sender |
125 | */ | 67 | */ |
126 | static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg) | 68 | static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) |
127 | { | 69 | { |
128 | int ret = 0, i = 1000; | 70 | int ret = 0, i = 1000; |
129 | 71 | ||
@@ -134,89 +76,49 @@ static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg) | |||
134 | return -1; | 76 | return -1; |
135 | udelay(1); | 77 | udelay(1); |
136 | } | 78 | } |
137 | |||
138 | if (arg && mbox->txq->callback) { | ||
139 | ret = mbox->txq->callback(arg); | ||
140 | if (ret) | ||
141 | goto out; | ||
142 | } | ||
143 | |||
144 | mbox_seq_toggle(mbox, &msg); | ||
145 | mbox_fifo_write(mbox, msg); | 79 | mbox_fifo_write(mbox, msg); |
146 | out: | ||
147 | return ret; | 80 | return ret; |
148 | } | 81 | } |
149 | 82 | ||
150 | struct omap_msg_tx_data { | ||
151 | mbox_msg_t msg; | ||
152 | void *arg; | ||
153 | }; | ||
154 | 83 | ||
155 | static void omap_msg_tx_end_io(struct request *rq, int error) | 84 | int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) |
156 | { | 85 | { |
157 | kfree(rq->special); | ||
158 | __blk_put_request(rq->q, rq); | ||
159 | } | ||
160 | 86 | ||
161 | int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg) | ||
162 | { | ||
163 | struct omap_msg_tx_data *tx_data; | ||
164 | struct request *rq; | 87 | struct request *rq; |
165 | struct request_queue *q = mbox->txq->queue; | 88 | struct request_queue *q = mbox->txq->queue; |
166 | 89 | ||
167 | tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC); | ||
168 | if (unlikely(!tx_data)) | ||
169 | return -ENOMEM; | ||
170 | |||
171 | rq = blk_get_request(q, WRITE, GFP_ATOMIC); | 90 | rq = blk_get_request(q, WRITE, GFP_ATOMIC); |
172 | if (unlikely(!rq)) { | 91 | if (unlikely(!rq)) |
173 | kfree(tx_data); | ||
174 | return -ENOMEM; | 92 | return -ENOMEM; |
175 | } | ||
176 | 93 | ||
177 | tx_data->msg = msg; | 94 | blk_insert_request(q, rq, 0, (void *) msg); |
178 | tx_data->arg = arg; | 95 | tasklet_schedule(&mbox->txq->tasklet); |
179 | rq->end_io = omap_msg_tx_end_io; | ||
180 | blk_insert_request(q, rq, 0, tx_data); | ||
181 | 96 | ||
182 | schedule_work(&mbox->txq->work); | ||
183 | return 0; | 97 | return 0; |
184 | } | 98 | } |
185 | EXPORT_SYMBOL(omap_mbox_msg_send); | 99 | EXPORT_SYMBOL(omap_mbox_msg_send); |
186 | 100 | ||
187 | static void mbox_tx_work(struct work_struct *work) | 101 | static void mbox_tx_tasklet(unsigned long tx_data) |
188 | { | 102 | { |
189 | int ret; | 103 | int ret; |
190 | struct request *rq; | 104 | struct request *rq; |
191 | struct omap_mbox_queue *mq = container_of(work, | 105 | struct omap_mbox *mbox = (struct omap_mbox *)tx_data; |
192 | struct omap_mbox_queue, work); | ||
193 | struct omap_mbox *mbox = mq->queue->queuedata; | ||
194 | struct request_queue *q = mbox->txq->queue; | 106 | struct request_queue *q = mbox->txq->queue; |
195 | 107 | ||
196 | while (1) { | 108 | while (1) { |
197 | struct omap_msg_tx_data *tx_data; | ||
198 | 109 | ||
199 | spin_lock(q->queue_lock); | ||
200 | rq = blk_fetch_request(q); | 110 | rq = blk_fetch_request(q); |
201 | spin_unlock(q->queue_lock); | ||
202 | 111 | ||
203 | if (!rq) | 112 | if (!rq) |
204 | break; | 113 | break; |
205 | 114 | ||
206 | tx_data = rq->special; | 115 | ret = __mbox_msg_send(mbox, (mbox_msg_t)rq->special); |
207 | |||
208 | ret = __mbox_msg_send(mbox, tx_data->msg, tx_data->arg); | ||
209 | if (ret) { | 116 | if (ret) { |
210 | enable_mbox_irq(mbox, IRQ_TX); | 117 | omap_mbox_enable_irq(mbox, IRQ_TX); |
211 | spin_lock(q->queue_lock); | ||
212 | blk_requeue_request(q, rq); | 118 | blk_requeue_request(q, rq); |
213 | spin_unlock(q->queue_lock); | ||
214 | return; | 119 | return; |
215 | } | 120 | } |
216 | 121 | blk_end_request_all(rq, 0); | |
217 | spin_lock(q->queue_lock); | ||
218 | __blk_end_request_all(rq, 0); | ||
219 | spin_unlock(q->queue_lock); | ||
220 | } | 122 | } |
221 | } | 123 | } |
222 | 124 | ||
@@ -233,11 +135,6 @@ static void mbox_rx_work(struct work_struct *work) | |||
233 | mbox_msg_t msg; | 135 | mbox_msg_t msg; |
234 | unsigned long flags; | 136 | unsigned long flags; |
235 | 137 | ||
236 | if (mbox->rxq->callback == NULL) { | ||
237 | sysfs_notify(&mbox->dev->kobj, NULL, "mbox"); | ||
238 | return; | ||
239 | } | ||
240 | |||
241 | while (1) { | 138 | while (1) { |
242 | spin_lock_irqsave(q->queue_lock, flags); | 139 | spin_lock_irqsave(q->queue_lock, flags); |
243 | rq = blk_fetch_request(q); | 140 | rq = blk_fetch_request(q); |
@@ -254,19 +151,19 @@ static void mbox_rx_work(struct work_struct *work) | |||
254 | /* | 151 | /* |
255 | * Mailbox interrupt handler | 152 | * Mailbox interrupt handler |
256 | */ | 153 | */ |
257 | static void mbox_txq_fn(struct request_queue * q) | 154 | static void mbox_txq_fn(struct request_queue *q) |
258 | { | 155 | { |
259 | } | 156 | } |
260 | 157 | ||
261 | static void mbox_rxq_fn(struct request_queue * q) | 158 | static void mbox_rxq_fn(struct request_queue *q) |
262 | { | 159 | { |
263 | } | 160 | } |
264 | 161 | ||
265 | static void __mbox_tx_interrupt(struct omap_mbox *mbox) | 162 | static void __mbox_tx_interrupt(struct omap_mbox *mbox) |
266 | { | 163 | { |
267 | disable_mbox_irq(mbox, IRQ_TX); | 164 | omap_mbox_disable_irq(mbox, IRQ_TX); |
268 | ack_mbox_irq(mbox, IRQ_TX); | 165 | ack_mbox_irq(mbox, IRQ_TX); |
269 | schedule_work(&mbox->txq->work); | 166 | tasklet_schedule(&mbox->txq->tasklet); |
270 | } | 167 | } |
271 | 168 | ||
272 | static void __mbox_rx_interrupt(struct omap_mbox *mbox) | 169 | static void __mbox_rx_interrupt(struct omap_mbox *mbox) |
@@ -275,8 +172,6 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox) | |||
275 | mbox_msg_t msg; | 172 | mbox_msg_t msg; |
276 | struct request_queue *q = mbox->rxq->queue; | 173 | struct request_queue *q = mbox->rxq->queue; |
277 | 174 | ||
278 | disable_mbox_irq(mbox, IRQ_RX); | ||
279 | |||
280 | while (!mbox_fifo_empty(mbox)) { | 175 | while (!mbox_fifo_empty(mbox)) { |
281 | rq = blk_get_request(q, WRITE, GFP_ATOMIC); | 176 | rq = blk_get_request(q, WRITE, GFP_ATOMIC); |
282 | if (unlikely(!rq)) | 177 | if (unlikely(!rq)) |
@@ -284,11 +179,6 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox) | |||
284 | 179 | ||
285 | msg = mbox_fifo_read(mbox); | 180 | msg = mbox_fifo_read(mbox); |
286 | 181 | ||
287 | if (unlikely(mbox_seq_test(mbox, msg))) { | ||
288 | pr_info("mbox: Illegal seq bit!(%08x)\n", msg); | ||
289 | if (mbox->err_notify) | ||
290 | mbox->err_notify(); | ||
291 | } | ||
292 | 182 | ||
293 | blk_insert_request(q, rq, 0, (void *)msg); | 183 | blk_insert_request(q, rq, 0, (void *)msg); |
294 | if (mbox->ops->type == OMAP_MBOX_TYPE1) | 184 | if (mbox->ops->type == OMAP_MBOX_TYPE1) |
@@ -297,7 +187,6 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox) | |||
297 | 187 | ||
298 | /* no more messages in the fifo. clear IRQ source. */ | 188 | /* no more messages in the fifo. clear IRQ source. */ |
299 | ack_mbox_irq(mbox, IRQ_RX); | 189 | ack_mbox_irq(mbox, IRQ_RX); |
300 | enable_mbox_irq(mbox, IRQ_RX); | ||
301 | nomem: | 190 | nomem: |
302 | schedule_work(&mbox->rxq->work); | 191 | schedule_work(&mbox->rxq->work); |
303 | } | 192 | } |
@@ -315,76 +204,10 @@ static irqreturn_t mbox_interrupt(int irq, void *p) | |||
315 | return IRQ_HANDLED; | 204 | return IRQ_HANDLED; |
316 | } | 205 | } |
317 | 206 | ||
318 | /* | ||
319 | * sysfs files | ||
320 | */ | ||
321 | static ssize_t | ||
322 | omap_mbox_write(struct device *dev, struct device_attribute *attr, | ||
323 | const char * buf, size_t count) | ||
324 | { | ||
325 | int ret; | ||
326 | mbox_msg_t *p = (mbox_msg_t *)buf; | ||
327 | struct omap_mbox *mbox = dev_get_drvdata(dev); | ||
328 | |||
329 | for (; count >= sizeof(mbox_msg_t); count -= sizeof(mbox_msg_t)) { | ||
330 | ret = omap_mbox_msg_send(mbox, be32_to_cpu(*p), NULL); | ||
331 | if (ret) | ||
332 | return -EAGAIN; | ||
333 | p++; | ||
334 | } | ||
335 | |||
336 | return (size_t)((char *)p - buf); | ||
337 | } | ||
338 | |||
339 | static ssize_t | ||
340 | omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf) | ||
341 | { | ||
342 | unsigned long flags; | ||
343 | struct request *rq; | ||
344 | mbox_msg_t *p = (mbox_msg_t *) buf; | ||
345 | struct omap_mbox *mbox = dev_get_drvdata(dev); | ||
346 | struct request_queue *q = mbox->rxq->queue; | ||
347 | |||
348 | while (1) { | ||
349 | spin_lock_irqsave(q->queue_lock, flags); | ||
350 | rq = blk_fetch_request(q); | ||
351 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
352 | |||
353 | if (!rq) | ||
354 | break; | ||
355 | |||
356 | *p = (mbox_msg_t)rq->special; | ||
357 | |||
358 | blk_end_request_all(rq, 0); | ||
359 | |||
360 | if (unlikely(mbox_seq_test(mbox, *p))) { | ||
361 | pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p); | ||
362 | continue; | ||
363 | } | ||
364 | p++; | ||
365 | } | ||
366 | |||
367 | pr_debug("%02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]); | ||
368 | |||
369 | return (size_t) ((char *)p - buf); | ||
370 | } | ||
371 | |||
372 | static DEVICE_ATTR(mbox, S_IRUGO | S_IWUSR, omap_mbox_read, omap_mbox_write); | ||
373 | |||
374 | static ssize_t mbox_show(struct class *class, char *buf) | ||
375 | { | ||
376 | return sprintf(buf, "mbox"); | ||
377 | } | ||
378 | |||
379 | static CLASS_ATTR(mbox, S_IRUGO, mbox_show, NULL); | ||
380 | |||
381 | static struct class omap_mbox_class = { | ||
382 | .name = "omap-mailbox", | ||
383 | }; | ||
384 | |||
385 | static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, | 207 | static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, |
386 | request_fn_proc * proc, | 208 | request_fn_proc *proc, |
387 | void (*work) (struct work_struct *)) | 209 | void (*work) (struct work_struct *), |
210 | void (*tasklet)(unsigned long)) | ||
388 | { | 211 | { |
389 | struct request_queue *q; | 212 | struct request_queue *q; |
390 | struct omap_mbox_queue *mq; | 213 | struct omap_mbox_queue *mq; |
@@ -401,8 +224,11 @@ static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, | |||
401 | q->queuedata = mbox; | 224 | q->queuedata = mbox; |
402 | mq->queue = q; | 225 | mq->queue = q; |
403 | 226 | ||
404 | INIT_WORK(&mq->work, work); | 227 | if (work) |
228 | INIT_WORK(&mq->work, work); | ||
405 | 229 | ||
230 | if (tasklet) | ||
231 | tasklet_init(&mq->tasklet, tasklet, (unsigned long)mbox); | ||
406 | return mq; | 232 | return mq; |
407 | error: | 233 | error: |
408 | kfree(mq); | 234 | kfree(mq); |
@@ -415,18 +241,25 @@ static void mbox_queue_free(struct omap_mbox_queue *q) | |||
415 | kfree(q); | 241 | kfree(q); |
416 | } | 242 | } |
417 | 243 | ||
418 | static int omap_mbox_init(struct omap_mbox *mbox) | 244 | static int omap_mbox_startup(struct omap_mbox *mbox) |
419 | { | 245 | { |
420 | int ret; | 246 | int ret = 0; |
421 | struct omap_mbox_queue *mq; | 247 | struct omap_mbox_queue *mq; |
422 | 248 | ||
423 | if (likely(mbox->ops->startup)) { | 249 | if (likely(mbox->ops->startup)) { |
424 | ret = mbox->ops->startup(mbox); | 250 | write_lock(&mboxes_lock); |
425 | if (unlikely(ret)) | 251 | if (!mbox_configured) |
252 | ret = mbox->ops->startup(mbox); | ||
253 | |||
254 | if (unlikely(ret)) { | ||
255 | write_unlock(&mboxes_lock); | ||
426 | return ret; | 256 | return ret; |
257 | } | ||
258 | mbox_configured++; | ||
259 | write_unlock(&mboxes_lock); | ||
427 | } | 260 | } |
428 | 261 | ||
429 | ret = request_irq(mbox->irq, mbox_interrupt, IRQF_DISABLED, | 262 | ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, |
430 | mbox->name, mbox); | 263 | mbox->name, mbox); |
431 | if (unlikely(ret)) { | 264 | if (unlikely(ret)) { |
432 | printk(KERN_ERR | 265 | printk(KERN_ERR |
@@ -434,14 +267,14 @@ static int omap_mbox_init(struct omap_mbox *mbox) | |||
434 | goto fail_request_irq; | 267 | goto fail_request_irq; |
435 | } | 268 | } |
436 | 269 | ||
437 | mq = mbox_queue_alloc(mbox, mbox_txq_fn, mbox_tx_work); | 270 | mq = mbox_queue_alloc(mbox, mbox_txq_fn, NULL, mbox_tx_tasklet); |
438 | if (!mq) { | 271 | if (!mq) { |
439 | ret = -ENOMEM; | 272 | ret = -ENOMEM; |
440 | goto fail_alloc_txq; | 273 | goto fail_alloc_txq; |
441 | } | 274 | } |
442 | mbox->txq = mq; | 275 | mbox->txq = mq; |
443 | 276 | ||
444 | mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work); | 277 | mq = mbox_queue_alloc(mbox, mbox_rxq_fn, mbox_rx_work, NULL); |
445 | if (!mq) { | 278 | if (!mq) { |
446 | ret = -ENOMEM; | 279 | ret = -ENOMEM; |
447 | goto fail_alloc_rxq; | 280 | goto fail_alloc_rxq; |
@@ -468,8 +301,14 @@ static void omap_mbox_fini(struct omap_mbox *mbox) | |||
468 | 301 | ||
469 | free_irq(mbox->irq, mbox); | 302 | free_irq(mbox->irq, mbox); |
470 | 303 | ||
471 | if (unlikely(mbox->ops->shutdown)) | 304 | if (unlikely(mbox->ops->shutdown)) { |
472 | mbox->ops->shutdown(mbox); | 305 | write_lock(&mboxes_lock); |
306 | if (mbox_configured > 0) | ||
307 | mbox_configured--; | ||
308 | if (!mbox_configured) | ||
309 | mbox->ops->shutdown(mbox); | ||
310 | write_unlock(&mboxes_lock); | ||
311 | } | ||
473 | } | 312 | } |
474 | 313 | ||
475 | static struct omap_mbox **find_mboxes(const char *name) | 314 | static struct omap_mbox **find_mboxes(const char *name) |
@@ -498,7 +337,7 @@ struct omap_mbox *omap_mbox_get(const char *name) | |||
498 | 337 | ||
499 | read_unlock(&mboxes_lock); | 338 | read_unlock(&mboxes_lock); |
500 | 339 | ||
501 | ret = omap_mbox_init(mbox); | 340 | ret = omap_mbox_startup(mbox); |
502 | if (ret) | 341 | if (ret) |
503 | return ERR_PTR(-ENODEV); | 342 | return ERR_PTR(-ENODEV); |
504 | 343 | ||
@@ -522,15 +361,6 @@ int omap_mbox_register(struct device *parent, struct omap_mbox *mbox) | |||
522 | if (mbox->next) | 361 | if (mbox->next) |
523 | return -EBUSY; | 362 | return -EBUSY; |
524 | 363 | ||
525 | mbox->dev = device_create(&omap_mbox_class, | ||
526 | parent, 0, mbox, "%s", mbox->name); | ||
527 | if (IS_ERR(mbox->dev)) | ||
528 | return PTR_ERR(mbox->dev); | ||
529 | |||
530 | ret = device_create_file(mbox->dev, &dev_attr_mbox); | ||
531 | if (ret) | ||
532 | goto err_sysfs; | ||
533 | |||
534 | write_lock(&mboxes_lock); | 364 | write_lock(&mboxes_lock); |
535 | tmp = find_mboxes(mbox->name); | 365 | tmp = find_mboxes(mbox->name); |
536 | if (*tmp) { | 366 | if (*tmp) { |
@@ -544,9 +374,6 @@ int omap_mbox_register(struct device *parent, struct omap_mbox *mbox) | |||
544 | return 0; | 374 | return 0; |
545 | 375 | ||
546 | err_find: | 376 | err_find: |
547 | device_remove_file(mbox->dev, &dev_attr_mbox); | ||
548 | err_sysfs: | ||
549 | device_unregister(mbox->dev); | ||
550 | return ret; | 377 | return ret; |
551 | } | 378 | } |
552 | EXPORT_SYMBOL(omap_mbox_register); | 379 | EXPORT_SYMBOL(omap_mbox_register); |
@@ -562,8 +389,6 @@ int omap_mbox_unregister(struct omap_mbox *mbox) | |||
562 | *tmp = mbox->next; | 389 | *tmp = mbox->next; |
563 | mbox->next = NULL; | 390 | mbox->next = NULL; |
564 | write_unlock(&mboxes_lock); | 391 | write_unlock(&mboxes_lock); |
565 | device_remove_file(mbox->dev, &dev_attr_mbox); | ||
566 | device_unregister(mbox->dev); | ||
567 | return 0; | 392 | return 0; |
568 | } | 393 | } |
569 | tmp = &(*tmp)->next; | 394 | tmp = &(*tmp)->next; |
@@ -574,23 +399,16 @@ int omap_mbox_unregister(struct omap_mbox *mbox) | |||
574 | } | 399 | } |
575 | EXPORT_SYMBOL(omap_mbox_unregister); | 400 | EXPORT_SYMBOL(omap_mbox_unregister); |
576 | 401 | ||
577 | static int __init omap_mbox_class_init(void) | 402 | static int __init omap_mbox_init(void) |
578 | { | 403 | { |
579 | int ret = class_register(&omap_mbox_class); | 404 | return 0; |
580 | if (!ret) | ||
581 | ret = class_create_file(&omap_mbox_class, &class_attr_mbox); | ||
582 | |||
583 | return ret; | ||
584 | } | 405 | } |
406 | module_init(omap_mbox_init); | ||
585 | 407 | ||
586 | static void __exit omap_mbox_class_exit(void) | 408 | static void __exit omap_mbox_exit(void) |
587 | { | 409 | { |
588 | class_remove_file(&omap_mbox_class, &class_attr_mbox); | ||
589 | class_unregister(&omap_mbox_class); | ||
590 | } | 410 | } |
591 | 411 | module_exit(omap_mbox_exit); | |
592 | subsys_initcall(omap_mbox_class_init); | ||
593 | module_exit(omap_mbox_class_exit); | ||
594 | 412 | ||
595 | MODULE_LICENSE("GPL v2"); | 413 | MODULE_LICENSE("GPL v2"); |
596 | MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging"); | 414 | MODULE_DESCRIPTION("omap mailbox: interrupt driven messaging"); |