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

Commit ee31b337 authored by Russell King's avatar Russell King Committed by Russell King
Browse files

[SERIAL] Fix Bug 4900: S3 resume oops with irattach - Thinkpad A21m



If we fail to re-startup a serial port on resume, shut it down
immediately and mark it as an error condition.

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 270c7a72
Loading
Loading
Loading
Loading
+49 −35
Original line number Original line Diff line number Diff line
@@ -209,8 +209,14 @@ static void uart_shutdown(struct uart_state *state)
	struct uart_info *info = state->info;
	struct uart_info *info = state->info;
	struct uart_port *port = state->port;
	struct uart_port *port = state->port;


	if (!(info->flags & UIF_INITIALIZED))
	/*
		return;
	 * Set the TTY IO error marker
	 */
	if (info->tty)
		set_bit(TTY_IO_ERROR, &info->tty->flags);

	if (info->flags & UIF_INITIALIZED) {
		info->flags &= ~UIF_INITIALIZED;


		/*
		/*
		 * Turn off DTR and RTS early.
		 * Turn off DTR and RTS early.
@@ -236,6 +242,12 @@ static void uart_shutdown(struct uart_state *state)
		 * Ensure that the IRQ handler isn't running on another CPU.
		 * Ensure that the IRQ handler isn't running on another CPU.
		 */
		 */
		synchronize_irq(port->irq);
		synchronize_irq(port->irq);
	}

	/*
	 * kill off our tasklet
	 */
	tasklet_kill(&info->tlet);


	/*
	/*
	 * Free the transmit buffer page.
	 * Free the transmit buffer page.
@@ -244,15 +256,6 @@ static void uart_shutdown(struct uart_state *state)
		free_page((unsigned long)info->xmit.buf);
		free_page((unsigned long)info->xmit.buf);
		info->xmit.buf = NULL;
		info->xmit.buf = NULL;
	}
	}

	/*
	 * kill off our tasklet
	 */
	tasklet_kill(&info->tlet);
	if (info->tty)
		set_bit(TTY_IO_ERROR, &info->tty->flags);

	info->flags &= ~UIF_INITIALIZED;
}
}


/**
/**
@@ -1928,14 +1931,25 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)


	if (state->info && state->info->flags & UIF_INITIALIZED) {
	if (state->info && state->info->flags & UIF_INITIALIZED) {
		struct uart_ops *ops = port->ops;
		struct uart_ops *ops = port->ops;
		int ret;


		ops->set_mctrl(port, 0);
		ops->set_mctrl(port, 0);
		ops->startup(port);
		ret = ops->startup(port);
		if (ret == 0) {
			uart_change_speed(state, NULL);
			uart_change_speed(state, NULL);
			spin_lock_irq(&port->lock);
			spin_lock_irq(&port->lock);
			ops->set_mctrl(port, port->mctrl);
			ops->set_mctrl(port, port->mctrl);
			ops->start_tx(port);
			ops->start_tx(port);
			spin_unlock_irq(&port->lock);
			spin_unlock_irq(&port->lock);
		} else {
			/*
			 * Failed to resume - maybe hardware went away?
			 * Clear the "initialized" flag so we won't try
			 * to call the low level drivers shutdown method.
			 */
			state->info->flags &= ~UIF_INITIALIZED;
			uart_shutdown(state);
		}
	}
	}


	up(&state->sem);
	up(&state->sem);