Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4c4018b authored by Ralf Baechle's avatar Ralf Baechle
Browse files

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

parent cbc84135
Loading
Loading
Loading
Loading
+20 −24
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ static char module_name[] = "rtlx";
static struct chan_waitqueues {
	wait_queue_head_t rt_queue;
	wait_queue_head_t lx_queue;
	int in_open;
	atomic_t in_open;
} channel_wqs[RTLX_CHANNELS];

static struct irqaction irq;
@@ -148,6 +148,7 @@ int rtlx_open(int index, int can_sleep)
{
	volatile struct rtlx_info **p;
	struct rtlx_channel *chan;
	enum rtlx_state state;
	int ret = 0;

	if (index >= RTLX_CHANNELS) {
@@ -155,13 +156,13 @@ int rtlx_open(int index, int can_sleep)
		return -ENOSYS;
	}

	if (channel_wqs[index].in_open) {
		printk(KERN_DEBUG "rtlx_open channel %d already opened\n", index);
		return -EBUSY;
	if (atomic_inc_return(&channel_wqs[index].in_open) > 1) {
		printk(KERN_DEBUG "rtlx_open channel %d already opened\n",
		       index);
		ret = -EBUSY;
		goto out_fail;
	}

	channel_wqs[index].in_open++;

	if (rtlx == NULL) {
		if( (p = vpe_get_shared(RTLX_TARG_VPE)) == NULL) {
			if (can_sleep) {
@@ -175,7 +176,6 @@ int rtlx_open(int index, int can_sleep)
			} else {
				printk(KERN_DEBUG "No SP program loaded, and device "
					"opened with O_NONBLOCK\n");
				channel_wqs[index].in_open = 0;
				ret = -ENOSYS;
				goto out_fail;
			}
@@ -193,7 +193,6 @@ int rtlx_open(int index, int can_sleep)
			} else {
				printk(" *vpe_get_shared is NULL. "
				       "Has an SP program been loaded?\n");
				channel_wqs[index].in_open = 0;
				ret = -ENOSYS;
				goto out_fail;
			}
@@ -202,31 +201,28 @@ int rtlx_open(int index, int can_sleep)
		if ((unsigned int)*p < KSEG0) {
			printk(KERN_WARNING "vpe_get_shared returned an invalid pointer "
			       "maybe an error code %d\n", (int)*p);
 			channel_wqs[index].in_open = 0;
			ret = -ENOSYS;
			goto out_fail;
		}

		if ((ret = rtlx_init(*p)) < 0) {
 			channel_wqs[index].in_open = 0;
  			return ret;
 		}
		if ((ret = rtlx_init(*p)) < 0)
			goto out_ret;
	}

	chan = &rtlx->channel[index];

 	if (chan->lx_state == RTLX_STATE_OPENED) {
 		channel_wqs[index].in_open = 0;
  		return -EBUSY;
	state = xchg(&chan->lx_state, RTLX_STATE_OPENED);
	if (state == RTLX_STATE_OPENED) {
		ret = -EBUSY;
		goto out_fail;
	}

  	chan->lx_state = RTLX_STATE_OPENED;
 	channel_wqs[index].in_open = 0;
	return 0;

out_fail:
	channel_wqs[index].in_open--;
	smp_mb();
	atomic_dec(&channel_wqs[index].in_open);
	smp_mb();

out_ret:
	return ret;
}

@@ -475,7 +471,7 @@ static int rtlx_module_init(void)
	for (i = 0; i < RTLX_CHANNELS; i++) {
		init_waitqueue_head(&channel_wqs[i].rt_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),
		                    "%s%d", module_name, i);
+3 −4
Original line number Diff line number Diff line
@@ -1079,6 +1079,7 @@ static int getcwd(char *buff, int size)
static int vpe_open(struct inode *inode, struct file *filp)
{
	int minor, ret;
	enum vpe_state state;
	struct vpe *v;
	struct vpe_notifications *not;

@@ -1093,7 +1094,8 @@ static int vpe_open(struct inode *inode, struct file *filp)
		return -ENODEV;
	}

	if (v->state != VPE_STATE_UNUSED) {
	state = xchg(&v->state, VPE_STATE_INUSE);
	if (state != VPE_STATE_UNUSED) {
		dvpe();

		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));
	}

	// 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... */
	v->pbuffer = vmalloc(P_SIZE);
	v->plen = P_SIZE;