From 587808d5f59e842f9258a15e88ad530fcf6e6763 Mon Sep 17 00:00:00 2001
From: Andy Walls <awalls@radix.net>
Date: Wed, 10 Feb 2010 15:34:46 -0300
Subject: V4L/DVB: ivtv: Fix ivtv_api_get_data() to avoid unneeded IO during
 IRQ handling

ivtv_api_get_data() was performing more PCI MMIO than needed, resulting
often in it accounting for more than half the total time spent in
ivtv_irq_handler().  Now it only reads at most 7 of the 16 mailbox data words
over the PCI bus, and in some instances only 2 or 3 data words as needed.

Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
---
 drivers/media/video/ivtv/ivtv-firmware.c | 2 +-
 drivers/media/video/ivtv/ivtv-irq.c      | 9 +++++----
 drivers/media/video/ivtv/ivtv-mailbox.c  | 9 +++++----
 drivers/media/video/ivtv/ivtv-mailbox.h  | 3 ++-
 4 files changed, 13 insertions(+), 10 deletions(-)

(limited to 'drivers')

diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c
index c1b7ec475c2..a71e8ba306b 100644
--- a/drivers/media/video/ivtv/ivtv-firmware.c
+++ b/drivers/media/video/ivtv/ivtv-firmware.c
@@ -258,7 +258,7 @@ void ivtv_init_mpeg_decoder(struct ivtv *itv)
 		IVTV_ERR("ivtv_init_mpeg_decoder failed to start playback\n");
 		return;
 	}
-	ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data);
+	ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data);
 	mem_offset = itv->dec_mem + data[1];
 
 	if ((readbytes = load_fw_direct(IVTV_DECODE_INIT_MPEG_FILENAME,
diff --git a/drivers/media/video/ivtv/ivtv-irq.c b/drivers/media/video/ivtv/ivtv-irq.c
index ee0cdded69f..12d36ca91d5 100644
--- a/drivers/media/video/ivtv/ivtv-irq.c
+++ b/drivers/media/video/ivtv/ivtv-irq.c
@@ -562,7 +562,7 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
 	u32 data[CX2341X_MBOX_MAX_DATA];
 	struct ivtv_stream *s;
 
-	ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data);
+	ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data);
 	IVTV_DEBUG_HI_IRQ("ENC DMA COMPLETE %x %d (%d)\n", data[0], data[1], itv->cur_dma_stream);
 
 	del_timer(&itv->dma_timer);
@@ -638,7 +638,7 @@ static void ivtv_irq_dma_err(struct ivtv *itv)
 	u32 data[CX2341X_MBOX_MAX_DATA];
 
 	del_timer(&itv->dma_timer);
-	ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, data);
+	ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA_END, 2, data);
 	IVTV_DEBUG_WARN("DMA ERROR %08x %08x %08x %d\n", data[0], data[1],
 				read_reg(IVTV_REG_DMASTATUS), itv->cur_dma_stream);
 	write_reg(read_reg(IVTV_REG_DMASTATUS) & 3, IVTV_REG_DMASTATUS);
@@ -669,7 +669,7 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv)
 	struct ivtv_stream *s;
 
 	/* Get DMA destination and size arguments from card */
-	ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA, data);
+	ivtv_api_get_data(&itv->enc_mbox, IVTV_MBOX_DMA, 7, data);
 	IVTV_DEBUG_HI_IRQ("ENC START CAP %d: %08x %08x\n", data[0], data[1], data[2]);
 
 	if (data[0] > 2 || data[1] == 0 || data[2] == 0) {
@@ -713,9 +713,9 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv)
 	struct ivtv_stream *s;
 
 	/* YUV or MPG */
-	ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, data);
 
 	if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags)) {
+		ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 2, data);
 		itv->dma_data_req_size =
 				 1080 * ((itv->yuv_info.v4l2_src_h + 31) & ~31);
 		itv->dma_data_req_offset = data[1];
@@ -724,6 +724,7 @@ static void ivtv_irq_dec_data_req(struct ivtv *itv)
 		s = &itv->streams[IVTV_DEC_STREAM_TYPE_YUV];
 	}
 	else {
+		ivtv_api_get_data(&itv->dec_mbox, IVTV_MBOX_DMA, 3, data);
 		itv->dma_data_req_size = min_t(u32, data[2], 0x10000);
 		itv->dma_data_req_offset = data[1];
 		s = &itv->streams[IVTV_DEC_STREAM_TYPE_MPG];
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c
index 1b5c0ac09a8..84577f6f41a 100644
--- a/drivers/media/video/ivtv/ivtv-mailbox.c
+++ b/drivers/media/video/ivtv/ivtv-mailbox.c
@@ -369,10 +369,11 @@ int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...)
 }
 
 /* This one is for stuff that can't sleep.. irq handlers, etc.. */
-void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb, u32 data[])
+void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb,
+		       int argc, u32 data[])
 {
+	volatile u32 __iomem *p = mbdata->mbox[mb].data;
 	int i;
-
-	for (i = 0; i < CX2341X_MBOX_MAX_DATA; i++)
-		data[i] = readl(&mbdata->mbox[mb].data[i]);
+	for (i = 0; i < argc; i++, p++)
+		data[i] = readl(p);
 }
diff --git a/drivers/media/video/ivtv/ivtv-mailbox.h b/drivers/media/video/ivtv/ivtv-mailbox.h
index 6ef12091e3f..8247662c928 100644
--- a/drivers/media/video/ivtv/ivtv-mailbox.h
+++ b/drivers/media/video/ivtv/ivtv-mailbox.h
@@ -24,7 +24,8 @@
 #define IVTV_MBOX_DMA_END         8
 #define IVTV_MBOX_DMA             9
 
-void ivtv_api_get_data(struct ivtv_mailbox_data *mbox, int mb, u32 data[]);
+void ivtv_api_get_data(struct ivtv_mailbox_data *mbdata, int mb,
+		       int argc, u32 data[]);
 int ivtv_api(struct ivtv *itv, int cmd, int args, u32 data[]);
 int ivtv_vapi_result(struct ivtv *itv, u32 data[CX2341X_MBOX_MAX_DATA], int cmd, int args, ...);
 int ivtv_vapi(struct ivtv *itv, int cmd, int args, ...);
-- 
cgit v1.2.3-70-g09d2