diff options
Diffstat (limited to 'drivers/char/diag')
-rw-r--r-- | drivers/char/diag/diag_masks.c | 9 | ||||
-rw-r--r-- | drivers/char/diag/diag_usb.c | 6 | ||||
-rw-r--r-- | drivers/char/diag/diagchar.h | 3 | ||||
-rw-r--r-- | drivers/char/diag/diagchar_core.c | 35 | ||||
-rw-r--r-- | drivers/char/diag/diagfwd.c | 17 |
5 files changed, 60 insertions, 10 deletions
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c index 7cb64e012f1f..a1721a3b80cc 100644 --- a/drivers/char/diag/diag_masks.c +++ b/drivers/char/diag/diag_masks.c @@ -1780,6 +1780,15 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count, if (!mask_info) return -EIO; + mutex_lock(&driver->diag_maskclear_mutex); + if (driver->mask_clear) { + DIAG_LOG(DIAG_DEBUG_PERIPHERALS, + "diag:%s: count = %zu\n", __func__, count); + mutex_unlock(&driver->diag_maskclear_mutex); + return -EIO; + } + mutex_unlock(&driver->diag_maskclear_mutex); + mutex_lock(&mask_info->lock); mask = (struct diag_msg_mask_t *)(mask_info->ptr); for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) { diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c index eb715cc8501c..ca54b24ec604 100644 --- a/drivers/char/diag/diag_usb.c +++ b/drivers/char/diag/diag_usb.c @@ -215,6 +215,12 @@ static void usb_connect_work_fn(struct work_struct *work) */ static void usb_disconnect(struct diag_usb_info *ch) { + if (!ch) + return; + + if (!atomic_read(&ch->connected) && driver->usb_connected) + diag_clear_masks(NULL); + if (ch && ch->ops && ch->ops->close) ch->ops->close(ch->ctxt, DIAG_USB_MODE); } diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h index dccaa6a0d9c4..2aef98f4fe04 100644 --- a/drivers/char/diag/diagchar.h +++ b/drivers/char/diag/diagchar.h @@ -467,6 +467,8 @@ struct diagchar_dev { struct class *diagchar_class; struct device *diag_dev; int ref_count; + int mask_clear; + struct mutex diag_maskclear_mutex; struct mutex diagchar_mutex; struct mutex diag_file_mutex; wait_queue_head_t wait_q; @@ -625,6 +627,7 @@ void diag_cmd_remove_reg(struct diag_cmd_reg_entry_t *entry, uint8_t proc); void diag_cmd_remove_reg_by_pid(int pid); void diag_cmd_remove_reg_by_proc(int proc); int diag_cmd_chk_polling(struct diag_cmd_reg_entry_t *entry); +void diag_clear_masks(struct diag_md_session_t *info); void diag_record_stats(int type, int flag); diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index a39e4929d999..9ed43cdc3845 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -389,6 +389,27 @@ static uint32_t diag_translate_kernel_to_user_mask(uint32_t peripheral_mask) return ret; } +void diag_clear_masks(struct diag_md_session_t *info) +{ + int ret; + char cmd_disable_log_mask[] = { 0x73, 0, 0, 0, 0, 0, 0, 0}; + char cmd_disable_msg_mask[] = { 0x7D, 0x05, 0, 0, 0, 0, 0, 0}; + char cmd_disable_event_mask[] = { 0x60, 0}; + + DIAG_LOG(DIAG_DEBUG_PERIPHERALS, + "diag: %s: masks clear request upon %s\n", __func__, + ((info) ? "ODL exit" : "USB Disconnection")); + + ret = diag_process_apps_masks(cmd_disable_log_mask, + sizeof(cmd_disable_log_mask), info); + ret = diag_process_apps_masks(cmd_disable_msg_mask, + sizeof(cmd_disable_msg_mask), info); + ret = diag_process_apps_masks(cmd_disable_event_mask, + sizeof(cmd_disable_event_mask), info); + DIAG_LOG(DIAG_DEBUG_PERIPHERALS, + "diag:%s: masks cleared successfully\n", __func__); +} + static void diag_close_logging_process(const int pid) { int i; @@ -400,6 +421,12 @@ static void diag_close_logging_process(const int pid) if (!session_info) return; + diag_clear_masks(session_info); + + mutex_lock(&driver->diag_maskclear_mutex); + driver->mask_clear = 1; + mutex_unlock(&driver->diag_maskclear_mutex); + session_peripheral_mask = session_info->peripheral_mask; diag_md_session_close(session_info); for (i = 0; i < NUM_MD_SESSIONS; i++) @@ -475,9 +502,14 @@ static int diag_remove_client_entry(struct file *file) } static int diagchar_close(struct inode *inode, struct file *file) { + int ret; DIAG_LOG(DIAG_DEBUG_USERSPACE, "diag: process exit %s\n", current->comm); - return diag_remove_client_entry(file); + ret = diag_remove_client_entry(file); + mutex_lock(&driver->diag_maskclear_mutex); + driver->mask_clear = 0; + mutex_unlock(&driver->diag_maskclear_mutex); + return ret; } void diag_record_stats(int type, int flag) @@ -3358,6 +3390,7 @@ static int __init diagchar_init(void) non_hdlc_data.len = 0; mutex_init(&driver->hdlc_disable_mutex); mutex_init(&driver->diagchar_mutex); + mutex_init(&driver->diag_maskclear_mutex); mutex_init(&driver->diag_file_mutex); mutex_init(&driver->delayed_rsp_mutex); mutex_init(&apps_data_mutex); diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c index 8205e5b05d85..0111b02634c8 100644 --- a/drivers/char/diag/diagfwd.c +++ b/drivers/char/diag/diagfwd.c @@ -1232,8 +1232,6 @@ static int diagfwd_mux_open(int id, int mode) static int diagfwd_mux_close(int id, int mode) { - uint8_t i; - switch (mode) { case DIAG_USB_MODE: driver->usb_connected = 0; @@ -1248,15 +1246,16 @@ static int diagfwd_mux_close(int id, int mode) driver->md_session_mode == DIAG_MD_NONE) || (driver->md_session_mode == DIAG_MD_PERIPHERAL)) { /* - * In this case the channel must not be closed. This case - * indicates that the USB is removed but there is a client - * running in background with Memory Device mode + * This case indicates that the USB is removed + * but there is a client running in background + * with Memory Device mode. */ } else { - for (i = 0; i < NUM_PERIPHERALS; i++) { - diagfwd_close(i, TYPE_DATA); - diagfwd_close(i, TYPE_CMD); - } + /* + * With clearing of masks on ODL exit and + * USB disconnection, closing of the channel is + * not needed.This enables read and drop of stale packets. + */ /* Re enable HDLC encoding */ pr_debug("diag: In %s, re-enabling HDLC encoding\n", __func__); |