aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2008-09-28 20:46:02 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-12 07:37:14 -0400
commitd267d85101c509020a12686b96cbd179deaf4ecd (patch)
tree1a016966d11efb400ca310cd5726478053cd00a0
parent7f9876785276ac7f8606f8bf53a3dae4c10b8adb (diff)
V4L/DVB (9110): cx18: Add default behavior of checking and retrying PCI MMIO accesses
cx18: Add default behavior of checking and retrying PCI MMIO accesses. The concept of checking and retrying PCI MMIO accesses for better reliability in older motherboards was suggested by Steve Toth <stoth@linuxtv.org>. This change implements MMIO retries and the retry_mmio module parameter that is enabled by default. Limited experiments have shown this is more reliable than the mmio_ndelay parameter. mmio_ndelay has insignificant effect with retries enabled. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/cx18/cx18-av-core.c11
-rw-r--r--drivers/media/video/cx18/cx18-av-core.h2
-rw-r--r--drivers/media/video/cx18/cx18-av-firmware.c18
-rw-r--r--drivers/media/video/cx18/cx18-driver.c7
-rw-r--r--drivers/media/video/cx18/cx18-driver.h11
-rw-r--r--drivers/media/video/cx18/cx18-io.c135
-rw-r--r--drivers/media/video/cx18/cx18-io.h278
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c1
8 files changed, 427 insertions, 36 deletions
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
index d8626e35465..73f5141a42d 100644
--- a/drivers/media/video/cx18/cx18-av-core.c
+++ b/drivers/media/video/cx18/cx18-av-core.c
@@ -42,6 +42,12 @@ int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value)
42 return 0; 42 return 0;
43} 43}
44 44
45int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value)
46{
47 cx18_write_reg_noretry(cx, value, 0xc40000 + addr);
48 return 0;
49}
50
45u8 cx18_av_read(struct cx18 *cx, u16 addr) 51u8 cx18_av_read(struct cx18 *cx, u16 addr)
46{ 52{
47 u32 x = cx18_read_reg(cx, 0xc40000 + (addr & ~3)); 53 u32 x = cx18_read_reg(cx, 0xc40000 + (addr & ~3));
@@ -55,6 +61,11 @@ u32 cx18_av_read4(struct cx18 *cx, u16 addr)
55 return cx18_read_reg(cx, 0xc40000 + addr); 61 return cx18_read_reg(cx, 0xc40000 + addr);
56} 62}
57 63
64u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr)
65{
66 return cx18_read_reg_noretry(cx, 0xc40000 + addr);
67}
68
58int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask, 69int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned and_mask,
59 u8 or_value) 70 u8 or_value)
60{ 71{
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h
index eb61fa1e096..b67d8df20cc 100644
--- a/drivers/media/video/cx18/cx18-av-core.h
+++ b/drivers/media/video/cx18/cx18-av-core.h
@@ -301,8 +301,10 @@ struct cx18_av_state {
301/* cx18_av-core.c */ 301/* cx18_av-core.c */
302int cx18_av_write(struct cx18 *cx, u16 addr, u8 value); 302int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
303int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value); 303int cx18_av_write4(struct cx18 *cx, u16 addr, u32 value);
304int cx18_av_write4_noretry(struct cx18 *cx, u16 addr, u32 value);
304u8 cx18_av_read(struct cx18 *cx, u16 addr); 305u8 cx18_av_read(struct cx18 *cx, u16 addr);
305u32 cx18_av_read4(struct cx18 *cx, u16 addr); 306u32 cx18_av_read4(struct cx18 *cx, u16 addr);
307u32 cx18_av_read4_noretry(struct cx18 *cx, u16 addr);
306int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value); 308int cx18_av_and_or(struct cx18 *cx, u16 addr, unsigned mask, u8 value);
307int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value); 309int cx18_av_and_or4(struct cx18 *cx, u16 addr, u32 mask, u32 value);
308int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg); 310int cx18_av_cmd(struct cx18 *cx, unsigned int cmd, void *arg);
diff --git a/drivers/media/video/cx18/cx18-av-firmware.c b/drivers/media/video/cx18/cx18-av-firmware.c
index 0488b629770..522a035b2e8 100644
--- a/drivers/media/video/cx18/cx18-av-firmware.c
+++ b/drivers/media/video/cx18/cx18-av-firmware.c
@@ -50,7 +50,7 @@ int cx18_av_loadfw(struct cx18 *cx)
50 cx18_av_write4(cx, 0x8100, 0x00010000); 50 cx18_av_write4(cx, 0x8100, 0x00010000);
51 51
52 /* Put the 8051 in reset and enable firmware upload */ 52 /* Put the 8051 in reset and enable firmware upload */
53 cx18_av_write4(cx, CXADEC_DL_CTL, 0x0F000000); 53 cx18_av_write4_noretry(cx, CXADEC_DL_CTL, 0x0F000000);
54 54
55 ptr = fw->data; 55 ptr = fw->data;
56 size = fw->size; 56 size = fw->size;
@@ -59,22 +59,28 @@ int cx18_av_loadfw(struct cx18 *cx)
59 u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16); 59 u32 dl_control = 0x0F000000 | i | ((u32)ptr[i] << 16);
60 u32 value = 0; 60 u32 value = 0;
61 int retries2; 61 int retries2;
62 int unrec_err = 0;
62 63
63 for (retries2 = 0; retries2 < 5; retries2++) { 64 for (retries2 = 0; retries2 < CX18_MAX_MMIO_RETRIES;
64 cx18_av_write4(cx, CXADEC_DL_CTL, dl_control); 65 retries2++) {
66 cx18_av_write4_noretry(cx, CXADEC_DL_CTL,
67 dl_control);
65 udelay(10); 68 udelay(10);
66 value = cx18_av_read4(cx, CXADEC_DL_CTL); 69 value = cx18_av_read4_noretry(cx,
70 CXADEC_DL_CTL);
67 if (value == dl_control) 71 if (value == dl_control)
68 break; 72 break;
69 /* Check if we can correct the byte by changing 73 /* Check if we can correct the byte by changing
70 the address. We can only write the lower 74 the address. We can only write the lower
71 address byte of the address. */ 75 address byte of the address. */
72 if ((value & 0x3F00) != (dl_control & 0x3F00)) { 76 if ((value & 0x3F00) != (dl_control & 0x3F00)) {
73 retries2 = 5; 77 unrec_err = 1;
74 break; 78 break;
75 } 79 }
76 } 80 }
77 if (retries2 >= 5) 81 cx18_log_write_retries(cx, retries2,
82 cx->reg_mem + 0xc40000 + CXADEC_DL_CTL);
83 if (unrec_err || retries2 >= CX18_MAX_MMIO_RETRIES)
78 break; 84 break;
79 } 85 }
80 if (i == size) 86 if (i == size)
diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c
index 4de7b501f20..df5531709ae 100644
--- a/drivers/media/video/cx18/cx18-driver.c
+++ b/drivers/media/video/cx18/cx18-driver.c
@@ -96,6 +96,7 @@ static int enc_pcm_buffers = CX18_DEFAULT_ENC_PCM_BUFFERS;
96 96
97static int cx18_pci_latency = 1; 97static int cx18_pci_latency = 1;
98 98
99int cx18_retry_mmio = 1;
99int cx18_debug; 100int cx18_debug;
100 101
101module_param_array(tuner, int, &tuner_c, 0644); 102module_param_array(tuner, int, &tuner_c, 0644);
@@ -106,6 +107,7 @@ module_param_string(pal, pal, sizeof(pal), 0644);
106module_param_string(secam, secam, sizeof(secam), 0644); 107module_param_string(secam, secam, sizeof(secam), 0644);
107module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); 108module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
108module_param_named(debug, cx18_debug, int, 0644); 109module_param_named(debug, cx18_debug, int, 0644);
110module_param_named(retry_mmio, cx18_retry_mmio, int, 0644);
109module_param(cx18_pci_latency, int, 0644); 111module_param(cx18_pci_latency, int, 0644);
110module_param(cx18_first_minor, int, 0644); 112module_param(cx18_first_minor, int, 0644);
111 113
@@ -147,6 +149,9 @@ MODULE_PARM_DESC(debug,
147MODULE_PARM_DESC(cx18_pci_latency, 149MODULE_PARM_DESC(cx18_pci_latency,
148 "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n" 150 "Change the PCI latency to 64 if lower: 0 = No, 1 = Yes,\n"
149 "\t\t\tDefault: Yes"); 151 "\t\t\tDefault: Yes");
152MODULE_PARM_DESC(retry_mmio,
153 "Check and retry memory mapped IO accesses\n"
154 "\t\t\tDefault: 1 [Yes]");
150MODULE_PARM_DESC(mmio_ndelay, 155MODULE_PARM_DESC(mmio_ndelay,
151 "Delay (ns) for each CX23418 memory mapped IO access.\n" 156 "Delay (ns) for each CX23418 memory mapped IO access.\n"
152 "\t\t\tTry larger values that are close to a multiple of the\n" 157 "\t\t\tTry larger values that are close to a multiple of the\n"
@@ -827,6 +832,7 @@ err:
827 if (retval == 0) 832 if (retval == 0)
828 retval = -ENODEV; 833 retval = -ENODEV;
829 CX18_ERR("Error %d on initialization\n", retval); 834 CX18_ERR("Error %d on initialization\n", retval);
835 cx18_log_statistics(cx);
830 836
831 kfree(cx18_cards[cx18_cards_active]); 837 kfree(cx18_cards[cx18_cards_active]);
832 cx18_cards[cx18_cards_active] = NULL; 838 cx18_cards[cx18_cards_active] = NULL;
@@ -931,6 +937,7 @@ static void cx18_remove(struct pci_dev *pci_dev)
931 937
932 pci_disable_device(cx->dev); 938 pci_disable_device(cx->dev);
933 939
940 cx18_log_statistics(cx);
934 CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num); 941 CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num);
935} 942}
936 943
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index 66cb748875c..80f5f563d4f 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -171,6 +171,7 @@
171 171
172#define CX18_MAX_PGM_INDEX (400) 172#define CX18_MAX_PGM_INDEX (400)
173 173
174extern int cx18_retry_mmio; /* enable check & retry of mmio accesses */
174extern int cx18_debug; 175extern int cx18_debug;
175 176
176 177
@@ -344,6 +345,13 @@ struct cx18_i2c_algo_callback_data {
344 int bus_index; /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */ 345 int bus_index; /* 0 or 1 for the cx23418's 1st or 2nd I2C bus */
345}; 346};
346 347
348#define CX18_MAX_MMIO_RETRIES 10
349
350struct cx18_mmio_stats {
351 atomic_t retried_write[CX18_MAX_MMIO_RETRIES+1];
352 atomic_t retried_read[CX18_MAX_MMIO_RETRIES+1];
353};
354
347/* Struct to hold info about cx18 cards */ 355/* Struct to hold info about cx18 cards */
348struct cx18 { 356struct cx18 {
349 int num; /* board number, -1 during init! */ 357 int num; /* board number, -1 during init! */
@@ -433,6 +441,9 @@ struct cx18 {
433 u32 gpio_val; 441 u32 gpio_val;
434 struct mutex gpio_lock; 442 struct mutex gpio_lock;
435 443
444 /* Statistics */
445 struct cx18_mmio_stats mmio_stats;
446
436 /* v4l2 and User settings */ 447 /* v4l2 and User settings */
437 448
438 /* codec settings */ 449 /* codec settings */
diff --git a/drivers/media/video/cx18/cx18-io.c b/drivers/media/video/cx18/cx18-io.c
index 55d1df93292..700ab9439c1 100644
--- a/drivers/media/video/cx18/cx18-io.c
+++ b/drivers/media/video/cx18/cx18-io.c
@@ -24,6 +24,131 @@
24#include "cx18-io.h" 24#include "cx18-io.h"
25#include "cx18-irq.h" 25#include "cx18-irq.h"
26 26
27void cx18_log_statistics(struct cx18 *cx)
28{
29 int i;
30
31 if (!(cx18_debug & CX18_DBGFLG_INFO))
32 return;
33
34 for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++)
35 CX18_DEBUG_INFO("retried_write[%d] = %d\n", i,
36 atomic_read(&cx->mmio_stats.retried_write[i]));
37 for (i = 0; i <= CX18_MAX_MMIO_RETRIES; i++)
38 CX18_DEBUG_INFO("retried_read[%d] = %d\n", i,
39 atomic_read(&cx->mmio_stats.retried_read[i]));
40 return;
41}
42
43void cx18_raw_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr)
44{
45 int i;
46 for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
47 cx18_raw_writel_noretry(cx, val, addr);
48 if (val == cx18_raw_readl_noretry(cx, addr))
49 break;
50 }
51 cx18_log_write_retries(cx, i, addr);
52}
53
54u32 cx18_raw_readl_retry(struct cx18 *cx, const void __iomem *addr)
55{
56 int i;
57 u32 val;
58 for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
59 val = cx18_raw_readl_noretry(cx, addr);
60 if (val != 0xffffffff) /* PCI bus read error */
61 break;
62 }
63 cx18_log_read_retries(cx, i, addr);
64 return val;
65}
66
67u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr)
68{
69 int i;
70 u16 val;
71 for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
72 val = cx18_raw_readw_noretry(cx, addr);
73 if (val != 0xffff) /* PCI bus read error */
74 break;
75 }
76 cx18_log_read_retries(cx, i, addr);
77 return val;
78}
79
80void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr)
81{
82 int i;
83 for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
84 cx18_writel_noretry(cx, val, addr);
85 if (val == cx18_readl_noretry(cx, addr))
86 break;
87 }
88 cx18_log_write_retries(cx, i, addr);
89}
90
91void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr)
92{
93 int i;
94 for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
95 cx18_writew_noretry(cx, val, addr);
96 if (val == cx18_readw_noretry(cx, addr))
97 break;
98 }
99 cx18_log_write_retries(cx, i, addr);
100}
101
102void cx18_writeb_retry(struct cx18 *cx, u8 val, void __iomem *addr)
103{
104 int i;
105 for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
106 cx18_writeb_noretry(cx, val, addr);
107 if (val == cx18_readb_noretry(cx, addr))
108 break;
109 }
110 cx18_log_write_retries(cx, i, addr);
111}
112
113u32 cx18_readl_retry(struct cx18 *cx, const void __iomem *addr)
114{
115 int i;
116 u32 val;
117 for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
118 val = cx18_readl_noretry(cx, addr);
119 if (val != 0xffffffff) /* PCI bus read error */
120 break;
121 }
122 cx18_log_read_retries(cx, i, addr);
123 return val;
124}
125
126u16 cx18_readw_retry(struct cx18 *cx, const void __iomem *addr)
127{
128 int i;
129 u16 val;
130 for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
131 val = cx18_readw_noretry(cx, addr);
132 if (val != 0xffff) /* PCI bus read error */
133 break;
134 }
135 cx18_log_read_retries(cx, i, addr);
136 return val;
137}
138
139u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr)
140{
141 int i;
142 u8 val;
143 for (i = 0; i < CX18_MAX_MMIO_RETRIES; i++) {
144 val = cx18_readb_noretry(cx, addr);
145 if (val != 0xff) /* PCI bus read error */
146 break;
147 }
148 cx18_log_read_retries(cx, i, addr);
149 return val;
150}
151
27void cx18_memcpy_fromio(struct cx18 *cx, void *to, 152void cx18_memcpy_fromio(struct cx18 *cx, void *to,
28 const void __iomem *from, unsigned int len) 153 const void __iomem *from, unsigned int len)
29{ 154{
@@ -127,13 +252,3 @@ void cx18_setup_page(struct cx18 *cx, u32 addr)
127 val = (val & ~0x1f00) | ((addr >> 17) & 0x1f00); 252 val = (val & ~0x1f00) | ((addr >> 17) & 0x1f00);
128 cx18_write_reg(cx, val, 0xD000F8); 253 cx18_write_reg(cx, val, 0xD000F8);
129} 254}
130
131/* Tries to recover from the CX23418 responding improperly on the PCI bus */
132int cx18_pci_try_recover(struct cx18 *cx)
133{
134 u16 status;
135
136 pci_read_config_word(cx->dev, PCI_STATUS, &status);
137 pci_write_config_word(cx->dev, PCI_STATUS, status);
138 return 0;
139}
diff --git a/drivers/media/video/cx18/cx18-io.h b/drivers/media/video/cx18/cx18-io.h
index 7ab7be2531c..197d4fbd9f9 100644
--- a/drivers/media/video/cx18/cx18-io.h
+++ b/drivers/media/video/cx18/cx18-io.h
@@ -31,102 +31,343 @@ static inline void cx18_io_delay(struct cx18 *cx)
31 ndelay(cx->options.mmio_ndelay); 31 ndelay(cx->options.mmio_ndelay);
32} 32}
33 33
34/*
35 * Readback and retry of MMIO access for reliability:
36 * The concept was suggested by Steve Toth <stoth@linuxtv.org>.
37 * The implmentation is the fault of Andy Walls <awalls@radix.net>.
38 */
39
40/* Statistics gathering */
41static inline
42void cx18_log_write_retries(struct cx18 *cx, int i, const void *addr)
43{
44 if (i > CX18_MAX_MMIO_RETRIES)
45 i = CX18_MAX_MMIO_RETRIES;
46 atomic_inc(&cx->mmio_stats.retried_write[i]);
47 return;
48}
49
50static inline
51void cx18_log_read_retries(struct cx18 *cx, int i, const void *addr)
52{
53 if (i > CX18_MAX_MMIO_RETRIES)
54 i = CX18_MAX_MMIO_RETRIES;
55 atomic_inc(&cx->mmio_stats.retried_read[i]);
56 return;
57}
58
59void cx18_log_statistics(struct cx18 *cx);
60
34/* Non byteswapping memory mapped IO */ 61/* Non byteswapping memory mapped IO */
35static inline void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr) 62static inline
63void cx18_raw_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
36{ 64{
37 __raw_writel(val, addr); 65 __raw_writel(val, addr);
38 cx18_io_delay(cx); 66 cx18_io_delay(cx);
39} 67}
40 68
41static inline u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr) 69void cx18_raw_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr);
70
71static inline void cx18_raw_writel(struct cx18 *cx, u32 val, void __iomem *addr)
72{
73 if (cx18_retry_mmio)
74 cx18_raw_writel_retry(cx, val, addr);
75 else
76 cx18_raw_writel_noretry(cx, val, addr);
77}
78
79
80static inline
81u32 cx18_raw_readl_noretry(struct cx18 *cx, const void __iomem *addr)
42{ 82{
43 u32 ret = __raw_readl(addr); 83 u32 ret = __raw_readl(addr);
44 cx18_io_delay(cx); 84 cx18_io_delay(cx);
45 return ret; 85 return ret;
46} 86}
47 87
48static inline u16 cx18_raw_readw(struct cx18 *cx, const void __iomem *addr) 88u32 cx18_raw_readl_retry(struct cx18 *cx, const void __iomem *addr);
89
90static inline u32 cx18_raw_readl(struct cx18 *cx, const void __iomem *addr)
91{
92 if (cx18_retry_mmio)
93 return cx18_raw_readl_retry(cx, addr);
94
95 return cx18_raw_readl_noretry(cx, addr);
96}
97
98
99static inline
100u16 cx18_raw_readw_noretry(struct cx18 *cx, const void __iomem *addr)
49{ 101{
50 u16 ret = __raw_readw(addr); 102 u16 ret = __raw_readw(addr);
51 cx18_io_delay(cx); 103 cx18_io_delay(cx);
52 return ret; 104 return ret;
53} 105}
54 106
107u16 cx18_raw_readw_retry(struct cx18 *cx, const void __iomem *addr);
108
109static inline u16 cx18_raw_readw(struct cx18 *cx, const void __iomem *addr)
110{
111 if (cx18_retry_mmio)
112 return cx18_raw_readw_retry(cx, addr);
113
114 return cx18_raw_readw_noretry(cx, addr);
115}
116
117
55/* Normal memory mapped IO */ 118/* Normal memory mapped IO */
56static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr) 119static inline
120void cx18_writel_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
57{ 121{
58 writel(val, addr); 122 writel(val, addr);
59 cx18_io_delay(cx); 123 cx18_io_delay(cx);
60} 124}
61 125
62static inline void cx18_writew(struct cx18 *cx, u16 val, void __iomem *addr) 126void cx18_writel_retry(struct cx18 *cx, u32 val, void __iomem *addr);
127
128static inline void cx18_writel(struct cx18 *cx, u32 val, void __iomem *addr)
129{
130 if (cx18_retry_mmio)
131 cx18_writel_retry(cx, val, addr);
132 else
133 cx18_writel_noretry(cx, val, addr);
134}
135
136
137static inline
138void cx18_writew_noretry(struct cx18 *cx, u16 val, void __iomem *addr)
63{ 139{
64 writew(val, addr); 140 writew(val, addr);
65 cx18_io_delay(cx); 141 cx18_io_delay(cx);
66} 142}
67 143
68static inline void cx18_writeb(struct cx18 *cx, u8 val, void __iomem *addr) 144void cx18_writew_retry(struct cx18 *cx, u16 val, void __iomem *addr);
145
146static inline void cx18_writew(struct cx18 *cx, u16 val, void __iomem *addr)
147{
148 if (cx18_retry_mmio)
149 cx18_writew_retry(cx, val, addr);
150 else
151 cx18_writew_noretry(cx, val, addr);
152}
153
154
155static inline
156void cx18_writeb_noretry(struct cx18 *cx, u8 val, void __iomem *addr)
69{ 157{
70 writeb(val, addr); 158 writeb(val, addr);
71 cx18_io_delay(cx); 159 cx18_io_delay(cx);
72} 160}
73 161
74static inline u32 cx18_readl(struct cx18 *cx, const void __iomem *addr) 162void cx18_writeb_retry(struct cx18 *cx, u8 val, void __iomem *addr);
163
164static inline void cx18_writeb(struct cx18 *cx, u8 val, void __iomem *addr)
165{
166 if (cx18_retry_mmio)
167 cx18_writeb_retry(cx, val, addr);
168 else
169 cx18_writeb_noretry(cx, val, addr);
170}
171
172
173static inline u32 cx18_readl_noretry(struct cx18 *cx, const void __iomem *addr)
75{ 174{
76 u32 ret = readl(addr); 175 u32 ret = readl(addr);
77 cx18_io_delay(cx); 176 cx18_io_delay(cx);
78 return ret; 177 return ret;
79} 178}
80 179
81static inline u8 cx18_readb(struct cx18 *cx, const void __iomem *addr) 180u32 cx18_readl_retry(struct cx18 *cx, const void __iomem *addr);
181
182static inline u32 cx18_readl(struct cx18 *cx, const void __iomem *addr)
183{
184 if (cx18_retry_mmio)
185 return cx18_readl_retry(cx, addr);
186
187 return cx18_readl_noretry(cx, addr);
188}
189
190
191static inline u16 cx18_readw_noretry(struct cx18 *cx, const void __iomem *addr)
192{
193 u16 ret = readw(addr);
194 cx18_io_delay(cx);
195 return ret;
196}
197
198u16 cx18_readw_retry(struct cx18 *cx, const void __iomem *addr);
199
200static inline u16 cx18_readw(struct cx18 *cx, const void __iomem *addr)
201{
202 if (cx18_retry_mmio)
203 return cx18_readw_retry(cx, addr);
204
205 return cx18_readw_noretry(cx, addr);
206}
207
208
209static inline u8 cx18_readb_noretry(struct cx18 *cx, const void __iomem *addr)
82{ 210{
83 u8 ret = readb(addr); 211 u8 ret = readb(addr);
84 cx18_io_delay(cx); 212 cx18_io_delay(cx);
85 return ret; 213 return ret;
86} 214}
87 215
216u8 cx18_readb_retry(struct cx18 *cx, const void __iomem *addr);
217
218static inline u8 cx18_readb(struct cx18 *cx, const void __iomem *addr)
219{
220 if (cx18_retry_mmio)
221 return cx18_readb_retry(cx, addr);
222
223 return cx18_readb_noretry(cx, addr);
224}
225
226
227static inline
228u32 cx18_write_sync_noretry(struct cx18 *cx, u32 val, void __iomem *addr)
229{
230 cx18_writel_noretry(cx, val, addr);
231 return cx18_readl_noretry(cx, addr);
232}
233
234static inline
235u32 cx18_write_sync_retry(struct cx18 *cx, u32 val, void __iomem *addr)
236{
237 cx18_writel_retry(cx, val, addr);
238 return cx18_readl_retry(cx, addr);
239}
240
88static inline u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr) 241static inline u32 cx18_write_sync(struct cx18 *cx, u32 val, void __iomem *addr)
89{ 242{
90 cx18_writel(cx, val, addr); 243 if (cx18_retry_mmio)
91 return cx18_readl(cx, addr); 244 return cx18_write_sync_retry(cx, val, addr);
245
246 return cx18_write_sync_noretry(cx, val, addr);
92} 247}
93 248
249
94void cx18_memcpy_fromio(struct cx18 *cx, void *to, 250void cx18_memcpy_fromio(struct cx18 *cx, void *to,
95 const void __iomem *from, unsigned int len); 251 const void __iomem *from, unsigned int len);
96void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count); 252void cx18_memset_io(struct cx18 *cx, void __iomem *addr, int val, size_t count);
97 253
254
98/* Access "register" region of CX23418 memory mapped I/O */ 255/* Access "register" region of CX23418 memory mapped I/O */
256static inline void cx18_write_reg_noretry(struct cx18 *cx, u32 val, u32 reg)
257{
258 cx18_writel_noretry(cx, val, cx->reg_mem + reg);
259}
260
261static inline void cx18_write_reg_retry(struct cx18 *cx, u32 val, u32 reg)
262{
263 cx18_writel_retry(cx, val, cx->reg_mem + reg);
264}
265
99static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg) 266static inline void cx18_write_reg(struct cx18 *cx, u32 val, u32 reg)
100{ 267{
101 cx18_writel(cx, val, cx->reg_mem + reg); 268 if (cx18_retry_mmio)
269 cx18_write_reg_retry(cx, val, reg);
270 else
271 cx18_write_reg_noretry(cx, val, reg);
272}
273
274
275static inline u32 cx18_read_reg_noretry(struct cx18 *cx, u32 reg)
276{
277 return cx18_readl_noretry(cx, cx->reg_mem + reg);
278}
279
280static inline u32 cx18_read_reg_retry(struct cx18 *cx, u32 reg)
281{
282 return cx18_readl_retry(cx, cx->reg_mem + reg);
102} 283}
103 284
104static inline u32 cx18_read_reg(struct cx18 *cx, u32 reg) 285static inline u32 cx18_read_reg(struct cx18 *cx, u32 reg)
105{ 286{
106 return cx18_readl(cx, cx->reg_mem + reg); 287 if (cx18_retry_mmio)
288 return cx18_read_reg_retry(cx, reg);
289
290 return cx18_read_reg_noretry(cx, reg);
291}
292
293
294static inline u32 cx18_write_reg_sync_noretry(struct cx18 *cx, u32 val, u32 reg)
295{
296 return cx18_write_sync_noretry(cx, val, cx->reg_mem + reg);
297}
298
299static inline u32 cx18_write_reg_sync_retry(struct cx18 *cx, u32 val, u32 reg)
300{
301 return cx18_write_sync_retry(cx, val, cx->reg_mem + reg);
107} 302}
108 303
109static inline u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg) 304static inline u32 cx18_write_reg_sync(struct cx18 *cx, u32 val, u32 reg)
110{ 305{
111 return cx18_write_sync(cx, val, cx->reg_mem + reg); 306 if (cx18_retry_mmio)
307 return cx18_write_reg_sync_retry(cx, val, reg);
308
309 return cx18_write_reg_sync_noretry(cx, val, reg);
112} 310}
113 311
312
114/* Access "encoder memory" region of CX23418 memory mapped I/O */ 313/* Access "encoder memory" region of CX23418 memory mapped I/O */
314static inline void cx18_write_enc_noretry(struct cx18 *cx, u32 val, u32 addr)
315{
316 cx18_writel_noretry(cx, val, cx->enc_mem + addr);
317}
318
319static inline void cx18_write_enc_retry(struct cx18 *cx, u32 val, u32 addr)
320{
321 cx18_writel_retry(cx, val, cx->enc_mem + addr);
322}
323
115static inline void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr) 324static inline void cx18_write_enc(struct cx18 *cx, u32 val, u32 addr)
116{ 325{
117 cx18_writel(cx, val, cx->enc_mem + addr); 326 if (cx18_retry_mmio)
327 cx18_write_enc_retry(cx, val, addr);
328 else
329 cx18_write_enc_noretry(cx, val, addr);
330}
331
332
333static inline u32 cx18_read_enc_noretry(struct cx18 *cx, u32 addr)
334{
335 return cx18_readl_noretry(cx, cx->enc_mem + addr);
336}
337
338static inline u32 cx18_read_enc_retry(struct cx18 *cx, u32 addr)
339{
340 return cx18_readl_retry(cx, cx->enc_mem + addr);
118} 341}
119 342
120static inline u32 cx18_read_enc(struct cx18 *cx, u32 addr) 343static inline u32 cx18_read_enc(struct cx18 *cx, u32 addr)
121{ 344{
122 return cx18_readl(cx, cx->enc_mem + addr); 345 if (cx18_retry_mmio)
346 return cx18_read_enc_retry(cx, addr);
347
348 return cx18_read_enc_noretry(cx, addr);
349}
350
351static inline
352u32 cx18_write_enc_sync_noretry(struct cx18 *cx, u32 val, u32 addr)
353{
354 return cx18_write_sync_noretry(cx, val, cx->enc_mem + addr);
123} 355}
124 356
125static inline u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr) 357static inline
358u32 cx18_write_enc_sync_retry(struct cx18 *cx, u32 val, u32 addr)
126{ 359{
127 return cx18_write_sync(cx, val, cx->enc_mem + addr); 360 return cx18_write_sync_retry(cx, val, cx->enc_mem + addr);
128} 361}
129 362
363static inline
364u32 cx18_write_enc_sync(struct cx18 *cx, u32 val, u32 addr)
365{
366 if (cx18_retry_mmio)
367 return cx18_write_enc_sync_retry(cx, val, addr);
368
369 return cx18_write_enc_sync_noretry(cx, val, addr);
370}
130 371
131void cx18_sw1_irq_enable(struct cx18 *cx, u32 val); 372void cx18_sw1_irq_enable(struct cx18 *cx, u32 val);
132void cx18_sw1_irq_disable(struct cx18 *cx, u32 val); 373void cx18_sw1_irq_disable(struct cx18 *cx, u32 val);
@@ -134,7 +375,4 @@ void cx18_sw2_irq_enable(struct cx18 *cx, u32 val);
134void cx18_sw2_irq_disable(struct cx18 *cx, u32 val); 375void cx18_sw2_irq_disable(struct cx18 *cx, u32 val);
135void cx18_setup_page(struct cx18 *cx, u32 addr); 376void cx18_setup_page(struct cx18 *cx, u32 addr);
136 377
137/* Tries to recover from the CX23418 responding improperly on the PCI bus */
138int cx18_pci_try_recover(struct cx18 *cx);
139
140#endif /* CX18_IO_H */ 378#endif /* CX18_IO_H */
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index 4a47f61d948..83aa9cb02e0 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -752,6 +752,7 @@ static int cx18_log_status(struct file *file, void *fh)
752 CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n", 752 CX18_INFO("Read MPEG/VBI: %lld/%lld bytes\n",
753 (long long)cx->mpg_data_received, 753 (long long)cx->mpg_data_received,
754 (long long)cx->vbi_data_inserted); 754 (long long)cx->vbi_data_inserted);
755 cx18_log_statistics(cx);
755 CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num); 756 CX18_INFO("================== END STATUS CARD #%d ==================\n", cx->num);
756 return 0; 757 return 0;
757} 758}