[MIPS] RTLX, VPE: Make open actually atomic.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
parent
cbc8413567
commit
c4c4018b04
|
@ -53,7 +53,7 @@ static char module_name[] = "rtlx";
|
||||||
static struct chan_waitqueues {
|
static struct chan_waitqueues {
|
||||||
wait_queue_head_t rt_queue;
|
wait_queue_head_t rt_queue;
|
||||||
wait_queue_head_t lx_queue;
|
wait_queue_head_t lx_queue;
|
||||||
int in_open;
|
atomic_t in_open;
|
||||||
} channel_wqs[RTLX_CHANNELS];
|
} channel_wqs[RTLX_CHANNELS];
|
||||||
|
|
||||||
static struct irqaction irq;
|
static struct irqaction irq;
|
||||||
|
@ -148,6 +148,7 @@ int rtlx_open(int index, int can_sleep)
|
||||||
{
|
{
|
||||||
volatile struct rtlx_info **p;
|
volatile struct rtlx_info **p;
|
||||||
struct rtlx_channel *chan;
|
struct rtlx_channel *chan;
|
||||||
|
enum rtlx_state state;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (index >= RTLX_CHANNELS) {
|
if (index >= RTLX_CHANNELS) {
|
||||||
|
@ -155,13 +156,13 @@ int rtlx_open(int index, int can_sleep)
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel_wqs[index].in_open) {
|
if (atomic_inc_return(&channel_wqs[index].in_open) > 1) {
|
||||||
printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index);
|
printk(KERN_DEBUG "rtlx_open channel %d already opened\n",
|
||||||
return -EBUSY;
|
index);
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto out_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_wqs[index].in_open++;
|
|
||||||
|
|
||||||
if (rtlx == NULL) {
|
if (rtlx == NULL) {
|
||||||
if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
|
if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
|
||||||
if (can_sleep) {
|
if (can_sleep) {
|
||||||
|
@ -173,9 +174,8 @@ int rtlx_open(int index, int can_sleep)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
} else {
|
} else {
|
||||||
printk( KERN_DEBUG "No SP program loaded, and device "
|
printk(KERN_DEBUG "No SP program loaded, and device "
|
||||||
"opened with O_NONBLOCK\n");
|
"opened with O_NONBLOCK\n");
|
||||||
channel_wqs[index].in_open = 0;
|
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
|
@ -193,7 +193,6 @@ int rtlx_open(int index, int can_sleep)
|
||||||
} else {
|
} else {
|
||||||
printk(" *vpe_get_shared is NULL. "
|
printk(" *vpe_get_shared is NULL. "
|
||||||
"Has an SP program been loaded?\n");
|
"Has an SP program been loaded?\n");
|
||||||
channel_wqs[index].in_open = 0;
|
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
|
@ -202,31 +201,28 @@ int rtlx_open(int index, int can_sleep)
|
||||||
if ((unsigned int)*p < KSEG0) {
|
if ((unsigned int)*p < KSEG0) {
|
||||||
printk(KERN_WARNING "vpe_get_shared returned an invalid pointer "
|
printk(KERN_WARNING "vpe_get_shared returned an invalid pointer "
|
||||||
"maybe an error code %d\n", (int)*p);
|
"maybe an error code %d\n", (int)*p);
|
||||||
channel_wqs[index].in_open = 0;
|
|
||||||
ret = -ENOSYS;
|
ret = -ENOSYS;
|
||||||
goto out_fail;
|
goto out_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = rtlx_init(*p)) < 0) {
|
if ((ret = rtlx_init(*p)) < 0)
|
||||||
channel_wqs[index].in_open = 0;
|
goto out_ret;
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chan = &rtlx->channel[index];
|
chan = &rtlx->channel[index];
|
||||||
|
|
||||||
if (chan->lx_state == RTLX_STATE_OPENED) {
|
state = xchg(&chan->lx_state, RTLX_STATE_OPENED);
|
||||||
channel_wqs[index].in_open = 0;
|
if (state == RTLX_STATE_OPENED) {
|
||||||
return -EBUSY;
|
ret = -EBUSY;
|
||||||
}
|
goto out_fail;
|
||||||
|
}
|
||||||
chan->lx_state = RTLX_STATE_OPENED;
|
|
||||||
channel_wqs[index].in_open = 0;
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out_fail:
|
out_fail:
|
||||||
channel_wqs[index].in_open--;
|
smp_mb();
|
||||||
|
atomic_dec(&channel_wqs[index].in_open);
|
||||||
|
smp_mb();
|
||||||
|
|
||||||
|
out_ret:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,7 +471,7 @@ static int rtlx_module_init(void)
|
||||||
for (i = 0; i < RTLX_CHANNELS; i++) {
|
for (i = 0; i < RTLX_CHANNELS; i++) {
|
||||||
init_waitqueue_head(&channel_wqs[i].rt_queue);
|
init_waitqueue_head(&channel_wqs[i].rt_queue);
|
||||||
init_waitqueue_head(&channel_wqs[i].lx_queue);
|
init_waitqueue_head(&channel_wqs[i].lx_queue);
|
||||||
channel_wqs[i].in_open = 0;
|
atomic_set(&channel_wqs[i].in_open, 0);
|
||||||
|
|
||||||
dev = device_create(mt_class, NULL, MKDEV(major, i),
|
dev = device_create(mt_class, NULL, MKDEV(major, i),
|
||||||
"%s%d", module_name, i);
|
"%s%d", module_name, i);
|
||||||
|
|
|
@ -1079,6 +1079,7 @@ static int getcwd(char *buff, int size)
|
||||||
static int vpe_open(struct inode *inode, struct file *filp)
|
static int vpe_open(struct inode *inode, struct file *filp)
|
||||||
{
|
{
|
||||||
int minor, ret;
|
int minor, ret;
|
||||||
|
enum vpe_state state;
|
||||||
struct vpe *v;
|
struct vpe *v;
|
||||||
struct vpe_notifications *not;
|
struct vpe_notifications *not;
|
||||||
|
|
||||||
|
@ -1093,7 +1094,8 @@ static int vpe_open(struct inode *inode, struct file *filp)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v->state != VPE_STATE_UNUSED) {
|
state = xchg(&v->state, VPE_STATE_INUSE);
|
||||||
|
if (state != VPE_STATE_UNUSED) {
|
||||||
dvpe();
|
dvpe();
|
||||||
|
|
||||||
printk(KERN_DEBUG "VPE loader: tc in use dumping regs\n");
|
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)
|
||||||
cleanup_tc(get_tc(minor));
|
cleanup_tc(get_tc(minor));
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate it so when we get write ops we know it's expected.
|
|
||||||
v->state = VPE_STATE_INUSE;
|
|
||||||
|
|
||||||
/* this of-course trashes what was there before... */
|
/* this of-course trashes what was there before... */
|
||||||
v->pbuffer = vmalloc(P_SIZE);
|
v->pbuffer = vmalloc(P_SIZE);
|
||||||
v->plen = P_SIZE;
|
v->plen = P_SIZE;
|
||||||
|
|
Loading…
Reference in New Issue