OSDN Git Service

diag: Synchronize threads to fix possible deadlock
authorManoj Prabhu B <bmanoj@codeaurora.org>
Tue, 10 Jan 2017 14:49:28 +0000 (20:19 +0530)
committerGerrit - the friendly Code Review server <code-review@localhost>
Fri, 20 Jan 2017 08:57:02 +0000 (00:57 -0800)
This patch fixes the possible deadlock during processing
of feature mask between different peripherals.

CRs-Fixed: 1101672
Change-Id: I4d4223275c03017ef367bafa8e55be1803b9a750
Signed-off-by: Manoj Prabhu B <bmanoj@codeaurora.org>
drivers/char/diag/diagchar.h
drivers/char/diag/diagchar_core.c
drivers/char/diag/diagfwd_peripheral.c
drivers/char/diag/diagfwd_socket.c

index 409d272..9d235b7 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -514,7 +514,7 @@ struct diagchar_dev {
        struct list_head cmd_reg_list;
        struct mutex cmd_reg_mutex;
        uint32_t cmd_reg_count;
-       struct mutex diagfwd_channel_mutex;
+       struct mutex diagfwd_channel_mutex[NUM_PERIPHERALS];
        /* Sizes that reflect memory pool sizes */
        unsigned int poolsize;
        unsigned int poolsize_hdlc;
index f8b0852..facdb0f 100644 (file)
@@ -3371,7 +3371,7 @@ static int diagchar_cleanup(void)
 static int __init diagchar_init(void)
 {
        dev_t dev;
-       int error, ret;
+       int error, ret, i;
 
        pr_debug("diagfwd initializing ..\n");
        ret = 0;
@@ -3418,7 +3418,8 @@ static int __init diagchar_init(void)
        mutex_init(&driver->diag_file_mutex);
        mutex_init(&driver->delayed_rsp_mutex);
        mutex_init(&apps_data_mutex);
-       mutex_init(&driver->diagfwd_channel_mutex);
+       for (i = 0; i < NUM_PERIPHERALS; i++)
+               mutex_init(&driver->diagfwd_channel_mutex[i]);
        init_waitqueue_head(&driver->wait_q);
        INIT_WORK(&(driver->diag_drain_work), diag_drain_work_fn);
        INIT_WORK(&(driver->update_user_clients),
index c1f954c..3f9f7a9 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -655,7 +655,7 @@ void diagfwd_close_transport(uint8_t transport, uint8_t peripheral)
                return;
        }
 
-       mutex_lock(&driver->diagfwd_channel_mutex);
+       mutex_lock(&driver->diagfwd_channel_mutex[peripheral]);
        fwd_info = &early_init_info[transport][peripheral];
        if (fwd_info->p_ops && fwd_info->p_ops->close)
                fwd_info->p_ops->close(fwd_info->ctxt);
@@ -679,7 +679,7 @@ void diagfwd_close_transport(uint8_t transport, uint8_t peripheral)
                diagfwd_late_open(dest_info);
        diagfwd_cntl_open(dest_info);
        init_fn(peripheral);
-       mutex_unlock(&driver->diagfwd_channel_mutex);
+       mutex_unlock(&driver->diagfwd_channel_mutex[peripheral]);
        diagfwd_queue_read(&peripheral_info[TYPE_DATA][peripheral]);
        diagfwd_queue_read(&peripheral_info[TYPE_CMD][peripheral]);
 }
index 8889498..22a60cd 100644 (file)
@@ -1088,9 +1088,9 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
                                      (info->data_ready > 0) || (!info->hdl) ||
                                      (atomic_read(&info->diag_state) == 0));
        if (err) {
-               mutex_lock(&driver->diagfwd_channel_mutex);
+               mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
                diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
-               mutex_unlock(&driver->diagfwd_channel_mutex);
+               mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
                return -ERESTARTSYS;
        }
 
@@ -1102,9 +1102,9 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
                DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
                         "%s closing read thread. diag state is closed\n",
                         info->name);
-               mutex_lock(&driver->diagfwd_channel_mutex);
+               mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
                diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
-               mutex_unlock(&driver->diagfwd_channel_mutex);
+               mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
                return 0;
        }
 
@@ -1171,10 +1171,10 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
        if (total_recd > 0) {
                DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s read total bytes: %d\n",
                         info->name, total_recd);
-               mutex_lock(&driver->diagfwd_channel_mutex);
+               mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
                err = diagfwd_channel_read_done(info->fwd_ctxt,
                                                buf, total_recd);
-               mutex_unlock(&driver->diagfwd_channel_mutex);
+               mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
                if (err)
                        goto fail;
        } else {
@@ -1187,9 +1187,9 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
        return 0;
 
 fail:
-       mutex_lock(&driver->diagfwd_channel_mutex);
+       mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
        diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
-       mutex_unlock(&driver->diagfwd_channel_mutex);
+       mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
        return -EIO;
 }