diff options
Diffstat (limited to 'arch/mips/kernel/rtlx.c')
-rw-r--r-- | arch/mips/kernel/rtlx.c | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c index 0233798f7155..b88f1c18ff4d 100644 --- a/arch/mips/kernel/rtlx.c +++ b/arch/mips/kernel/rtlx.c | |||
@@ -72,6 +72,15 @@ static void rtlx_dispatch(void) | |||
72 | static irqreturn_t rtlx_interrupt(int irq, void *dev_id) | 72 | static irqreturn_t rtlx_interrupt(int irq, void *dev_id) |
73 | { | 73 | { |
74 | int i; | 74 | int i; |
75 | unsigned int flags, vpeflags; | ||
76 | |||
77 | /* Ought not to be strictly necessary for SMTC builds */ | ||
78 | local_irq_save(flags); | ||
79 | vpeflags = dvpe(); | ||
80 | set_c0_status(0x100 << MIPS_CPU_RTLX_IRQ); | ||
81 | irq_enable_hazard(); | ||
82 | evpe(vpeflags); | ||
83 | local_irq_restore(flags); | ||
75 | 84 | ||
76 | for (i = 0; i < RTLX_CHANNELS; i++) { | 85 | for (i = 0; i < RTLX_CHANNELS; i++) { |
77 | wake_up(&channel_wqs[i].lx_queue); | 86 | wake_up(&channel_wqs[i].lx_queue); |
@@ -108,7 +117,8 @@ static void __used dump_rtlx(void) | |||
108 | static int rtlx_init(struct rtlx_info *rtlxi) | 117 | static int rtlx_init(struct rtlx_info *rtlxi) |
109 | { | 118 | { |
110 | if (rtlxi->id != RTLX_ID) { | 119 | if (rtlxi->id != RTLX_ID) { |
111 | printk(KERN_ERR "no valid RTLX id at 0x%p 0x%lx\n", rtlxi, rtlxi->id); | 120 | printk(KERN_ERR "no valid RTLX id at 0x%p 0x%lx\n", |
121 | rtlxi, rtlxi->id); | ||
112 | return -ENOEXEC; | 122 | return -ENOEXEC; |
113 | } | 123 | } |
114 | 124 | ||
@@ -162,18 +172,17 @@ int rtlx_open(int index, int can_sleep) | |||
162 | 172 | ||
163 | if (rtlx == NULL) { | 173 | if (rtlx == NULL) { |
164 | if( (p = vpe_get_shared(tclimit)) == NULL) { | 174 | if( (p = vpe_get_shared(tclimit)) == NULL) { |
165 | if (can_sleep) { | 175 | if (can_sleep) { |
166 | __wait_event_interruptible(channel_wqs[index].lx_queue, | 176 | __wait_event_interruptible(channel_wqs[index].lx_queue, |
167 | (p = vpe_get_shared(tclimit)), | 177 | (p = vpe_get_shared(tclimit)), ret); |
168 | ret); | 178 | if (ret) |
169 | if (ret) | ||
170 | goto out_fail; | ||
171 | } else { | ||
172 | printk(KERN_DEBUG "No SP program loaded, and device " | ||
173 | "opened with O_NONBLOCK\n"); | ||
174 | ret = -ENOSYS; | ||
175 | goto out_fail; | 179 | goto out_fail; |
176 | } | 180 | } else { |
181 | printk(KERN_DEBUG "No SP program loaded, and device " | ||
182 | "opened with O_NONBLOCK\n"); | ||
183 | ret = -ENOSYS; | ||
184 | goto out_fail; | ||
185 | } | ||
177 | } | 186 | } |
178 | 187 | ||
179 | smp_rmb(); | 188 | smp_rmb(); |
@@ -182,7 +191,9 @@ int rtlx_open(int index, int can_sleep) | |||
182 | DEFINE_WAIT(wait); | 191 | DEFINE_WAIT(wait); |
183 | 192 | ||
184 | for (;;) { | 193 | for (;;) { |
185 | prepare_to_wait(&channel_wqs[index].lx_queue, &wait, TASK_INTERRUPTIBLE); | 194 | prepare_to_wait( |
195 | &channel_wqs[index].lx_queue, | ||
196 | &wait, TASK_INTERRUPTIBLE); | ||
186 | smp_rmb(); | 197 | smp_rmb(); |
187 | if (*p != NULL) | 198 | if (*p != NULL) |
188 | break; | 199 | break; |
@@ -195,7 +206,7 @@ int rtlx_open(int index, int can_sleep) | |||
195 | } | 206 | } |
196 | finish_wait(&channel_wqs[index].lx_queue, &wait); | 207 | finish_wait(&channel_wqs[index].lx_queue, &wait); |
197 | } else { | 208 | } else { |
198 | printk(" *vpe_get_shared is NULL. " | 209 | pr_err(" *vpe_get_shared is NULL. " |
199 | "Has an SP program been loaded?\n"); | 210 | "Has an SP program been loaded?\n"); |
200 | ret = -ENOSYS; | 211 | ret = -ENOSYS; |
201 | goto out_fail; | 212 | goto out_fail; |
@@ -203,8 +214,9 @@ int rtlx_open(int index, int can_sleep) | |||
203 | } | 214 | } |
204 | 215 | ||
205 | if ((unsigned int)*p < KSEG0) { | 216 | if ((unsigned int)*p < KSEG0) { |
206 | printk(KERN_WARNING "vpe_get_shared returned an invalid pointer " | 217 | printk(KERN_WARNING "vpe_get_shared returned an " |
207 | "maybe an error code %d\n", (int)*p); | 218 | "invalid pointer maybe an error code %d\n", |
219 | (int)*p); | ||
208 | ret = -ENOSYS; | 220 | ret = -ENOSYS; |
209 | goto out_fail; | 221 | goto out_fail; |
210 | } | 222 | } |
@@ -232,6 +244,10 @@ out_ret: | |||
232 | 244 | ||
233 | int rtlx_release(int index) | 245 | int rtlx_release(int index) |
234 | { | 246 | { |
247 | if (rtlx == NULL) { | ||
248 | pr_err("rtlx_release() with null rtlx\n"); | ||
249 | return 0; | ||
250 | } | ||
235 | rtlx->channel[index].lx_state = RTLX_STATE_UNUSED; | 251 | rtlx->channel[index].lx_state = RTLX_STATE_UNUSED; |
236 | return 0; | 252 | return 0; |
237 | } | 253 | } |
@@ -251,8 +267,8 @@ unsigned int rtlx_read_poll(int index, int can_sleep) | |||
251 | int ret = 0; | 267 | int ret = 0; |
252 | 268 | ||
253 | __wait_event_interruptible(channel_wqs[index].lx_queue, | 269 | __wait_event_interruptible(channel_wqs[index].lx_queue, |
254 | chan->lx_read != chan->lx_write || sp_stopping, | 270 | (chan->lx_read != chan->lx_write) || |
255 | ret); | 271 | sp_stopping, ret); |
256 | if (ret) | 272 | if (ret) |
257 | return ret; | 273 | return ret; |
258 | 274 | ||
@@ -282,7 +298,9 @@ static inline int write_spacefree(int read, int write, int size) | |||
282 | unsigned int rtlx_write_poll(int index) | 298 | unsigned int rtlx_write_poll(int index) |
283 | { | 299 | { |
284 | struct rtlx_channel *chan = &rtlx->channel[index]; | 300 | struct rtlx_channel *chan = &rtlx->channel[index]; |
285 | return write_spacefree(chan->rt_read, chan->rt_write, chan->buffer_size); | 301 | |
302 | return write_spacefree(chan->rt_read, chan->rt_write, | ||
303 | chan->buffer_size); | ||
286 | } | 304 | } |
287 | 305 | ||
288 | ssize_t rtlx_read(int index, void __user *buff, size_t count) | 306 | ssize_t rtlx_read(int index, void __user *buff, size_t count) |
@@ -344,8 +362,8 @@ ssize_t rtlx_write(int index, const void __user *buffer, size_t count) | |||
344 | rt_read = rt->rt_read; | 362 | rt_read = rt->rt_read; |
345 | 363 | ||
346 | /* total number of bytes to copy */ | 364 | /* total number of bytes to copy */ |
347 | count = min(count, | 365 | count = min(count, (size_t)write_spacefree(rt_read, rt->rt_write, |
348 | (size_t)write_spacefree(rt_read, rt->rt_write, rt->buffer_size)); | 366 | rt->buffer_size)); |
349 | 367 | ||
350 | /* first bit from write pointer to the end of the buffer, or count */ | 368 | /* first bit from write pointer to the end of the buffer, or count */ |
351 | fl = min(count, (size_t) rt->buffer_size - rt->rt_write); | 369 | fl = min(count, (size_t) rt->buffer_size - rt->rt_write); |
@@ -514,6 +532,11 @@ static int __init rtlx_module_init(void) | |||
514 | 532 | ||
515 | if (cpu_has_vint) | 533 | if (cpu_has_vint) |
516 | set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch); | 534 | set_vi_handler(MIPS_CPU_RTLX_IRQ, rtlx_dispatch); |
535 | else { | ||
536 | pr_err("APRP RTLX init on non-vectored-interrupt processor\n"); | ||
537 | err = -ENODEV; | ||
538 | goto out_chrdev; | ||
539 | } | ||
517 | 540 | ||
518 | rtlx_irq.dev_id = rtlx; | 541 | rtlx_irq.dev_id = rtlx; |
519 | setup_irq(rtlx_irq_num, &rtlx_irq); | 542 | setup_irq(rtlx_irq_num, &rtlx_irq); |