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

Commit a360fae6 authored by Alan Cox's avatar Alan Cox Committed by Greg Kroah-Hartman
Browse files

synclink: reworking locking a bit



Use the port mutex and port lock to fix the various races. The locking
still isn't totally consistent but its better than before. Wants switching
to the port helpers.

Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 4287341d
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -675,12 +675,14 @@ static int open(struct tty_struct *tty, struct file *filp)
		goto cleanup;
	}

	mutex_lock(&info->port.mutex);
	info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;

	spin_lock_irqsave(&info->netlock, flags);
	if (info->netcount) {
		retval = -EBUSY;
		spin_unlock_irqrestore(&info->netlock, flags);
		mutex_unlock(&info->port.mutex);
		goto cleanup;
	}
	info->port.count++;
@@ -692,7 +694,7 @@ static int open(struct tty_struct *tty, struct file *filp)
		if (retval < 0)
			goto cleanup;
	}

	mutex_unlock(&info->port.mutex);
	retval = block_til_ready(tty, filp, info);
	if (retval) {
		DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval));
@@ -724,12 +726,14 @@ static void close(struct tty_struct *tty, struct file *filp)
	if (tty_port_close_start(&info->port, tty, filp) == 0)
		goto cleanup;

	mutex_lock(&info->port.mutex);
 	if (info->port.flags & ASYNC_INITIALIZED)
 		wait_until_sent(tty, info->timeout);
	flush_buffer(tty);
	tty_ldisc_flush(tty);

	shutdown(info);
	mutex_unlock(&info->port.mutex);

	tty_port_close_end(&info->port, tty);
	info->port.tty = NULL;
@@ -740,17 +744,23 @@ cleanup:
static void hangup(struct tty_struct *tty)
{
	struct slgt_info *info = tty->driver_data;
	unsigned long flags;

	if (sanity_check(info, tty->name, "hangup"))
		return;
	DBGINFO(("%s hangup\n", info->device_name));

	flush_buffer(tty);

	mutex_lock(&info->port.mutex);
	shutdown(info);

	spin_lock_irqsave(&info->port.lock, flags);
	info->port.count = 0;
	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
	info->port.tty = NULL;
	spin_unlock_irqrestore(&info->port.lock, flags);
	mutex_unlock(&info->port.mutex);

	wake_up_interruptible(&info->port.open_wait);
}
+8 −1
Original line number Diff line number Diff line
@@ -813,12 +813,14 @@ static void close(struct tty_struct *tty, struct file *filp)
	if (tty_port_close_start(&info->port, tty, filp) == 0)
		goto cleanup;

	mutex_lock(&info->port.mutex);
 	if (info->port.flags & ASYNC_INITIALIZED)
 		wait_until_sent(tty, info->timeout);

	flush_buffer(tty);
	tty_ldisc_flush(tty);
	shutdown(info);
	mutex_unlock(&info->port.mutex);

	tty_port_close_end(&info->port, tty);
	info->port.tty = NULL;
@@ -834,6 +836,7 @@ cleanup:
static void hangup(struct tty_struct *tty)
{
	SLMP_INFO *info = tty->driver_data;
	unsigned long flags;

	if (debug_level >= DEBUG_LEVEL_INFO)
		printk("%s(%d):%s hangup()\n",
@@ -842,12 +845,16 @@ static void hangup(struct tty_struct *tty)
	if (sanity_check(info, tty->name, "hangup"))
		return;

	mutex_lock(&info->port.mutex);
	flush_buffer(tty);
	shutdown(info);

	spin_lock_irqsave(&info->port.lock, flags);
	info->port.count = 0;
	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
	info->port.tty = NULL;
	spin_unlock_irqrestore(&info->port.lock, flags);
	mutex_unlock(&info->port.mutex);

	wake_up_interruptible(&info->port.open_wait);
}