USB: f_fs: Add memory barrier before atomic operations
authorMayank Rana <mrana@codeaurora.org>
Wed, 25 Feb 2015 06:10:12 +0000 (22:10 -0800)
committerDanny Wood <danwood76@gmail.com>
Fri, 15 Feb 2019 16:51:51 +0000 (16:51 +0000)
In few instances, it is observed that multiple adbd instances are
running on device causing condition BUG_ON(ffs->gadget) to be true.
ffs->opened and ffs->ref atomic variables are used here to make
decision for checking ffs->gadget. These atomic variable operations
requires expilict memory barrier to make sure that update to
ffs->gadget is visible to other CPUs before updated atomic variable
based value is seen.

CRs-Fixed: 793733
Change-Id: I3c846eb6bbb53663892e05d51ebac8439aac957a
Signed-off-by: Mayank Rana <mrana@codeaurora.org>
drivers/usb/gadget/f_fs.c

index 46615a7b7d29284466dce420e5a1c86bded2b635..68619caa7d70c4829769ac950f489a2784814c17 100644 (file)
@@ -696,6 +696,7 @@ static int ffs_ep0_open(struct inode *inode, struct file *file)
        if (unlikely(ffs->state == FFS_CLOSING))
                return -EBUSY;
 
+       smp_mb__before_atomic();
        if (atomic_read(&ffs->opened))
                return -EBUSY;
 
@@ -1324,6 +1325,7 @@ static void ffs_data_get(struct ffs_data *ffs)
 {
        ENTER();
 
+       smp_mb__before_atomic();
        atomic_inc(&ffs->ref);
 }
 
@@ -1331,6 +1333,7 @@ static void ffs_data_opened(struct ffs_data *ffs)
 {
        ENTER();
 
+       smp_mb__before_atomic();
        atomic_inc(&ffs->ref);
        atomic_inc(&ffs->opened);
 }
@@ -1339,6 +1342,7 @@ static void ffs_data_put(struct ffs_data *ffs)
 {
        ENTER();
 
+       smp_mb__before_atomic();
        if (unlikely(atomic_dec_and_test(&ffs->ref))) {
                pr_info("%s(): freeing\n", __func__);
                ffs_data_clear(ffs);
@@ -1353,6 +1357,7 @@ static void ffs_data_closed(struct ffs_data *ffs)
 {
        ENTER();
 
+       smp_mb__before_atomic();
        if (atomic_dec_and_test(&ffs->opened)) {
                ffs->state = FFS_CLOSING;
                ffs_data_reset(ffs);
@@ -1396,8 +1401,8 @@ static void ffs_data_clear(struct ffs_data *ffs)
 
        /* Dump ffs->gadget and ffs->flags */
        if (ffs->gadget)
-               pr_err("%s: ffs->gadget= %p, ffs->flags= %lu\n", __func__,
-                                               ffs->gadget, ffs->flags);
+               pr_err("%s: ffs:%p ffs->gadget= %p, ffs->flags= %lu\n",
+                               __func__, ffs, ffs->gadget, ffs->flags);
        BUG_ON(ffs->gadget);
 
        if (ffs->epfiles)