diff options
| -rw-r--r-- | arch/mips/kernel/rtlx.c | 44 | ||||
| -rw-r--r-- | arch/mips/kernel/vpe.c | 7 |
2 files changed, 23 insertions, 28 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"; | |||
| 53 | static struct chan_waitqueues { | 53 | static 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 | ||
| 59 | static struct irqaction irq; | 59 | static 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 | ||
| 227 | out_fail: | 220 | out_fail: |
| 228 | channel_wqs[index].in_open--; | 221 | smp_mb(); |
| 222 | atomic_dec(&channel_wqs[index].in_open); | ||
| 223 | smp_mb(); | ||
| 229 | 224 | ||
| 225 | out_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); |
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 9aca871a307f..c9ee9d2d5856 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c | |||
| @@ -1079,6 +1079,7 @@ static int getcwd(char *buff, int size) | |||
| 1079 | static int vpe_open(struct inode *inode, struct file *filp) | 1079 | static int vpe_open(struct inode *inode, struct file *filp) |
| 1080 | { | 1080 | { |
| 1081 | int minor, ret; | 1081 | int minor, ret; |
| 1082 | enum vpe_state state; | ||
| 1082 | struct vpe *v; | 1083 | struct vpe *v; |
| 1083 | struct vpe_notifications *not; | 1084 | struct vpe_notifications *not; |
| 1084 | 1085 | ||
| @@ -1093,7 +1094,8 @@ static int vpe_open(struct inode *inode, struct file *filp) | |||
| 1093 | return -ENODEV; | 1094 | return -ENODEV; |
| 1094 | } | 1095 | } |
| 1095 | 1096 | ||
| 1096 | if (v->state != VPE_STATE_UNUSED) { | 1097 | state = xchg(&v->state, VPE_STATE_INUSE); |
| 1098 | if (state != VPE_STATE_UNUSED) { | ||
| 1097 | dvpe(); | 1099 | dvpe(); |
| 1098 | 1100 | ||
| 1099 | printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n"); | 1101 | printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n"); |
| @@ -1108,9 +1110,6 @@ static int vpe_open(struct inode *inode, struct file *filp) | |||
| 1108 | cleanup_tc(get_tc(minor)); | 1110 | cleanup_tc(get_tc(minor)); |
| 1109 | } | 1111 | } |
| 1110 | 1112 | ||
| 1111 | // allocate it so when we get write ops we know it's expected. | ||
| 1112 | v->state = VPE_STATE_INUSE; | ||
| 1113 | |||
| 1114 | /* this of-course trashes what was there before... */ | 1113 | /* this of-course trashes what was there before... */ |
| 1115 | v->pbuffer = vmalloc(P_SIZE); | 1114 | v->pbuffer = vmalloc(P_SIZE); |
| 1116 | v->plen = P_SIZE; | 1115 | v->plen = P_SIZE; |
