Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

[MIPS] RTLX, VPE: Make open actually atomic.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

+23 -28
+20 -24
arch/mips/kernel/rtlx.c
··· 53 53 static struct chan_waitqueues { 54 54 wait_queue_head_t rt_queue; 55 55 wait_queue_head_t lx_queue; 56 - int in_open; 56 + atomic_t in_open; 57 57 } channel_wqs[RTLX_CHANNELS]; 58 58 59 59 static struct irqaction irq; ··· 148 148 { 149 149 volatile struct rtlx_info **p; 150 150 struct rtlx_channel *chan; 151 + enum rtlx_state state; 151 152 int ret = 0; 152 153 153 154 if (index >= RTLX_CHANNELS) { ··· 156 155 return -ENOSYS; 157 156 } 158 157 159 - if (channel_wqs[index].in_open) { 160 - printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index); 161 - return -EBUSY; 158 + if (atomic_inc_return(&channel_wqs[index].in_open) > 1) { 159 + printk(KERN_DEBUG "rtlx_open channel %d already opened\n", 160 + index); 161 + ret = -EBUSY; 162 + goto out_fail; 162 163 } 163 - 164 - channel_wqs[index].in_open++; 165 164 166 165 if (rtlx == NULL) { 167 166 if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) { ··· 174 173 if (ret) 175 174 goto out_fail; 176 175 } else { 177 - printk( KERN_DEBUG "No SP program loaded, and device " 176 + printk(KERN_DEBUG "No SP program loaded, and device " 178 177 "opened with O_NONBLOCK\n"); 179 - channel_wqs[index].in_open = 0; 180 178 ret = -ENOSYS; 181 179 goto out_fail; 182 180 } ··· 193 193 } else { 194 194 printk(" *vpe_get_shared is NULL. " 195 195 "Has an SP program been loaded?\n"); 196 - channel_wqs[index].in_open = 0; 197 196 ret = -ENOSYS; 198 197 goto out_fail; 199 198 } ··· 201 202 if ((unsigned int)*p < KSEG0) { 202 203 printk(KERN_WARNING "vpe_get_shared returned an invalid pointer " 203 204 "maybe an error code %d\n", (int)*p); 204 - channel_wqs[index].in_open = 0; 205 205 ret = -ENOSYS; 206 206 goto out_fail; 207 207 } 208 208 209 - if ((ret = rtlx_init(*p)) < 0) { 210 - channel_wqs[index].in_open = 0; 211 - return ret; 212 - } 209 + if ((ret = rtlx_init(*p)) < 0) 210 + goto out_ret; 213 211 } 214 212 215 213 chan = &rtlx->channel[index]; 216 214 217 - if (chan->lx_state == RTLX_STATE_OPENED) { 218 - channel_wqs[index].in_open = 0; 219 - return -EBUSY; 220 - } 221 - 222 - chan->lx_state = RTLX_STATE_OPENED; 223 - channel_wqs[index].in_open = 0; 224 - return 0; 215 + state = xchg(&chan->lx_state, RTLX_STATE_OPENED); 216 + if (state == RTLX_STATE_OPENED) { 217 + ret = -EBUSY; 218 + goto out_fail; 219 + } 225 220 226 221 out_fail: 227 - channel_wqs[index].in_open--; 222 + smp_mb(); 223 + atomic_dec(&channel_wqs[index].in_open); 224 + smp_mb(); 228 225 226 + out_ret: 229 227 return ret; 230 228 } 231 229 ··· 471 475 for (i = 0; i < RTLX_CHANNELS; i++) { 472 476 init_waitqueue_head(&channel_wqs[i].rt_queue); 473 477 init_waitqueue_head(&channel_wqs[i].lx_queue); 474 - channel_wqs[i].in_open = 0; 478 + atomic_set(&channel_wqs[i].in_open, 0); 475 479 476 480 dev = device_create(mt_class, NULL, MKDEV(major, i), 477 481 "%s%d", module_name, i);
+3 -4
arch/mips/kernel/vpe.c
··· 1079 1079 static int vpe_open(struct inode *inode, struct file *filp) 1080 1080 { 1081 1081 int minor, ret; 1082 + enum vpe_state state; 1082 1083 struct vpe *v; 1083 1084 struct vpe_notifications *not; 1084 1085 ··· 1094 1093 return -ENODEV; 1095 1094 } 1096 1095 1097 - if (v->state != VPE_STATE_UNUSED) { 1096 + state = xchg(&v->state, VPE_STATE_INUSE); 1097 + if (state != VPE_STATE_UNUSED) { 1098 1098 dvpe(); 1099 1099 1100 1100 printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n"); ··· 1109 1107 release_progmem(v->load_addr); 1110 1108 cleanup_tc(get_tc(minor)); 1111 1109 } 1112 - 1113 - // allocate it so when we get write ops we know it's expected. 1114 - v->state = VPE_STATE_INUSE; 1115 1110 1116 1111 /* this of-course trashes what was there before... */ 1117 1112 v->pbuffer = vmalloc(P_SIZE);