aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18/cx18-mailbox.c
diff options
context:
space:
mode:
authorAndy Walls <awalls@radix.net>2008-11-05 23:15:41 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-12-30 06:38:02 -0500
commit72c2d6d3ac91d1b9efb482ff4a8dd68e3d867965 (patch)
tree0e80f865ac4763e30eb7777360fbf3d860b140f0 /drivers/media/video/cx18/cx18-mailbox.c
parentf68d0cf56761128e85ebc98d8de4776b89c30279 (diff)
V4L/DVB (9593): cx18: Add outgoing mailbox mutexes and check for ack via waitq vs poll
Add mutexes to ensure exclusive access for outgoing driver to CX23418 mailboxes. Also wait on a waitq for mailbox acknowledgement from the CX23418 instead of polling. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18/cx18-mailbox.c')
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c84
1 files changed, 41 insertions, 43 deletions
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index acff7dfb60df..d2975a2e6cb7 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -30,11 +30,6 @@
30#define API_FAST (1 << 2) /* Short timeout */ 30#define API_FAST (1 << 2) /* Short timeout */
31#define API_SLOW (1 << 3) /* Additional 300ms timeout */ 31#define API_SLOW (1 << 3) /* Additional 300ms timeout */
32 32
33#define APU 0
34#define CPU 1
35#define EPU 2
36#define HPU 3
37
38struct cx18_api_info { 33struct cx18_api_info {
39 u32 cmd; 34 u32 cmd;
40 u8 flags; /* Flags, see above */ 35 u8 flags; /* Flags, see above */
@@ -117,10 +112,7 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu
117 *irq = cx18_readl(cx, &cx->scb->epu2cpu_irq); 112 *irq = cx18_readl(cx, &cx->scb->epu2cpu_irq);
118 break; 113 break;
119 114
120 case HPU: 115 default:
121 mb = &cx->scb->epu2hpu_mb;
122 *state = cx18_readl(cx, &cx->scb->hpu_state);
123 *irq = cx18_readl(cx, &cx->scb->epu2hpu_irq);
124 break; 116 break;
125 } 117 }
126 118
@@ -142,25 +134,12 @@ static struct cx18_mailbox __iomem *cx18_mb_is_complete(struct cx18 *cx, int rpu
142 return NULL; 134 return NULL;
143} 135}
144 136
145long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb) 137long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb, int rpu)
146{ 138{
147 const struct cx18_api_info *info = find_api_info(mb->cmd);
148 struct cx18_mailbox __iomem *ack_mb; 139 struct cx18_mailbox __iomem *ack_mb;
149 u32 ack_irq; 140 u32 ack_irq;
150 u8 rpu = CPU;
151
152 if (info == NULL && mb->cmd) {
153 CX18_WARN("Cannot ack unknown command %x\n", mb->cmd);
154 return -EINVAL;
155 }
156 if (info)
157 rpu = info->rpu;
158 141
159 switch (rpu) { 142 switch (rpu) {
160 case HPU:
161 ack_irq = IRQ_EPU_TO_HPU_ACK;
162 ack_mb = &cx->scb->hpu2epu_mb;
163 break;
164 case APU: 143 case APU:
165 ack_irq = IRQ_EPU_TO_APU_ACK; 144 ack_irq = IRQ_EPU_TO_APU_ACK;
166 ack_mb = &cx->scb->apu2epu_mb; 145 ack_mb = &cx->scb->apu2epu_mb;
@@ -170,7 +149,8 @@ long cx18_mb_ack(struct cx18 *cx, const struct cx18_mailbox *mb)
170 ack_mb = &cx->scb->cpu2epu_mb; 149 ack_mb = &cx->scb->cpu2epu_mb;
171 break; 150 break;
172 default: 151 default:
173 CX18_WARN("Unknown RPU for command %x\n", mb->cmd); 152 CX18_WARN("Unhandled RPU (%d) for command %x ack\n",
153 rpu, mb->cmd);
174 return -EINVAL; 154 return -EINVAL;
175 } 155 }
176 156
@@ -187,8 +167,8 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
187 u32 state = 0, irq = 0, req, oldreq, err; 167 u32 state = 0, irq = 0, req, oldreq, err;
188 struct cx18_mailbox __iomem *mb; 168 struct cx18_mailbox __iomem *mb;
189 wait_queue_head_t *waitq; 169 wait_queue_head_t *waitq;
170 struct mutex *mb_lock;
190 int timeout = 100; 171 int timeout = 100;
191 int cnt = 0;
192 int sig = 0; 172 int sig = 0;
193 int i; 173 int i;
194 174
@@ -201,10 +181,27 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
201 CX18_DEBUG_HI_API("%s\n", info->name); 181 CX18_DEBUG_HI_API("%s\n", info->name);
202 else 182 else
203 CX18_DEBUG_API("%s\n", info->name); 183 CX18_DEBUG_API("%s\n", info->name);
184
185 switch (info->rpu) {
186 case APU:
187 waitq = &cx->mb_apu_waitq;
188 mb_lock = &cx->epu2apu_mb_lock;
189 break;
190 case CPU:
191 waitq = &cx->mb_cpu_waitq;
192 mb_lock = &cx->epu2cpu_mb_lock;
193 break;
194 default:
195 CX18_WARN("Unknown RPU (%d) for API call\n", info->rpu);
196 return -EINVAL;
197 }
198
199 mutex_lock(mb_lock);
204 cx18_setup_page(cx, SCB_OFFSET); 200 cx18_setup_page(cx, SCB_OFFSET);
205 mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req); 201 mb = cx18_mb_is_complete(cx, info->rpu, &state, &irq, &req);
206 202
207 if (mb == NULL) { 203 if (mb == NULL) {
204 mutex_unlock(mb_lock);
208 CX18_ERR("mb %s busy\n", info->name); 205 CX18_ERR("mb %s busy\n", info->name);
209 return -EBUSY; 206 return -EBUSY;
210 } 207 }
@@ -216,34 +213,35 @@ static int cx18_api_call(struct cx18 *cx, u32 cmd, int args, u32 data[])
216 cx18_writel(cx, 0, &mb->error); 213 cx18_writel(cx, 0, &mb->error);
217 cx18_writel(cx, req, &mb->request); 214 cx18_writel(cx, req, &mb->request);
218 215
219 switch (info->rpu) {
220 case APU: waitq = &cx->mb_apu_waitq; break;
221 case CPU: waitq = &cx->mb_cpu_waitq; break;
222 case EPU: waitq = &cx->mb_epu_waitq; break;
223 case HPU: waitq = &cx->mb_hpu_waitq; break;
224 default: return -EINVAL;
225 }
226 if (info->flags & API_FAST) 216 if (info->flags & API_FAST)
227 timeout /= 2; 217 timeout /= 2;
228 cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq); 218 cx18_write_reg_expect(cx, irq, SW1_INT_SET, irq, irq);
229 219
230 while (!sig && cx18_readl(cx, &mb->ack) != cx18_readl(cx, &mb->request) 220 sig = wait_event_interruptible_timeout(
231 && cnt < 660) { 221 *waitq,
232 if (cnt > 200 && !in_atomic()) 222 cx18_readl(cx, &mb->ack) == cx18_readl(cx, &mb->request),
233 sig = cx18_msleep_timeout(10, 1); 223 msecs_to_jiffies(timeout));
234 cnt++; 224 if (sig == 0) {
235 } 225 /* Timed out */
236 if (sig)
237 return -EINTR;
238 if (cnt == 660) {
239 cx18_writel(cx, oldreq, &mb->request); 226 cx18_writel(cx, oldreq, &mb->request);
240 CX18_ERR("mb %s failed\n", info->name); 227 mutex_unlock(mb_lock);
228 CX18_ERR("sending %s timed out waiting for RPU to respond\n",
229 info->name);
241 return -EINVAL; 230 return -EINVAL;
231 } else if (sig < 0) {
232 /* Interrupted */
233 cx18_writel(cx, oldreq, &mb->request);
234 mutex_unlock(mb_lock);
235 CX18_WARN("sending %s interrupted waiting for RPU to respond\n",
236 info->name);
237 return -EINTR;
242 } 238 }
239
243 for (i = 0; i < MAX_MB_ARGUMENTS; i++) 240 for (i = 0; i < MAX_MB_ARGUMENTS; i++)
244 data[i] = cx18_readl(cx, &mb->args[i]); 241 data[i] = cx18_readl(cx, &mb->args[i]);
245 err = cx18_readl(cx, &mb->error); 242 err = cx18_readl(cx, &mb->error);
246 if (!in_atomic() && (info->flags & API_SLOW)) 243 mutex_unlock(mb_lock);
244 if (info->flags & API_SLOW)
247 cx18_msleep_timeout(300, 0); 245 cx18_msleep_timeout(300, 0);
248 if (err) 246 if (err)
249 CX18_DEBUG_API("mailbox error %08x for command %s\n", err, 247 CX18_DEBUG_API("mailbox error %08x for command %s\n", err,