diff options
Diffstat (limited to 'arch/arm/plat-omap/mailbox.c')
-rw-r--r-- | arch/arm/plat-omap/mailbox.c | 63 |
1 files changed, 40 insertions, 23 deletions
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 0abfbaa59871..40424edae939 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c | |||
@@ -147,24 +147,40 @@ static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg) | |||
147 | return ret; | 147 | return ret; |
148 | } | 148 | } |
149 | 149 | ||
150 | struct omap_msg_tx_data { | ||
151 | mbox_msg_t msg; | ||
152 | void *arg; | ||
153 | }; | ||
154 | |||
155 | static void omap_msg_tx_end_io(struct request *rq, int error) | ||
156 | { | ||
157 | kfree(rq->special); | ||
158 | __blk_put_request(rq->q, rq); | ||
159 | } | ||
160 | |||
150 | int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg) | 161 | int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg) |
151 | { | 162 | { |
163 | struct omap_msg_tx_data *tx_data; | ||
152 | struct request *rq; | 164 | struct request *rq; |
153 | struct request_queue *q = mbox->txq->queue; | 165 | struct request_queue *q = mbox->txq->queue; |
154 | int ret = 0; | 166 | |
167 | tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC); | ||
168 | if (unlikely(!tx_data)) | ||
169 | return -ENOMEM; | ||
155 | 170 | ||
156 | rq = blk_get_request(q, WRITE, GFP_ATOMIC); | 171 | rq = blk_get_request(q, WRITE, GFP_ATOMIC); |
157 | if (unlikely(!rq)) { | 172 | if (unlikely(!rq)) { |
158 | ret = -ENOMEM; | 173 | kfree(tx_data); |
159 | goto fail; | 174 | return -ENOMEM; |
160 | } | 175 | } |
161 | 176 | ||
162 | rq->data = (void *)msg; | 177 | tx_data->msg = msg; |
163 | blk_insert_request(q, rq, 0, arg); | 178 | tx_data->arg = arg; |
179 | rq->end_io = omap_msg_tx_end_io; | ||
180 | blk_insert_request(q, rq, 0, tx_data); | ||
164 | 181 | ||
165 | schedule_work(&mbox->txq->work); | 182 | schedule_work(&mbox->txq->work); |
166 | fail: | 183 | return 0; |
167 | return ret; | ||
168 | } | 184 | } |
169 | EXPORT_SYMBOL(omap_mbox_msg_send); | 185 | EXPORT_SYMBOL(omap_mbox_msg_send); |
170 | 186 | ||
@@ -178,22 +194,28 @@ static void mbox_tx_work(struct work_struct *work) | |||
178 | struct request_queue *q = mbox->txq->queue; | 194 | struct request_queue *q = mbox->txq->queue; |
179 | 195 | ||
180 | while (1) { | 196 | while (1) { |
197 | struct omap_msg_tx_data *tx_data; | ||
198 | |||
181 | spin_lock(q->queue_lock); | 199 | spin_lock(q->queue_lock); |
182 | rq = elv_next_request(q); | 200 | rq = blk_fetch_request(q); |
183 | spin_unlock(q->queue_lock); | 201 | spin_unlock(q->queue_lock); |
184 | 202 | ||
185 | if (!rq) | 203 | if (!rq) |
186 | break; | 204 | break; |
187 | 205 | ||
188 | ret = __mbox_msg_send(mbox, (mbox_msg_t) rq->data, rq->special); | 206 | tx_data = rq->special; |
207 | |||
208 | ret = __mbox_msg_send(mbox, tx_data->msg, tx_data->arg); | ||
189 | if (ret) { | 209 | if (ret) { |
190 | enable_mbox_irq(mbox, IRQ_TX); | 210 | enable_mbox_irq(mbox, IRQ_TX); |
211 | spin_lock(q->queue_lock); | ||
212 | blk_requeue_request(q, rq); | ||
213 | spin_unlock(q->queue_lock); | ||
191 | return; | 214 | return; |
192 | } | 215 | } |
193 | 216 | ||
194 | spin_lock(q->queue_lock); | 217 | spin_lock(q->queue_lock); |
195 | if (__blk_end_request(rq, 0, 0)) | 218 | __blk_end_request_all(rq, 0); |
196 | BUG(); | ||
197 | spin_unlock(q->queue_lock); | 219 | spin_unlock(q->queue_lock); |
198 | } | 220 | } |
199 | } | 221 | } |
@@ -218,16 +240,13 @@ static void mbox_rx_work(struct work_struct *work) | |||
218 | 240 | ||
219 | while (1) { | 241 | while (1) { |
220 | spin_lock_irqsave(q->queue_lock, flags); | 242 | spin_lock_irqsave(q->queue_lock, flags); |
221 | rq = elv_next_request(q); | 243 | rq = blk_fetch_request(q); |
222 | spin_unlock_irqrestore(q->queue_lock, flags); | 244 | spin_unlock_irqrestore(q->queue_lock, flags); |
223 | if (!rq) | 245 | if (!rq) |
224 | break; | 246 | break; |
225 | 247 | ||
226 | msg = (mbox_msg_t) rq->data; | 248 | msg = (mbox_msg_t)rq->special; |
227 | 249 | blk_end_request_all(rq, 0); | |
228 | if (blk_end_request(rq, 0, 0)) | ||
229 | BUG(); | ||
230 | |||
231 | mbox->rxq->callback((void *)msg); | 250 | mbox->rxq->callback((void *)msg); |
232 | } | 251 | } |
233 | } | 252 | } |
@@ -264,7 +283,6 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox) | |||
264 | goto nomem; | 283 | goto nomem; |
265 | 284 | ||
266 | msg = mbox_fifo_read(mbox); | 285 | msg = mbox_fifo_read(mbox); |
267 | rq->data = (void *)msg; | ||
268 | 286 | ||
269 | if (unlikely(mbox_seq_test(mbox, msg))) { | 287 | if (unlikely(mbox_seq_test(mbox, msg))) { |
270 | pr_info("mbox: Illegal seq bit!(%08x)\n", msg); | 288 | pr_info("mbox: Illegal seq bit!(%08x)\n", msg); |
@@ -272,7 +290,7 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox) | |||
272 | mbox->err_notify(); | 290 | mbox->err_notify(); |
273 | } | 291 | } |
274 | 292 | ||
275 | blk_insert_request(q, rq, 0, NULL); | 293 | blk_insert_request(q, rq, 0, (void *)msg); |
276 | if (mbox->ops->type == OMAP_MBOX_TYPE1) | 294 | if (mbox->ops->type == OMAP_MBOX_TYPE1) |
277 | break; | 295 | break; |
278 | } | 296 | } |
@@ -329,16 +347,15 @@ omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf) | |||
329 | 347 | ||
330 | while (1) { | 348 | while (1) { |
331 | spin_lock_irqsave(q->queue_lock, flags); | 349 | spin_lock_irqsave(q->queue_lock, flags); |
332 | rq = elv_next_request(q); | 350 | rq = blk_fetch_request(q); |
333 | spin_unlock_irqrestore(q->queue_lock, flags); | 351 | spin_unlock_irqrestore(q->queue_lock, flags); |
334 | 352 | ||
335 | if (!rq) | 353 | if (!rq) |
336 | break; | 354 | break; |
337 | 355 | ||
338 | *p = (mbox_msg_t) rq->data; | 356 | *p = (mbox_msg_t)rq->special; |
339 | 357 | ||
340 | if (blk_end_request(rq, 0, 0)) | 358 | blk_end_request_all(rq, 0); |
341 | BUG(); | ||
342 | 359 | ||
343 | if (unlikely(mbox_seq_test(mbox, *p))) { | 360 | if (unlikely(mbox_seq_test(mbox, *p))) { |
344 | pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p); | 361 | pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p); |