···5353static struct chan_waitqueues {5454 wait_queue_head_t rt_queue;5555 wait_queue_head_t lx_queue;5656- int in_open;5656+ atomic_t in_open;5757} channel_wqs[RTLX_CHANNELS];58585959static struct irqaction irq;···148148{149149 volatile struct rtlx_info **p;150150 struct rtlx_channel *chan;151151+ enum rtlx_state state;151152 int ret = 0;152153153154 if (index >= RTLX_CHANNELS) {···156155 return -ENOSYS;157156 }158157159159- if (channel_wqs[index].in_open) {160160- printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index);161161- return -EBUSY;158158+ if (atomic_inc_return(&channel_wqs[index].in_open) > 1) {159159+ printk(KERN_DEBUG "rtlx_open channel %d already opened\n",160160+ index);161161+ ret = -EBUSY;162162+ goto out_fail;162163 }163163-164164- channel_wqs[index].in_open++;165164166165 if (rtlx == NULL) {167166 if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {···174173 if (ret)175174 goto out_fail;176175 } else {177177- printk( KERN_DEBUG "No SP program loaded, and device "176176+ printk(KERN_DEBUG "No SP program loaded, and device "178177 "opened with O_NONBLOCK\n");179179- channel_wqs[index].in_open = 0;180178 ret = -ENOSYS;181179 goto out_fail;182180 }···193193 } else {194194 printk(" *vpe_get_shared is NULL. "195195 "Has an SP program been loaded?\n");196196- channel_wqs[index].in_open = 0;197196 ret = -ENOSYS;198197 goto out_fail;199198 }···201202 if ((unsigned int)*p < KSEG0) {202203 printk(KERN_WARNING "vpe_get_shared returned an invalid pointer "203204 "maybe an error code %d\n", (int)*p);204204- channel_wqs[index].in_open = 0;205205 ret = -ENOSYS;206206 goto out_fail;207207 }208208209209- if ((ret = rtlx_init(*p)) < 0) {210210- channel_wqs[index].in_open = 0;211211- return ret;212212- }209209+ if ((ret = rtlx_init(*p)) < 0)210210+ goto out_ret;213211 }214212215213 chan = &rtlx->channel[index];216214217217- if (chan->lx_state == RTLX_STATE_OPENED) {218218- channel_wqs[index].in_open = 0;219219- return -EBUSY;220220- }221221-222222- chan->lx_state = RTLX_STATE_OPENED;223223- channel_wqs[index].in_open = 0;224224- return 0;215215+ state = xchg(&chan->lx_state, RTLX_STATE_OPENED);216216+ if (state == RTLX_STATE_OPENED) {217217+ ret = -EBUSY;218218+ goto out_fail;219219+ }225220226221out_fail:227227- channel_wqs[index].in_open--;222222+ smp_mb();223223+ atomic_dec(&channel_wqs[index].in_open);224224+ smp_mb();228225226226+out_ret:229227 return ret;230228}231229···471475 for (i = 0; i < RTLX_CHANNELS; i++) {472476 init_waitqueue_head(&channel_wqs[i].rt_queue);473477 init_waitqueue_head(&channel_wqs[i].lx_queue);474474- channel_wqs[i].in_open = 0;478478+ atomic_set(&channel_wqs[i].in_open, 0);475479476480 dev = device_create(mt_class, NULL, MKDEV(major, i),477481 "%s%d", module_name, i);
+3-4
arch/mips/kernel/vpe.c
···10791079static int vpe_open(struct inode *inode, struct file *filp)10801080{10811081 int minor, ret;10821082+ enum vpe_state state;10821083 struct vpe *v;10831084 struct vpe_notifications *not;10841085···10941093 return -ENODEV;10951094 }1096109510971097- if (v->state != VPE_STATE_UNUSED) {10961096+ state = xchg(&v->state, VPE_STATE_INUSE);10971097+ if (state != VPE_STATE_UNUSED) {10981098 dvpe();1099109911001100 printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n");···11091107 release_progmem(v->load_addr);11101108 cleanup_tc(get_tc(minor));11111109 }11121112-11131113- // allocate it so when we get write ops we know it's expected.11141114- v->state = VPE_STATE_INUSE;1115111011161111 /* this of-course trashes what was there before... */11171112 v->pbuffer = vmalloc(P_SIZE);