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

Commit f9c42831 authored by Michael Bohan's avatar Michael Bohan Committed by Se Wang (Patrick) Oh
Browse files

printk: Don't take console semaphore in atomic context



The CPU HOTPLUG take_cpu_down path is invokved with preemption
disabled via stop_machine. This causes a "Scheduling while
atomic" BUG when there is contention for the console semaphore.
The solution is to defer the console flush until it's not in
scheduling violation.

Change-Id: I2d0d58576a4db308ee40850a18a6bb9784ca4e4b
Signed-off-by: default avatarMichael Bohan <mbohan@codeaurora.org>
[mattw@codeaurora.org: adjust for moved location of printk.c]
Signed-off-by: default avatarMatt Wagantall <mattw@codeaurora.org>
parent d9479b68
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -2065,6 +2065,14 @@ void resume_console(void)
	console_unlock();
}

static void __cpuinit console_flush(struct work_struct *work)
{
	console_lock();
	console_unlock();
}

static __cpuinitdata DECLARE_WORK(console_cpu_notify_work, console_flush);

/**
 * console_cpu_notify - print deferred console messages after CPU hotplug
 * @self: notifier struct
@@ -2075,6 +2083,9 @@ void resume_console(void)
 * will be spooled but will not show up on the console.  This function is
 * called when a new CPU comes online (or fails to come up), and ensures
 * that any such output gets printed.
 *
 * Special handling must be done for cases invoked from an atomic context,
 * as we can't be taking the console semaphore here.
 */
static int console_cpu_notify(struct notifier_block *self,
	unsigned long action, void *hcpu)
@@ -2092,6 +2103,12 @@ static int console_cpu_notify(struct notifier_block *self,
		console_unlock();
#endif
		break;
	/* invoked with preemption disabled, so defer */
	case CPU_DYING:
		if (!console_trylock())
			schedule_work(&console_cpu_notify_work);
		else
			console_unlock();
	}
	return NOTIFY_OK;
}