aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2018-08-14 16:45:03 +1000
committerStewart Smith <stewart@linux.ibm.com>2018-08-16 18:28:10 +1000
commit9844f12ea28eee7c8d07c76043b5fdb170d6cd6a (patch)
tree35a4fd35815cac3f15a79a7bd8c67139c719e03e
parent58a86b8101c82deda94e85838fd10a3dbaf210f5 (diff)
downloadskiboot-9844f12ea28eee7c8d07c76043b5fdb170d6cd6a.zip
skiboot-9844f12ea28eee7c8d07c76043b5fdb170d6cd6a.tar.gz
skiboot-9844f12ea28eee7c8d07c76043b5fdb170d6cd6a.tar.bz2
i2c: Ensure ordering between i2c_request_send() and completion
i2c_request_send loops waiting for a flag "uc.done" set by the completion routine, and then look for a result code also set by that same completion. There is no synchronization, the completion can happen on another processor, so we need to order the stores to uc and the reads from uc so that uc.done is stored last and tested first using memory barriers. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Stewart Smith <stewart@linux.ibm.com> (cherry picked from commit ef79d0370737130256168d20a9bf40f06001af88) Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
-rw-r--r--core/i2c.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/core/i2c.c b/core/i2c.c
index 070a0f6..e833310 100644
--- a/core/i2c.c
+++ b/core/i2c.c
@@ -20,6 +20,7 @@
#include <device.h>
#include <opal-msg.h>
#include <timebase.h>
+#include <processor.h>
static LIST_HEAD(i2c_bus_list);
@@ -148,6 +149,7 @@ static void i2c_sync_request_complete(int rc, struct i2c_request *req)
{
struct i2c_sync_userdata *ud = req->user_data;
ud->rc = rc;
+ lwsync();
ud->done = true;
}
@@ -222,6 +224,7 @@ int i2c_request_send(int bus_id, int dev_addr, int read_write,
waited += time_to_wait;
} while (!ud.done);
+ lwsync();
rc = ud.rc;
/* error or success */