aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/rtlx.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/rtlx.c')
-rw-r--r--arch/mips/kernel/rtlx.c44
1 files changed, 20 insertions, 24 deletions
diff --git a/arch/mips/kernel/rtlx.c b/arch/mips/kernel/rtlx.c
index 766db51ab69e..7a8683ab6fde 100644
--- a/arch/mips/kernel/rtlx.c
+++ b/arch/mips/kernel/rtlx.c
@@ -53,7 +53,7 @@ static char module_name[] = "rtlx";
53static struct chan_waitqueues { 53static struct chan_waitqueues {
54 wait_queue_head_t rt_queue; 54 wait_queue_head_t rt_queue;
55 wait_queue_head_t lx_queue; 55 wait_queue_head_t lx_queue;
56 int in_open; 56 atomic_t in_open;
57} channel_wqs[RTLX_CHANNELS]; 57} channel_wqs[RTLX_CHANNELS];
58 58
59static struct irqaction irq; 59static struct irqaction irq;
@@ -148,6 +148,7 @@ int rtlx_open(int index, int can_sleep)
148{ 148{
149 volatile struct rtlx_info **p; 149 volatile struct rtlx_info **p;
150 struct rtlx_channel *chan; 150 struct rtlx_channel *chan;
151 enum rtlx_state state;
151 int ret = 0; 152 int ret = 0;
152 153
153 if (index >= RTLX_CHANNELS) { 154 if (index >= RTLX_CHANNELS) {
@@ -155,13 +156,13 @@ int rtlx_open(int index, int can_sleep)
155 return -ENOSYS; 156 return -ENOSYS;
156 } 157 }
157 158
158 if (channel_wqs[index].in_open) { 159 if (atomic_inc_return(&channel_wqs[index].in_open) > 1) {
159 printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index); 160 printk(KERN_DEBUG "rtlx_open channel %d already opened\n",
160 return -EBUSY; 161 index);
162 ret = -EBUSY;
163 goto out_fail;
161 } 164 }
162 165
163 channel_wqs[index].in_open++;
164
165 if (rtlx == NULL) { 166 if (rtlx == NULL) {
166 if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { 167 if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
167 if (can_sleep) { 168 if (can_sleep) {
@@ -173,9 +174,8 @@ int rtlx_open(int index, int can_sleep)
173 if (ret) 174 if (ret)
174 goto out_fail; 175 goto out_fail;
175 } else { 176 } else {
176 printk( KERN_DEBUG "No SP program loaded, and device " 177 printk(KERN_DEBUG "No SP program loaded, and device "
177 "opened with O_NONBLOCK\n"); 178 "opened with O_NONBLOCK\n");
178 channel_wqs[index].in_open = 0;
179 ret = -ENOSYS; 179 ret = -ENOSYS;
180 goto out_fail; 180 goto out_fail;
181 } 181 }
@@ -193,7 +193,6 @@ int rtlx_open(int index, int can_sleep)
193 } else { 193 } else {
194 printk(" *vpe_get_shared is NULL. " 194 printk(" *vpe_get_shared is NULL. "
195 "Has an SP program been loaded?\n"); 195 "Has an SP program been loaded?\n");
196 channel_wqs[index].in_open = 0;
197 ret = -ENOSYS; 196 ret = -ENOSYS;
198 goto out_fail; 197 goto out_fail;
199 } 198 }
@@ -202,31 +201,28 @@ int rtlx_open(int index, int can_sleep)
202 if ((unsigned int)*p < KSEG0) { 201 if ((unsigned int)*p < KSEG0) {
203 printk(KERN_WARNING "vpe_get_shared returned an invalid pointer " 202 printk(KERN_WARNING "vpe_get_shared returned an invalid pointer "
204 "maybe an error code %d\n", (int)*p); 203 "maybe an error code %d\n", (int)*p);
205 channel_wqs[index].in_open = 0;
206 ret = -ENOSYS; 204 ret = -ENOSYS;
207 goto out_fail; 205 goto out_fail;
208 } 206 }
209 207
210 if ((ret = rtlx_init(*p)) < 0) { 208 if ((ret = rtlx_init(*p)) < 0)
211 channel_wqs[index].in_open = 0; 209 goto out_ret;
212 return ret;
213 }
214 } 210 }
215 211
216 chan = &rtlx->channel[index]; 212 chan = &rtlx->channel[index];
217 213
218 if (chan->lx_state == RTLX_STATE_OPENED) { 214 state = xchg(&chan->lx_state, RTLX_STATE_OPENED);
219 channel_wqs[index].in_open = 0; 215 if (state == RTLX_STATE_OPENED) {
220 return -EBUSY; 216 ret = -EBUSY;
221 } 217 goto out_fail;
222 218 }
223 chan->lx_state = RTLX_STATE_OPENED;
224 channel_wqs[index].in_open = 0;
225 return 0;
226 219
227out_fail: 220out_fail:
228 channel_wqs[index].in_open--; 221 smp_mb();
222 atomic_dec(&channel_wqs[index].in_open);
223 smp_mb();
229 224
225out_ret:
230 return ret; 226 return ret;
231} 227}
232 228
@@ -475,7 +471,7 @@ static int rtlx_module_init(void)
475 for (i = 0; i < RTLX_CHANNELS; i++) { 471 for (i = 0; i < RTLX_CHANNELS; i++) {
476 init_waitqueue_head(&channel_wqs[i].rt_queue); 472 init_waitqueue_head(&channel_wqs[i].rt_queue);
477 init_waitqueue_head(&channel_wqs[i].lx_queue); 473 init_waitqueue_head(&channel_wqs[i].lx_queue);
478 channel_wqs[i].in_open = 0; 474 atomic_set(&channel_wqs[i].in_open, 0);
479 475
480 dev = device_create(mt_class, NULL, MKDEV(major, i), 476 dev = device_create(mt_class, NULL, MKDEV(major, i),
481 "%s%d", module_name, i); 477 "%s%d", module_name, i);