usb: adb panic [1/1]
authorhe.he <he.he@amlogic.com>
Tue, 20 Nov 2018 05:57:37 +0000 (13:57 +0800)
committerJianxin Pan <jianxin.pan@amlogic.com>
Wed, 12 Dec 2018 03:37:08 +0000 (19:37 -0800)
PD#SWPL-2678

Problem:
adb panic in release_ffs_buffer

Solution:
1.when kzalloc data_ep use GFP_ATOMIC  instead of GFP_KERNEL
and keep spin lock protection.
2.check buffer_temp->data_ep == NULL, return

Test: adb push

Verify:
verified by he he

Change-Id: I3402b17d62b8a0ef4e3185a87729a0c3e87449e9
Signed-off-by: he.he <he.he@amlogic.com>
drivers/usb/gadget/function/f_fs.c

index 35d66f5..32c2999 100644 (file)
@@ -294,10 +294,8 @@ struct ffs_data_buffer *ffs_retry_malloc_buffer(struct ffs_data *ffs)
        pr_info("ffs_retry_malloc_buffer\n");
        for (i = 0; i < FFS_BUFFER_MAX; i++) {
                if (ffs->buffer[i].data_state == -1) {
-                       spin_unlock_irq(&ffs->eps_lock);
                        ffs->buffer[i].data_ep
-                               = kzalloc(MAX_PAYLOAD_EPS, GFP_KERNEL);
-                       spin_lock_irq(&ffs->eps_lock);
+                               = kzalloc(MAX_PAYLOAD_EPS, GFP_ATOMIC);
                        if (!ffs->buffer[i].data_ep)
                                return NULL;
                        ffs->buffer[i].data_state = 1;
@@ -317,7 +315,7 @@ static void ffs_free_buffer(struct ffs_data *ffs)
                if (ffs->buffer[i].data_state != -1) {
                        kfree(ffs->buffer[i].data_ep);
                        ffs->buffer[i].data_ep = NULL;
-                       ffs->buffer[i].data_state = 0;
+                       ffs->buffer[i].data_state = -1;
                }
        }
 }
@@ -342,6 +340,11 @@ static void release_ffs_buffer(struct ffs_data *ffs,
        struct ffs_data_buffer *buffer_temp = buffer;
 
        spin_lock_irq(&ffs->eps_lock);
+       if (buffer_temp->data_ep == NULL) {
+               buffer_temp->data_state = -1;
+               spin_unlock_irq(&ffs->eps_lock);
+               return;
+       }
        memset(buffer_temp->data_ep, 0, MAX_PAYLOAD_EPS);
        buffer_temp->data_state = 0;
        spin_unlock_irq(&ffs->eps_lock);
@@ -872,6 +875,10 @@ static void ffs_user_copy_worker(struct work_struct *work)
                if (io_data->buf == buffer->data_ep) {
                        break;
                }
+               if (i == FFS_BUFFER_MAX - 1) {
+                       pr_info("io_data->buf is missing, i=%d-\n", i);
+                       buffer = NULL;
+               }
        }
 #endif
        if (io_data->read && ret > 0) {