aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-08-08 17:13:01 +1000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2014-08-08 17:20:52 +1000
commitf1067cdc0a9c8e34e4c2e57ad9dd37132b47fcb3 (patch)
treeb2991f60378c2b29e860b7490d173159c95a312d /hw
parent869c7522aad98c2682e37feb8e56be7a3e975d4d (diff)
downloadskiboot-f1067cdc0a9c8e34e4c2e57ad9dd37132b47fcb3.zip
skiboot-f1067cdc0a9c8e34e4c2e57ad9dd37132b47fcb3.tar.gz
skiboot-f1067cdc0a9c8e34e4c2e57ad9dd37132b47fcb3.tar.bz2
lock: Fix races when setting in_con_lock
When setting the flag in a lock that indicates that it's on the console path, we need to take and release that lock to ensure that any other processor that might have taken it before the flag was set has released it, otherwise the lock might still be held without the console count properly incremented, which can cause it to go negative or cause the deadlock that we mean to avoid by that to still occur. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/fsp/fsp-console.c3
-rw-r--r--hw/fsp/fsp.c8
-rw-r--r--hw/lpc.c5
-rw-r--r--hw/xscom.c8
4 files changed, 23 insertions, 1 deletions
diff --git a/hw/fsp/fsp-console.c b/hw/fsp/fsp-console.c
index d14e520..4e5803a 100644
--- a/hw/fsp/fsp-console.c
+++ b/hw/fsp/fsp-console.c
@@ -299,6 +299,9 @@ static void fsp_open_vserial(struct fsp_msg *msg)
*/
fsp_used_by_console();
fsp_con_lock.in_con_path = true;
+ /* See comment in fsp_used_by_console */
+ lock(&fsp_con_lock);
+ unlock(&fsp_con_lock);
set_console(&fsp_con_ops);
}
#endif
diff --git a/hw/fsp/fsp.c b/hw/fsp/fsp.c
index b87c8b3..2189bbb 100644
--- a/hw/fsp/fsp.c
+++ b/hw/fsp/fsp.c
@@ -2213,4 +2213,12 @@ int fsp_fetch_data_queue(uint8_t flags, uint16_t id, uint32_t sub_id,
void fsp_used_by_console(void)
{
fsp_lock.in_con_path = true;
+
+ /*
+ * Some other processor might hold it without having
+ * disabled the console locally so let's make sure that
+ * is over by taking/releasing the lock ourselves
+ */
+ lock(&fsp_lock);
+ unlock(&fsp_lock);
}
diff --git a/hw/lpc.c b/hw/lpc.c
index 603d3af..313c8d2 100644
--- a/hw/lpc.c
+++ b/hw/lpc.c
@@ -495,6 +495,9 @@ void lpc_used_by_console(void)
xscom_used_by_console();
- for_each_chip(chip)
+ for_each_chip(chip) {
chip->lpc_lock.in_con_path = true;
+ lock(&chip->lpc_lock);
+ unlock(&chip->lpc_lock);
+ }
}
diff --git a/hw/xscom.c b/hw/xscom.c
index c4c3be2..98cbaec 100644
--- a/hw/xscom.c
+++ b/hw/xscom.c
@@ -515,4 +515,12 @@ void xscom_init(void)
void xscom_used_by_console(void)
{
xscom_lock.in_con_path = true;
+
+ /*
+ * Some other processor might hold it without having
+ * disabled the console locally so let's make sure that
+ * is over by taking/releasing the lock ourselves
+ */
+ lock(&xscom_lock);
+ unlock(&xscom_lock);
}