aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHari Kanigeri <h-kanigeri2@ti.com>2010-08-05 21:00:01 -0400
committerPaolo Pisati <paolo.pisati@canonical.com>2012-08-17 04:19:06 -0400
commit28e00e987cf585247a88b4efc764c2892089f1bd (patch)
tree884a4c57629a484529710fc09c9ef2731ede0825
parent3bdbdae464566dd88236e27e04d0ce677a9e30ba (diff)
omap:mailbox-resolve multiple receiver problem
The ISR is handling only the mailbox instance that was registered last. So if both mailbox instances are running at the same time, the first mailbox that registered wouldn't get the mailbox message. The same issue is present in Transmit Interrupt case too. Only the last registered mailbox is handled. The fix is to iterate through the list of mailbox that were registered. Signed-off-by: Hari Kanigeri <h-kanigeri2@ti.com> Signed-off-by: Ramesh Gupta <grgupta@ti.com> Signed-off-by: Subramaniam C.A <subramaniam.ca@ti.com>
-rw-r--r--arch/arm/plat-omap/mailbox.c66
1 files changed, 44 insertions, 22 deletions
diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c
index 578465de17a..faadfb6cb5a 100644
--- a/arch/arm/plat-omap/mailbox.c
+++ b/arch/arm/plat-omap/mailbox.c
@@ -167,37 +167,59 @@ static void mbox_rx_work(struct work_struct *work)
167 */ 167 */
168static void __mbox_tx_interrupt(struct omap_mbox *mbox) 168static void __mbox_tx_interrupt(struct omap_mbox *mbox)
169{ 169{
170 omap_mbox_disable_irq(mbox, IRQ_TX); 170 struct omap_mbox *mbox_curr;
171 ack_mbox_irq(mbox, IRQ_TX); 171 int i =0;
172 tasklet_schedule(&mbox->txq->tasklet); 172
173 while (mboxes[i]) {
174 mbox_curr = mboxes[i];
175 if (!mbox_fifo_full(mbox_curr)) {
176 omap_mbox_disable_irq(mbox_curr, IRQ_TX);
177 ack_mbox_irq(mbox_curr, IRQ_TX);
178 tasklet_schedule(&mbox_curr->txq->tasklet);
179 }
180 i++;
181 }
173} 182}
174 183
175static void __mbox_rx_interrupt(struct omap_mbox *mbox) 184static void __mbox_rx_interrupt(struct omap_mbox *mbox)
176{ 185{
177 struct omap_mbox_queue *mq = mbox->rxq; 186 struct omap_mbox_queue *mq;
178 mbox_msg_t msg; 187 mbox_msg_t msg;
179 int len; 188 int len;
180 189 int i = 0;
181 while (!mbox_fifo_empty(mbox)) { 190 struct omap_mbox *mbox_curr;
182 if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) { 191 bool msg_rx;
183 omap_mbox_disable_irq(mbox, IRQ_RX); 192
184 mq->full = true; 193 while (mboxes[i]) {
185 goto nomem; 194 mbox_curr = mboxes[i];
195 mq = mbox_curr->rxq;
196 msg_rx = false;
197 while (!mbox_fifo_empty(mbox_curr)) {
198 msg_rx = true;
199 if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) {
200 omap_mbox_disable_irq(mbox_curr, IRQ_RX);
201 rq_full = true;
202 goto nomem;
203 }
204
205 msg = mbox_fifo_read(mbox_curr);
206
207 len = kfifo_in(&mq->fifo, (unsigned char *)&msg,
208 sizeof(msg));
209 if (unlikely(len != sizeof(msg)))
210 pr_err("%s: kfifo_in anomaly detected\n",
211 __func__);
212 if (mbox->ops->type == OMAP_MBOX_TYPE1)
213 break;
186 } 214 }
215 /* no more messages in the fifo. clear IRQ source. */
216 if (msg_rx)
217 ack_mbox_irq(mbox, IRQ_RX);
218nomem:
219 schedule_work(&mbox->rxq->work);
187 220
188 msg = mbox_fifo_read(mbox); 221 i++;
189
190 len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
191 WARN_ON(len != sizeof(msg));
192
193 if (mbox->ops->type == OMAP_MBOX_TYPE1)
194 break;
195 } 222 }
196
197 /* no more messages in the fifo. clear IRQ source. */
198 ack_mbox_irq(mbox, IRQ_RX);
199nomem:
200 schedule_work(&mbox->rxq->work);
201} 223}
202 224
203static irqreturn_t mbox_interrupt(int irq, void *p) 225static irqreturn_t mbox_interrupt(int irq, void *p)