V4L/DVB (9725): cx18: Remove unnecessary MMIO accesses in time critical irq handling...
authorAndy Walls <awalls@radix.net>
Tue, 18 Nov 2008 01:48:46 +0000 (22:48 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 30 Dec 2008 11:38:10 +0000 (09:38 -0200)
Remove unnecessary MMIO accesses in time critical irq handling path.  Also
ensured that the mailbox ack field is read in last, so we know for sure if we
have a stale mailbox or not on receipt.

Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/cx18/cx18-driver.h
drivers/media/video/cx18/cx18-io.c
drivers/media/video/cx18/cx18-irq.c
drivers/media/video/cx18/cx18-mailbox.c

index 02a82c3..cad352a 100644 (file)
@@ -446,6 +446,10 @@ struct cx18 {
        /* when the current DMA is finished this queue is woken up */
        wait_queue_head_t dma_waitq;
 
+       u32 sw1_irq_mask;
+       u32 sw2_irq_mask;
+       u32 hw2_irq_mask;
+
        struct cx18_epu_work_order epu_work_order[CX18_MAX_EPU_WORK_ORDERS];
        char epu_debug_str[256]; /* CX18_EPU_DEBUG is rare: use shared space */
 
index a2b5e80..c6f1d0d 100644 (file)
@@ -71,32 +71,28 @@ void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count)
 
 void cx18_sw1_irq_enable(struct cx18 *cx, u32 val)
 {
-       u32 r;
        cx18_write_reg_expect(cx, val, SW1_INT_STATUS, ~val, val);
-       r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI);
-       cx18_write_reg(cx, r | val, SW1_INT_ENABLE_PCI);
+       cx->sw1_irq_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) | val;
+       cx18_write_reg(cx, cx->sw1_irq_mask, SW1_INT_ENABLE_PCI);
 }
 
 void cx18_sw1_irq_disable(struct cx18 *cx, u32 val)
 {
-       u32 r;
-       r = cx18_read_reg(cx, SW1_INT_ENABLE_PCI);
-       cx18_write_reg(cx, r & ~val, SW1_INT_ENABLE_PCI);
+       cx->sw1_irq_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI) & ~val;
+       cx18_write_reg(cx, cx->sw1_irq_mask, SW1_INT_ENABLE_PCI);
 }
 
 void cx18_sw2_irq_enable(struct cx18 *cx, u32 val)
 {
-       u32 r;
        cx18_write_reg_expect(cx, val, SW2_INT_STATUS, ~val, val);
-       r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI);
-       cx18_write_reg(cx, r | val, SW2_INT_ENABLE_PCI);
+       cx->sw2_irq_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) | val;
+       cx18_write_reg(cx, cx->sw2_irq_mask, SW2_INT_ENABLE_PCI);
 }
 
 void cx18_sw2_irq_disable(struct cx18 *cx, u32 val)
 {
-       u32 r;
-       r = cx18_read_reg(cx, SW2_INT_ENABLE_PCI);
-       cx18_write_reg(cx, r & ~val, SW2_INT_ENABLE_PCI);
+       cx->sw2_irq_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI) & ~val;
+       cx18_write_reg(cx, cx->sw2_irq_mask, SW2_INT_ENABLE_PCI);
 }
 
 void cx18_sw2_irq_disable_cpu(struct cx18 *cx, u32 val)
index bc36a6b..2a94e50 100644 (file)
@@ -44,16 +44,11 @@ static void epu_cmd(struct cx18 *cx, u32 sw1)
 irqreturn_t cx18_irq_handler(int irq, void *dev_id)
 {
        struct cx18 *cx = (struct cx18 *)dev_id;
-       u32 sw1, sw1_mask;
-       u32 sw2, sw2_mask;
-       u32 hw2, hw2_mask;
+       u32 sw1, sw2, hw2;
 
-       sw1_mask = cx18_read_reg(cx, SW1_INT_ENABLE_PCI);
-       sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & sw1_mask;
-       sw2_mask = cx18_read_reg(cx, SW2_INT_ENABLE_PCI);
-       sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & sw2_mask;
-       hw2_mask = cx18_read_reg(cx, HW2_INT_MASK5_PCI);
-       hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & hw2_mask;
+       sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & cx->sw1_irq_mask;
+       sw2 = cx18_read_reg(cx, SW2_INT_STATUS) & cx->sw2_irq_mask;
+       hw2 = cx18_read_reg(cx, HW2_INT_CLR_STATUS) & cx->hw2_irq_mask;
 
        if (sw1)
                cx18_write_reg_expect(cx, sw1, SW1_INT_STATUS, ~sw1, sw1);
index 844a62d..e5d4f31 100644 (file)
@@ -399,7 +399,12 @@ void cx18_api_epu_cmd_irq(struct cx18 *cx, int rpu)
        order->flags = 0;
        order->rpu = rpu;
        order_mb = &order->mb;
-       cx18_memcpy_fromio(cx, order_mb, mb, sizeof(struct cx18_mailbox));
+
+       /* mb->cmd and mb->args[0] through mb->args[2] */
+       cx18_memcpy_fromio(cx, &order_mb->cmd, &mb->cmd, 4 * sizeof(u32));
+       /* mb->request and mb->ack.  N.B. we want to read mb->ack last */
+       cx18_memcpy_fromio(cx, &order_mb->request, &mb->request,
+                          2 * sizeof(u32));
 
        if (order_mb->request == order_mb->ack) {
                CX18_WARN("Possibly falling behind: %s self-ack'ed our incoming"