diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2018-08-14 16:45:03 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.ibm.com> | 2018-08-16 18:28:10 +1000 |
commit | 9844f12ea28eee7c8d07c76043b5fdb170d6cd6a (patch) | |
tree | 35a4fd35815cac3f15a79a7bd8c67139c719e03e | |
parent | 58a86b8101c82deda94e85838fd10a3dbaf210f5 (diff) | |
download | skiboot-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.c | 3 |
1 files changed, 3 insertions, 0 deletions
@@ -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 */ |