diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/diag/diag_dci.c | 50 | ||||
-rw-r--r-- | drivers/char/diag/diag_dci.h | 3 | ||||
-rw-r--r-- | drivers/char/diag/diag_debugfs.c | 47 | ||||
-rw-r--r-- | drivers/char/diag/diagchar.h | 32 | ||||
-rw-r--r-- | drivers/char/diag/diagchar_core.c | 208 | ||||
-rw-r--r-- | drivers/char/diag/diagfwd.c | 163 | ||||
-rw-r--r-- | drivers/char/diag/diagfwd.h | 5 | ||||
-rw-r--r-- | drivers/char/diag/diagfwd_cntl.c | 1 | ||||
-rw-r--r-- | drivers/char/diag/diagfwd_hsic.c | 6 |
9 files changed, 325 insertions, 190 deletions
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index d2601d7f68da..7912c44f86a6 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -190,6 +190,12 @@ static void dci_add_buffer_to_list(struct diag_dci_client_tbl *client, mutex_lock(&client->write_buf_mutex); list_add_tail(&buf->buf_track, &client->list_write_buf); + /* + * In the case of DCI, there can be multiple packets in one read. To + * calculate the wakeup source reference count, we must account for each + * packet in a single read. + */ + diag_ws_on_read(DIAG_WS_DCI, buf->data_len); mutex_lock(&buf->data_mutex); buf->in_busy = 1; buf->in_list = 1; @@ -470,7 +476,6 @@ end: /* wake up all sleeping DCI clients which have some data */ diag_dci_wakeup_clients(); dci_check_drain_timer(); - diag_dci_try_deactivate_wakeup_source(); return 0; } @@ -491,7 +496,7 @@ int diag_process_smd_dci_read_data(struct diag_smd_info *smd_info, void *buf, * process DCI data */ if (driver->num_dci_client == 0) { - diag_dci_try_deactivate_wakeup_source(); + diag_ws_reset(DIAG_WS_DCI); return 0; } @@ -511,7 +516,7 @@ int diag_process_smd_dci_read_data(struct diag_smd_info *smd_info, void *buf, if ((dci_pkt_len + 5) > (recd_bytes - read_bytes)) { pr_err("diag: Invalid length in %s, len: %d, dci_pkt_len: %d", __func__, recd_bytes, dci_pkt_len); - diag_dci_try_deactivate_wakeup_source(); + diag_ws_release(); return 0; } /* @@ -520,8 +525,10 @@ int diag_process_smd_dci_read_data(struct diag_smd_info *smd_info, void *buf, */ err = diag_process_single_dci_pkt(buf + 4, dci_pkt_len, smd_info->peripheral, DCI_LOCAL_PROC); - if (err) + if (err) { + diag_ws_release(); break; + } read_bytes += 5 + dci_pkt_len; buf += 5 + dci_pkt_len; /* advance to next DCI pkt */ } @@ -529,7 +536,6 @@ int diag_process_smd_dci_read_data(struct diag_smd_info *smd_info, void *buf, /* wake up all sleeping DCI clients which have some data */ diag_dci_wakeup_clients(); dci_check_drain_timer(); - diag_dci_try_deactivate_wakeup_source(); return 0; } @@ -723,6 +729,7 @@ void extract_dci_ctrl_pkt(unsigned char *buf, int len, int token) return; } + diag_ws_on_read(DIAG_WS_DCI, len); header = (struct diag_ctrl_dci_status *)temp; temp += sizeof(struct diag_ctrl_dci_status); read_len += sizeof(struct diag_ctrl_dci_status); @@ -731,7 +738,7 @@ void extract_dci_ctrl_pkt(unsigned char *buf, int len, int token) if (read_len > len) { pr_err("diag: Invalid length len: %d in %s\n", len, __func__); - return; + goto err; } switch (*(uint8_t *)temp) { @@ -747,7 +754,7 @@ void extract_dci_ctrl_pkt(unsigned char *buf, int len, int token) default: pr_err("diag: In %s, unknown peripheral, peripheral: %d\n", __func__, *(uint8_t *)temp); - return; + goto err; } temp += sizeof(uint8_t); read_len += sizeof(uint8_t); @@ -758,6 +765,13 @@ void extract_dci_ctrl_pkt(unsigned char *buf, int len, int token) read_len += sizeof(uint8_t); diag_dci_notify_client(peripheral_mask, status, token); } +err: + /* + * DCI control packets are not consumed by the clients. Mimic client + * consumption by setting and clearing the wakeup source copy_count + * explicitly. + */ + diag_ws_on_copy_fail(DIAG_WS_DCI); } void extract_dci_pkt_rsp(unsigned char *buf, int len, int data_source, @@ -2574,21 +2588,6 @@ int diag_dci_set_real_time(struct diag_dci_client_tbl *entry, uint8_t real_time) return 1; } -void diag_dci_try_activate_wakeup_source() -{ - spin_lock_irqsave(&ws_lock, ws_lock_flags); - pm_wakeup_event(driver->diag_dev, DCI_WAKEUP_TIMEOUT); - pm_stay_awake(driver->diag_dev); - spin_unlock_irqrestore(&ws_lock, ws_lock_flags); -} - -void diag_dci_try_deactivate_wakeup_source() -{ - spin_lock_irqsave(&ws_lock, ws_lock_flags); - pm_relax(driver->diag_dev); - spin_unlock_irqrestore(&ws_lock, ws_lock_flags); -} - int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry) { int i, err = 0; @@ -2807,7 +2806,12 @@ int diag_dci_deinit_client(struct diag_dci_client_tbl *entry) smd_info->in_busy_1 = 0; mutex_unlock(&buf_entry->data_mutex); } - diag_dci_try_deactivate_wakeup_source(); + /* + * These are buffers that can't be written to the client which + * means that the copy cannot be completed. Make sure that we + * remove those references in DCI wakeup source. + */ + diag_ws_on_copy_fail(DIAG_WS_DCI); } mutex_unlock(&entry->write_buf_mutex); diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h index a52fbe212e11..aa6d7de6d440 100644 --- a/drivers/char/diag/diag_dci.h +++ b/drivers/char/diag/diag_dci.h @@ -258,9 +258,6 @@ uint8_t diag_dci_get_cumulative_real_time(int token); int diag_dci_set_real_time(struct diag_dci_client_tbl *entry, uint8_t real_time); int diag_dci_copy_health_stats(struct diag_dci_health_stats_proc *stats_proc); -/* Functions related to DCI wakeup sources */ -void diag_dci_try_activate_wakeup_source(void); -void diag_dci_try_deactivate_wakeup_source(void); int diag_dci_write_proc(int peripheral, int pkt_type, char *buf, int len); #ifdef CONFIG_DIAGFWD_BRIDGE_CODE diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c index 7abc2cade6e6..cdad688e95fa 100644 --- a/drivers/char/diag/diag_debugfs.c +++ b/drivers/char/diag/diag_debugfs.c @@ -288,6 +288,44 @@ static ssize_t diag_dbgfs_read_dcistats(struct file *file, return bytes_written; } +static ssize_t diag_dbgfs_read_power(struct file *file, char __user *ubuf, + size_t count, loff_t *ppos) +{ + char *buf; + int ret; + unsigned int buf_size; + + buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL); + if (!buf) { + pr_err("diag: %s, Error allocating memory\n", __func__); + return -ENOMEM; + } + + buf_size = ksize(buf); + ret = scnprintf(buf, buf_size, + "DCI reference count: %d\n" + "DCI copy count: %d\n" + "DCI Client Count: %d\n\n" + "Memory Device reference count: %d\n" + "Memory Device copy count: %d\n" + "Logging mode: %d\n\n" + "Wakeup source active count: %lu\n" + "Wakeup source relax count: %lu\n\n", + driver->dci_ws.ref_count, + driver->dci_ws.copy_count, + driver->num_dci_client, + driver->md_ws.ref_count, + driver->md_ws.copy_count, + driver->logging_mode, + driver->diag_dev->power.wakeup->active_count, + driver->diag_dev->power.wakeup->relax_count); + + ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret); + + kfree(buf); + return ret; +} + static ssize_t diag_dbgfs_read_workpending(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { @@ -786,6 +824,10 @@ const struct file_operations diag_dbgfs_dcistats_ops = { .read = diag_dbgfs_read_dcistats, }; +const struct file_operations diag_dbgfs_power_ops = { + .read = diag_dbgfs_read_power, +}; + int diag_debugfs_init(void) { struct dentry *entry = NULL; @@ -819,6 +861,11 @@ int diag_debugfs_init(void) if (!entry) goto err; + entry = debugfs_create_file("power", 0444, diag_dbgfs_dent, 0, + &diag_dbgfs_power_ops); + if (!entry) + goto err; + #ifdef CONFIG_DIAGFWD_BRIDGE_CODE entry = debugfs_create_file("bridge", 0444, diag_dbgfs_dent, 0, &diag_dbgfs_bridge_ops); diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h index 9bca95856789..b20b5990954c 100644 --- a/drivers/char/diag/diagchar.h +++ b/drivers/char/diag/diagchar.h @@ -191,6 +191,9 @@ #define DIAG_NUM_PROC 1 #endif +#define DIAG_WS_DCI 0 +#define DIAG_WS_MD 1 + /* Maximum number of pkt reg supported at initialization*/ extern int diag_max_reg; extern int diag_threshold_reg; @@ -254,14 +257,6 @@ struct diag_client_map { int pid; }; -struct diag_nrt_wake_lock { - int enabled; - int ref_count; - int copy_count; - struct wake_lock read_lock; - spinlock_t read_spinlock; -}; - struct real_time_vote_t { int client_id; uint16_t proc; @@ -273,6 +268,12 @@ struct real_time_query_t { int proc; } __packed; +struct diag_ws_ref_t { + int ref_count; + int copy_count; + spinlock_t lock; +}; + /* This structure is defined in USB header file */ #ifndef CONFIG_DIAG_OVER_USB struct diag_request { @@ -314,8 +315,6 @@ struct diag_smd_info { struct diag_request *write_ptr_1; struct diag_request *write_ptr_2; - struct diag_nrt_wake_lock nrt_lock; - struct workqueue_struct *wq; struct work_struct diag_read_smd_work; @@ -475,6 +474,10 @@ struct diagchar_dev { int logging_process_id; struct task_struct *socket_process; struct task_struct *callback_process; + /* Power related variables */ + struct diag_ws_ref_t dci_ws; + struct diag_ws_ref_t md_ws; + spinlock_t ws_lock; #ifdef CONFIG_DIAGFWD_BRIDGE_CODE /* common for all bridges */ @@ -503,4 +506,13 @@ void diag_get_timestamp(char *time_str); int diag_find_polling_reg(int i); void check_drain_timer(void); +void diag_ws_init(void); +void diag_ws_on_notify(void); +void diag_ws_on_read(int type, int pkt_len); +void diag_ws_on_copy(int type); +void diag_ws_on_copy_fail(int type); +void diag_ws_on_copy_complete(int type); +void diag_ws_reset(int type); +void diag_ws_release(void); + #endif diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index 754f752f7857..58e99199565d 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -330,6 +330,7 @@ static int diagchar_close(struct inode *inode, struct file *file) diag_update_proc_vote(DIAG_PROC_MEMORY_DEVICE, VOTE_DOWN, ALL_PROC); diag_switch_logging(USB_MODE); + diag_ws_reset(DIAG_WS_MD); } #endif /* DIAG over USB */ /* Delete the pkt response table entry for the exiting process */ @@ -492,6 +493,7 @@ int diag_copy_remote(char __user *buf, size_t count, int *pret, int *pnum_data) int ret = *pret; int num_data = *pnum_data; int remote_token; + int copy_data = 0; unsigned long spin_lock_flags; struct diag_write_device hsic_buf_tbl[NUM_HSIC_BUF_TBL_ENTRIES]; @@ -523,6 +525,9 @@ int diag_copy_remote(char __user *buf, size_t count, int *pret, int *pnum_data) hsic_buf_tbl[i].length); num_data++; + diag_ws_on_copy(DIAG_WS_MD); + copy_data = 1; + /* Copy the negative token */ if (copy_to_user(buf+ret, &remote_token, 4)) { @@ -579,6 +584,8 @@ drop_hsic: driver->in_busy_smux = 0; } exit_stat = 0; + if (copy_data) + diag_ws_on_copy_complete(DIAG_WS_MD); exit: *pret = ret; *pnum_data = num_data; @@ -620,6 +627,7 @@ static int diag_copy_dci(char __user *buf, size_t count, goto drop; ret += buf_entry->data_len; total_data_len += buf_entry->data_len; + diag_ws_on_copy(DIAG_WS_DCI); drop: buf_entry->in_busy = 0; buf_entry->data_len = 0; @@ -657,6 +665,13 @@ drop: /* Copy the total data length */ COPY_USER_SPACE_OR_EXIT(buf+8, total_data_len, 4); ret -= 4; + /* + * Flush any read that is currently pending on DCI data and + * command channnels. This will ensure that the next read is not + * missed. + */ + flush_workqueue(driver->diag_dci_wq); + diag_ws_on_copy_complete(DIAG_WS_DCI); } else { pr_debug("diag: In %s, Trying to copy ZERO bytes, total_data_len: %d\n", __func__, total_data_len); @@ -1341,7 +1356,7 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count, int num_data = 0, data_type; int remote_token; int exit_stat; - int clear_read_wakelock; + int copy_data = 0; unsigned long flags; for (i = 0; i < driver->num_clients; i++) @@ -1360,7 +1375,6 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count, mutex_lock(&driver->diagchar_mutex); - clear_read_wakelock = 0; if ((driver->data_ready[index] & USER_SPACE_DATA_TYPE) && (driver-> logging_mode == MEMORY_DEVICE_MODE)) { remote_token = 0; @@ -1442,14 +1456,12 @@ drop: COPY_USER_SPACE_OR_EXIT(buf+ret, *(data->buf_in_1), data->write_ptr_1->length); - if (!driver->real_time_mode) { - process_lock_on_copy(&data->nrt_lock); - clear_read_wakelock++; - } spin_lock_irqsave(&data->in_busy_lock, flags); data->in_busy_1 = 0; spin_unlock_irqrestore(&data->in_busy_lock, flags); + diag_ws_on_copy(DIAG_WS_MD); + copy_data = 1; } if (data->in_busy_2 == 1) { num_data++; @@ -1460,14 +1472,12 @@ drop: COPY_USER_SPACE_OR_EXIT(buf+ret, *(data->buf_in_2), data->write_ptr_2->length); - if (!driver->real_time_mode) { - process_lock_on_copy(&data->nrt_lock); - clear_read_wakelock++; - } spin_lock_irqsave(&data->in_busy_lock, flags); data->in_busy_2 = 0; spin_unlock_irqrestore(&data->in_busy_lock, flags); + diag_ws_on_copy(DIAG_WS_MD); + copy_data = 1; } } if (driver->supports_separate_cmdrsp) { @@ -1634,10 +1644,15 @@ drop: goto exit; } exit: - if (clear_read_wakelock) { + if (copy_data) { + /* + * Flush any work that is currently pending on the data + * channels. This will ensure that the next read is not missed. + */ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) - process_lock_on_copy_complete( - &driver->smd_data[i].nrt_lock); + flush_workqueue(driver->smd_data[i].wq); + wake_up(&driver->smd_wait_q); + diag_ws_on_copy_complete(DIAG_WS_MD); } mutex_unlock(&driver->diagchar_mutex); return ret; @@ -2112,6 +2127,172 @@ fail_free_copy: return ret; } +void diag_ws_init() +{ + driver->dci_ws.ref_count = 0; + driver->dci_ws.copy_count = 0; + spin_lock_init(&driver->dci_ws.lock); + + driver->md_ws.ref_count = 0; + driver->md_ws.copy_count = 0; + spin_lock_init(&driver->md_ws.lock); + + spin_lock_init(&driver->ws_lock); +} + +void diag_ws_on_notify() +{ + /* + * Do not deal with reference count here as there can be spurious + * interrupts. + */ + pm_stay_awake(driver->diag_dev); +} + +void diag_ws_on_read(int type, int pkt_len) +{ + unsigned long flags; + struct diag_ws_ref_t *ws_ref = NULL; + + switch (type) { + case DIAG_WS_DCI: + ws_ref = &driver->dci_ws; + break; + case DIAG_WS_MD: + ws_ref = &driver->md_ws; + break; + default: + pr_err_ratelimited("diag: In %s, invalid type: %d\n", + __func__, type); + return; + } + + spin_lock_irqsave(&ws_ref->lock, flags); + if (pkt_len > 0) { + ws_ref->ref_count++; + } else { + if (ws_ref->ref_count < 1) { + ws_ref->ref_count = 0; + ws_ref->copy_count = 0; + } + diag_ws_release(); + } + spin_unlock_irqrestore(&ws_ref->lock, flags); +} + + +void diag_ws_on_copy(int type) +{ + unsigned long flags; + struct diag_ws_ref_t *ws_ref = NULL; + + switch (type) { + case DIAG_WS_DCI: + ws_ref = &driver->dci_ws; + break; + case DIAG_WS_MD: + ws_ref = &driver->md_ws; + break; + default: + pr_err_ratelimited("diag: In %s, invalid type: %d\n", + __func__, type); + return; + } + + spin_lock_irqsave(&ws_ref->lock, flags); + ws_ref->copy_count++; + spin_unlock_irqrestore(&ws_ref->lock, flags); +} + +void diag_ws_on_copy_fail(int type) +{ + unsigned long flags; + struct diag_ws_ref_t *ws_ref = NULL; + + switch (type) { + case DIAG_WS_DCI: + ws_ref = &driver->dci_ws; + break; + case DIAG_WS_MD: + ws_ref = &driver->md_ws; + break; + default: + pr_err_ratelimited("diag: In %s, invalid type: %d\n", + __func__, type); + return; + } + + spin_lock_irqsave(&ws_ref->lock, flags); + ws_ref->ref_count--; + spin_unlock_irqrestore(&ws_ref->lock, flags); + + diag_ws_release(); +} + +void diag_ws_on_copy_complete(int type) +{ + unsigned long flags; + struct diag_ws_ref_t *ws_ref = NULL; + + switch (type) { + case DIAG_WS_DCI: + ws_ref = &driver->dci_ws; + break; + case DIAG_WS_MD: + ws_ref = &driver->md_ws; + break; + default: + pr_err_ratelimited("diag: In %s, invalid type: %d\n", + __func__, type); + return; + } + + spin_lock_irqsave(&ws_ref->lock, flags); + ws_ref->ref_count -= ws_ref->copy_count; + if (ws_ref->ref_count < 1) + ws_ref->ref_count = 0; + ws_ref->copy_count = 0; + spin_unlock_irqrestore(&ws_ref->lock, flags); + + diag_ws_release(); +} + +void diag_ws_reset(int type) +{ + unsigned long flags; + struct diag_ws_ref_t *ws_ref = NULL; + + switch (type) { + case DIAG_WS_DCI: + ws_ref = &driver->dci_ws; + break; + case DIAG_WS_MD: + ws_ref = &driver->md_ws; + break; + default: + pr_err_ratelimited("diag: In %s, invalid type: %d\n", + __func__, type); + return; + } + + spin_lock_irqsave(&ws_ref->lock, flags); + ws_ref->ref_count = 0; + ws_ref->copy_count = 0; + spin_unlock_irqrestore(&ws_ref->lock, flags); + + diag_ws_release(); +} + +void diag_ws_release() +{ + unsigned long flags; + + spin_lock_irqsave(&driver->ws_lock, flags); + if (driver->dci_ws.ref_count == 0 && driver->md_ws.ref_count == 0) + pm_relax(driver->diag_dev); + spin_unlock_irqrestore(&driver->ws_lock, flags); +} + static int diag_real_time_info_init(void) { int i; @@ -2352,6 +2533,7 @@ static int __init diagchar_init(void) init_waitqueue_head(&driver->wait_q); init_waitqueue_head(&driver->smd_wait_q); INIT_WORK(&(driver->diag_drain_work), diag_drain_work_fn); + diag_ws_init(); ret = diag_real_time_info_init(); if (ret) goto fail; diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c index c2962692019a..8f44514b21ba 100644 --- a/drivers/char/diag/diagfwd.c +++ b/drivers/char/diag/diagfwd.c @@ -333,93 +333,6 @@ static int check_bufsize_for_encoding(struct diag_smd_info *smd_info, void *buf, return buf_size; } -void process_lock_enabling(struct diag_nrt_wake_lock *lock, int real_time) -{ - unsigned long read_lock_flags; - - spin_lock_irqsave(&lock->read_spinlock, read_lock_flags); - if (real_time) - lock->enabled = 0; - else - lock->enabled = 1; - lock->ref_count = 0; - lock->copy_count = 0; - wake_unlock(&lock->read_lock); - spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags); -} - -void process_lock_on_notify(struct diag_nrt_wake_lock *lock) -{ - unsigned long read_lock_flags; - - spin_lock_irqsave(&lock->read_spinlock, read_lock_flags); - /* - * Do not work with ref_count here in case - * of spurious interrupt - */ - if (lock->enabled && !wake_lock_active(&lock->read_lock)) - wake_lock(&lock->read_lock); - spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags); -} - -void process_lock_on_read(struct diag_nrt_wake_lock *lock, int pkt_len) -{ - unsigned long read_lock_flags; - - spin_lock_irqsave(&lock->read_spinlock, read_lock_flags); - if (lock->enabled) { - if (pkt_len > 0) { - /* - * We have an data that is read that - * needs to be processed, make sure the - * processor does not go to sleep - */ - lock->ref_count++; - if (!wake_lock_active(&lock->read_lock)) - wake_lock(&lock->read_lock); - } else { - /* - * There was no data associated with the - * read from the smd, unlock the wake lock - * if it is not needed. - */ - if (lock->ref_count < 1) { - if (wake_lock_active(&lock->read_lock)) - wake_unlock(&lock->read_lock); - lock->ref_count = 0; - lock->copy_count = 0; - } - } - } - spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags); -} - -void process_lock_on_copy(struct diag_nrt_wake_lock *lock) -{ - unsigned long read_lock_flags; - - spin_lock_irqsave(&lock->read_spinlock, read_lock_flags); - if (lock->enabled) - lock->copy_count++; - spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags); -} - -void process_lock_on_copy_complete(struct diag_nrt_wake_lock *lock) -{ - unsigned long read_lock_flags; - - spin_lock_irqsave(&lock->read_spinlock, read_lock_flags); - if (lock->enabled) { - lock->ref_count -= lock->copy_count; - if (lock->ref_count < 1) { - wake_unlock(&lock->read_lock); - lock->ref_count = 0; - } - lock->copy_count = 0; - } - spin_unlock_irqrestore(&lock->read_spinlock, read_lock_flags); -} - /* Process the data read from the smd data channel */ int diag_process_smd_read_data(struct diag_smd_info *smd_info, void *buf, int total_recd) @@ -435,10 +348,9 @@ int diag_process_smd_read_data(struct diag_smd_info *smd_info, void *buf, */ if ((smd_info->type == SMD_CMD_TYPE) && !driver->separate_cmdrsp[smd_info->peripheral]) { - /* This print is for debugging */ - pr_err("diag, In %s, received data on non-designated command channel: %d\n", + pr_debug("diag, In %s, received data on non-designated command channel: %d\n", __func__, smd_info->peripheral); - return 0; + goto fail_return; } /* If the data is already hdlc encoded */ @@ -511,6 +423,14 @@ int diag_process_smd_read_data(struct diag_smd_info *smd_info, void *buf, } } + if (err) { +fail_return: + if (smd_info->type == SMD_DATA_TYPE && + driver->logging_mode == MEMORY_DEVICE_MODE) { + diag_ws_on_copy_fail(DIAG_WS_MD); + } + } + return 0; } @@ -649,9 +569,8 @@ void diag_smd_send_req(struct diag_smd_info *smd_info) buf_size = smd_info->buf_in_1_size; } - if (!buf && (smd_info->type == SMD_DCI_TYPE || - smd_info->type == SMD_DCI_CMD_TYPE)) - diag_dci_try_deactivate_wakeup_source(); + if (!buf) + goto fail_return; if (smd_info->ch && buf) { int required_size = 0; @@ -743,14 +662,11 @@ void diag_smd_send_req(struct diag_smd_info *smd_info) } - if (pkt_len == 0 && (smd_info->type == SMD_DCI_TYPE || - smd_info->type == SMD_DCI_CMD_TYPE)) - diag_dci_try_deactivate_wakeup_source(); - - if (!driver->real_time_mode && smd_info->type == SMD_DATA_TYPE) - process_lock_on_read(&smd_info->nrt_lock, pkt_len); - if (total_recd > 0) { + if (smd_info->type == SMD_DATA_TYPE && + driver->logging_mode == MEMORY_DEVICE_MODE) + diag_ws_on_read(DIAG_WS_MD, total_recd); + if (!buf) { pr_err("diag: In %s, SMD peripheral: %d, Out of diagmem for Modem\n", __func__, smd_info->peripheral); @@ -769,6 +685,8 @@ void diag_smd_send_req(struct diag_smd_info *smd_info) diag_smd_notify(smd_info, SMD_EVENT_DATA); } + } else { + goto fail_return; } } else if (smd_info->ch && !buf && (driver->logging_mode == MEMORY_DEVICE_MODE)) { @@ -778,8 +696,9 @@ void diag_smd_send_req(struct diag_smd_info *smd_info) fail_return: if (smd_info->type == SMD_DCI_TYPE || - smd_info->type == SMD_DCI_CMD_TYPE) - diag_dci_try_deactivate_wakeup_source(); + smd_info->type == SMD_DCI_CMD_TYPE || + driver->logging_mode == MEMORY_DEVICE_MODE) + diag_ws_release(); return; } @@ -2187,17 +2106,19 @@ void diag_smd_notify(void *ctxt, unsigned event) diag_dci_notify_client(smd_info->peripheral_mask, DIAG_STATUS_OPEN, DCI_LOCAL_PROC); } - } else if (event == SMD_EVENT_DATA && !driver->real_time_mode && - smd_info->type == SMD_DATA_TYPE) { - process_lock_on_notify(&smd_info->nrt_lock); + } else if (event == SMD_EVENT_DATA) { + if ((smd_info->type == SMD_DCI_TYPE) || + (smd_info->type == SMD_DCI_CMD_TYPE) || + (smd_info->type == SMD_DATA_TYPE && + driver->logging_mode == MEMORY_DEVICE_MODE)) { + diag_ws_on_notify(); + } } wake_up(&driver->smd_wait_q); if (smd_info->type == SMD_DCI_TYPE || smd_info->type == SMD_DCI_CMD_TYPE) { - if (event == SMD_EVENT_DATA) - diag_dci_try_activate_wakeup_source(); queue_work(driver->diag_dci_wq, &(smd_info->diag_read_smd_work)); } else if (smd_info->type == SMD_DATA_TYPE) { @@ -2333,10 +2254,8 @@ int device_supports_separate_cmdrsp(void) void diag_smd_destructor(struct diag_smd_info *smd_info) { - if (smd_info->type == SMD_DATA_TYPE) { - wake_lock_destroy(&smd_info->nrt_lock.read_lock); + if (smd_info->type == SMD_DATA_TYPE) destroy_workqueue(smd_info->wq); - } if (smd_info->ch) smd_close(smd_info->ch); @@ -2559,30 +2478,6 @@ int diag_smd_constructor(struct diag_smd_info *smd_info, int peripheral, goto err; } - smd_info->nrt_lock.enabled = 0; - smd_info->nrt_lock.ref_count = 0; - smd_info->nrt_lock.copy_count = 0; - if (type == SMD_DATA_TYPE) { - spin_lock_init(&smd_info->nrt_lock.read_spinlock); - - switch (peripheral) { - case MODEM_DATA: - wake_lock_init(&smd_info->nrt_lock.read_lock, - WAKE_LOCK_SUSPEND, "diag_nrt_modem_read"); - break; - case LPASS_DATA: - wake_lock_init(&smd_info->nrt_lock.read_lock, - WAKE_LOCK_SUSPEND, "diag_nrt_lpass_read"); - break; - case WCNSS_DATA: - wake_lock_init(&smd_info->nrt_lock.read_lock, - WAKE_LOCK_SUSPEND, "diag_nrt_wcnss_read"); - break; - default: - break; - } - } - return 0; err: if (smd_info->wq) diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h index 2e701fc94ec1..94856697f64b 100644 --- a/drivers/char/diag/diagfwd.h +++ b/drivers/char/diag/diagfwd.h @@ -26,11 +26,6 @@ int diagfwd_init(void); void diagfwd_exit(void); void diag_process_hdlc(void *data, unsigned len); void diag_smd_send_req(struct diag_smd_info *smd_info); -void process_lock_enabling(struct diag_nrt_wake_lock *lock, int real_time); -void process_lock_on_notify(struct diag_nrt_wake_lock *lock); -void process_lock_on_read(struct diag_nrt_wake_lock *lock, int pkt_len); -void process_lock_on_copy(struct diag_nrt_wake_lock *lock); -void process_lock_on_copy_complete(struct diag_nrt_wake_lock *lock); void diag_usb_legacy_notifier(void *, unsigned, struct diag_request *); long diagchar_ioctl(struct file *, unsigned int, unsigned long); int diag_device_write(void *, int, struct diag_request *); diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c index 6c8096bb5aa7..2e946798294d 100644 --- a/drivers/char/diag/diagfwd_cntl.c +++ b/drivers/char/diag/diagfwd_cntl.c @@ -549,7 +549,6 @@ void diag_send_diag_mode_update_by_smd(struct diag_smd_info *smd_info, pr_err("diag: ch invalid, feature update on proc %d\n", smd_info->peripheral); } - process_lock_enabling(&data->nrt_lock, real_time); mutex_unlock(&driver->diag_cntl_mutex); } diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c index 20e6a8ebd3b7..0c17b711f4d9 100644 --- a/drivers/char/diag/diagfwd_hsic.c +++ b/drivers/char/diag/diagfwd_hsic.c @@ -287,10 +287,14 @@ static void diag_hsic_read_complete_callback(void *ctxt, char *buf, * appropriate device, e.g. USB MDM channel */ diag_bridge[index].write_len = actual_size; + if (driver->logging_mode == MEMORY_DEVICE_MODE) + diag_ws_on_notify(); err = diag_device_write((void *)buf, index+HSIC_DATA, NULL); /* If an error, return buffer to the pool */ if (err) { + if (driver->logging_mode == MEMORY_DEVICE_MODE) + diag_ws_release(); diagmem_free(driver, buf, index + POOL_TYPE_HSIC); if (__ratelimit(&rl)) @@ -344,7 +348,7 @@ static void diag_hsic_dci_read_complete_callback(void *ctxt, char *buf, if (!buf) { pr_err("diag: Out of diagmem for HSIC\n"); } else { - diag_dci_try_activate_wakeup_source(); + diag_ws_on_notify(); diag_hsic_dci[index].data_len = actual_size; diag_hsic_dci[index].data_buf = buf; memcpy(diag_hsic_dci[index].data, buf, actual_size); |