OSDN Git Service

Merge "diag: Handle data ready notification properly"
authorLinux Build Service Account <lnxbuild@quicinc.com>
Mon, 6 Nov 2017 06:32:50 +0000 (22:32 -0800)
committerGerrit - the friendly Code Review server <code-review@localhost>
Mon, 6 Nov 2017 06:32:50 +0000 (22:32 -0800)
drivers/char/diag/diag_memorydevice.c
drivers/char/diag/diagchar.h
drivers/char/diag/diagchar_core.c
drivers/char/diag/diagfwd.c

index 986aeed..072c55c 100644 (file)
@@ -202,6 +202,7 @@ int diag_md_write(int id, unsigned char *buf, int len, int ctx)
 
                found = 1;
                driver->data_ready[i] |= USER_SPACE_DATA_TYPE;
+               atomic_inc(&driver->data_ready_notif[i]);
                pr_debug("diag: wake up logging process\n");
                wake_up_interruptible(&driver->wait_q);
        }
index f1596eb..80f004b 100644 (file)
@@ -26,6 +26,8 @@
 #include <asm/atomic.h>
 #include "diagfwd_bridge.h"
 
+#define THRESHOLD_CLIENT_LIMIT 50
+
 /* Size of the USB buffers used for read and write*/
 #define USB_MAX_OUT_BUF 4096
 #define APPS_BUF_SIZE  4096
@@ -508,6 +510,7 @@ struct diagchar_dev {
        wait_queue_head_t wait_q;
        struct diag_client_map *client_map;
        int *data_ready;
+       atomic_t data_ready_notif[THRESHOLD_CLIENT_LIMIT];
        int num_clients;
        int polling_reg_flag;
        int use_device_tree;
index 4111e59..ae0182a 100644 (file)
@@ -139,7 +139,6 @@ module_param(poolsize_qsc_usb, uint, 0);
 
 /* This is the max number of user-space clients supported at initialization*/
 static unsigned int max_clients = 15;
-static unsigned int threshold_client_limit = 50;
 module_param(max_clients, uint, 0);
 
 /* Timer variables */
@@ -328,7 +327,7 @@ static int diagchar_open(struct inode *inode, struct file *file)
                if (i < driver->num_clients) {
                        diag_add_client(i, file);
                } else {
-                       if (i < threshold_client_limit) {
+                       if (i < THRESHOLD_CLIENT_LIMIT) {
                                driver->num_clients++;
                                temp = krealloc(driver->client_map
                                        , (driver->num_clients) * sizeof(struct
@@ -358,11 +357,17 @@ static int diagchar_open(struct inode *inode, struct file *file)
                        }
                }
                driver->data_ready[i] = 0x0;
+               atomic_set(&driver->data_ready_notif[i], 0);
                driver->data_ready[i] |= MSG_MASKS_TYPE;
+               atomic_inc(&driver->data_ready_notif[i]);
                driver->data_ready[i] |= EVENT_MASKS_TYPE;
+               atomic_inc(&driver->data_ready_notif[i]);
                driver->data_ready[i] |= LOG_MASKS_TYPE;
+               atomic_inc(&driver->data_ready_notif[i]);
                driver->data_ready[i] |= DCI_LOG_MASKS_TYPE;
+               atomic_inc(&driver->data_ready_notif[i]);
                driver->data_ready[i] |= DCI_EVENT_MASKS_TYPE;
+               atomic_inc(&driver->data_ready_notif[i]);
 
                if (driver->ref_count == 0)
                        diag_mempool_init();
@@ -1866,6 +1871,7 @@ static int diag_ioctl_lsm_deinit(void)
        }
 
        driver->data_ready[i] |= DEINIT_TYPE;
+       atomic_inc(&driver->data_ready_notif[i]);
        mutex_unlock(&driver->diagchar_mutex);
        wake_up_interruptible(&driver->wait_q);
 
@@ -3029,16 +3035,6 @@ static int diag_user_process_apps_data(const char __user *buf, int len,
        return 0;
 }
 
-static int check_data_ready(int index)
-{
-       int data_type = 0;
-
-       mutex_lock(&driver->diagchar_mutex);
-       data_type = driver->data_ready[index];
-       mutex_unlock(&driver->diagchar_mutex);
-       return data_type;
-}
-
 static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
                          loff_t *ppos)
 {
@@ -3065,7 +3061,8 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
                pr_err("diag: bad address from user side\n");
                return -EFAULT;
        }
-       wait_event_interruptible(driver->wait_q, (check_data_ready(index)) > 0);
+       wait_event_interruptible(driver->wait_q,
+                       atomic_read(&driver->data_ready_notif[index]) > 0);
 
        mutex_lock(&driver->diagchar_mutex);
 
@@ -3076,6 +3073,7 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
                /*Copy the type of data being passed*/
                data_type = driver->data_ready[index] & USER_SPACE_DATA_TYPE;
                driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
+               atomic_dec(&driver->data_ready_notif[index]);
                COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int));
                /* place holder for number of data field */
                ret += sizeof(int);
@@ -3089,11 +3087,13 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
                /* In case, the thread wakes up and the logging mode is
                not memory device any more, the condition needs to be cleared */
                driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
+               atomic_dec(&driver->data_ready_notif[index]);
        }
 
        if (driver->data_ready[index] & HDLC_SUPPORT_TYPE) {
                data_type = driver->data_ready[index] & HDLC_SUPPORT_TYPE;
                driver->data_ready[index] ^= HDLC_SUPPORT_TYPE;
+               atomic_dec(&driver->data_ready_notif[index]);
                COPY_USER_SPACE_OR_EXIT(buf, data_type, sizeof(int));
                mutex_lock(&driver->md_session_lock);
                session_info = diag_md_session_get_pid(current->tgid);
@@ -3110,6 +3110,7 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
                data_type = driver->data_ready[index] & DEINIT_TYPE;
                COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
                driver->data_ready[index] ^= DEINIT_TYPE;
+               atomic_dec(&driver->data_ready_notif[index]);
                mutex_unlock(&driver->diagchar_mutex);
                diag_remove_client_entry(file);
                return ret;
@@ -3125,6 +3126,7 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
                if (write_len > 0)
                        ret += write_len;
                driver->data_ready[index] ^= MSG_MASKS_TYPE;
+               atomic_dec(&driver->data_ready_notif[index]);
                goto exit;
        }
 
@@ -3144,6 +3146,7 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
                                                event_mask.mask_len);
                }
                driver->data_ready[index] ^= EVENT_MASKS_TYPE;
+               atomic_dec(&driver->data_ready_notif[index]);
                goto exit;
        }
 
@@ -3157,6 +3160,7 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
                if (write_len > 0)
                        ret += write_len;
                driver->data_ready[index] ^= LOG_MASKS_TYPE;
+               atomic_dec(&driver->data_ready_notif[index]);
                goto exit;
        }
 
@@ -3168,6 +3172,7 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
                                        *(driver->apps_req_buf),
                                        driver->apps_req_buf_len);
                driver->data_ready[index] ^= PKT_TYPE;
+               atomic_dec(&driver->data_ready_notif[index]);
                driver->in_busy_pktdata = 0;
                goto exit;
        }
@@ -3179,6 +3184,7 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
                COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->dci_pkt_buf),
                                        driver->dci_pkt_length);
                driver->data_ready[index] ^= DCI_PKT_TYPE;
+               atomic_dec(&driver->data_ready_notif[index]);
                driver->in_busy_dcipktdata = 0;
                goto exit;
        }
@@ -3191,6 +3197,7 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
                COPY_USER_SPACE_OR_EXIT(buf + 8, (dci_ops_tbl[DCI_LOCAL_PROC].
                                event_mask_composite), DCI_EVENT_MASK_SIZE);
                driver->data_ready[index] ^= DCI_EVENT_MASKS_TYPE;
+               atomic_dec(&driver->data_ready_notif[index]);
                goto exit;
        }
 
@@ -3202,6 +3209,7 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
                COPY_USER_SPACE_OR_EXIT(buf+8, (dci_ops_tbl[DCI_LOCAL_PROC].
                                log_mask_composite), DCI_LOG_MASK_SIZE);
                driver->data_ready[index] ^= DCI_LOG_MASKS_TYPE;
+               atomic_dec(&driver->data_ready_notif[index]);
                goto exit;
        }
 
@@ -3233,6 +3241,7 @@ exit:
                        exit_stat = diag_copy_dci(buf, count, entry, &ret);
                        mutex_lock(&driver->diagchar_mutex);
                        driver->data_ready[index] ^= DCI_DATA_TYPE;
+                       atomic_dec(&driver->data_ready_notif[index]);
                        mutex_unlock(&driver->diagchar_mutex);
                        if (exit_stat == 1) {
                                mutex_unlock(&driver->dci_mutex);
index ef08f93..40412ba 100644 (file)
@@ -226,6 +226,7 @@ void chk_logging_wakeup(void)
                         * situation.
                         */
                        driver->data_ready[i] |= USER_SPACE_DATA_TYPE;
+                       atomic_inc(&driver->data_ready_notif[i]);
                        pr_debug("diag: Force wakeup of logging process\n");
                        wake_up_interruptible(&driver->wait_q);
                        break;
@@ -480,8 +481,10 @@ void diag_update_userspace_clients(unsigned int type)
 
        mutex_lock(&driver->diagchar_mutex);
        for (i = 0; i < driver->num_clients; i++)
-               if (driver->client_map[i].pid != 0)
+               if (driver->client_map[i].pid != 0) {
                        driver->data_ready[i] |= type;
+                       atomic_inc(&driver->data_ready_notif[i]);
+               }
        wake_up_interruptible(&driver->wait_q);
        mutex_unlock(&driver->diagchar_mutex);
 }
@@ -498,6 +501,8 @@ void diag_update_md_clients(unsigned int type)
                                        driver->client_map[j].pid ==
                                        driver->md_session_map[i]->pid) {
                                        driver->data_ready[j] |= type;
+                                       atomic_inc(
+                                               &driver->data_ready_notif[j]);
                                        break;
                                }
                        }
@@ -513,6 +518,7 @@ void diag_update_sleeping_process(int process_id, int data_type)
        for (i = 0; i < driver->num_clients; i++)
                if (driver->client_map[i].pid == process_id) {
                        driver->data_ready[i] |= data_type;
+                       atomic_inc(&driver->data_ready_notif[i]);
                        break;
                }
        wake_up_interruptible(&driver->wait_q);
@@ -1703,6 +1709,8 @@ int diagfwd_init(void)
                                                        , GFP_KERNEL)) == NULL)
                goto err;
        kmemleak_not_leak(driver->data_ready);
+       for (i = 0; i < THRESHOLD_CLIENT_LIMIT; i++)
+               atomic_set(&driver->data_ready_notif[i], 0);
        if (driver->apps_req_buf == NULL) {
                driver->apps_req_buf = kzalloc(DIAG_MAX_REQ_SIZE, GFP_KERNEL);
                if (!driver->apps_req_buf)