static int diagchar_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int index = -1, i = 0, ret = 0; int num_data = 0, data_type; for (i = 0; i < driver->num_clients; i++) if (driver->client_map[i].pid == current->tgid) index = i; if (index == -1) { pr_err("diag: Client PID not found in table"); return -EINVAL; } wait_event_interruptible(driver->wait_q, driver->data_ready[index]); mutex_lock(&driver->diagchar_mutex); if ((driver->data_ready[index] & USER_SPACE_LOG_TYPE) && (driver-> logging_mode == MEMORY_DEVICE_MODE)) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & USER_SPACE_LOG_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); /* place holder for number of data field */ ret += 4; for (i = 0; i < driver->poolsize_write_struct; i++) { if (driver->buf_tbl[i].length > 0) { #ifdef DIAG_DEBUG pr_debug("diag: WRITING the buf address " "and length is %x , %d\n", (unsigned int) (driver->buf_tbl[i].buf), driver->buf_tbl[i].length); #endif num_data++; /* Copy the length of data being passed */ if (copy_to_user(buf+ret, (void *)&(driver-> buf_tbl[i].length), 4)) { num_data--; goto drop; } ret += 4; /* Copy the actual data being passed */ if (copy_to_user(buf+ret, (void *)driver-> buf_tbl[i].buf, driver->buf_tbl[i].length)) { ret -= 4; num_data--; goto drop; } ret += driver->buf_tbl[i].length; drop: #ifdef DIAG_DEBUG pr_debug("diag: DEQUEUE buf address and" " length is %x,%d\n", (unsigned int) (driver->buf_tbl[i].buf), driver-> buf_tbl[i].length); #endif diagmem_free(driver, (unsigned char *) (driver->buf_tbl[i].buf), POOL_TYPE_HDLC); driver->buf_tbl[i].length = 0; driver->buf_tbl[i].buf = 0; } } /* copy modem data */ if (driver->in_busy_1 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_1->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->buf_in_1), driver->write_ptr_1->length); driver->in_busy_1 = 0; } if (driver->in_busy_2 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_2->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->buf_in_2), driver->write_ptr_2->length); driver->in_busy_2 = 0; } /* copy lpass data */ if (driver->in_busy_qdsp_1 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_qdsp_1->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_qdsp_1), driver->write_ptr_qdsp_1->length); driver->in_busy_qdsp_1 = 0; } if (driver->in_busy_qdsp_2 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_qdsp_2->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_qdsp_2), driver-> write_ptr_qdsp_2->length); driver->in_busy_qdsp_2 = 0; } /* copy wncss data */ if (driver->in_busy_wcnss == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_wcnss->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_wcnss), driver->write_ptr_wcnss->length); driver->in_busy_wcnss = 0; } #ifdef CONFIG_DIAG_SDIO_PIPE /* copy 9K data over SDIO */ if (driver->in_busy_sdio == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_mdm->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->buf_in_sdio), driver->write_ptr_mdm->length); driver->in_busy_sdio = 0; } #endif /* copy number of data fields */ COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4); ret -= 4; driver->data_ready[index] ^= USER_SPACE_LOG_TYPE; if (driver->ch) queue_work(driver->diag_wq, &(driver->diag_read_smd_work)); if (driver->chqdsp) queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work)); if (driver->ch_wcnss) queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work)); #ifdef CONFIG_DIAG_SDIO_PIPE if (driver->sdio_ch) queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); #endif APPEND_DEBUG('n'); goto exit; } else if (driver->data_ready[index] & USER_SPACE_LOG_TYPE) { /* 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_LOG_TYPE; } if (driver->data_ready[index] & DEINIT_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & DEINIT_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); driver->data_ready[index] ^= DEINIT_TYPE; goto exit; } if (driver->data_ready[index] & MSG_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & MSG_MASKS_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->msg_masks), MSG_MASK_SIZE); driver->data_ready[index] ^= MSG_MASKS_TYPE; goto exit; } if (driver->data_ready[index] & EVENT_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & EVENT_MASKS_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->event_masks), EVENT_MASK_SIZE); driver->data_ready[index] ^= EVENT_MASKS_TYPE; goto exit; } if (driver->data_ready[index] & LOG_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & LOG_MASKS_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->log_masks), LOG_MASK_SIZE); driver->data_ready[index] ^= LOG_MASKS_TYPE; goto exit; } if (driver->data_ready[index] & PKT_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & PKT_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->pkt_buf), driver->pkt_length); driver->data_ready[index] ^= PKT_TYPE; goto exit; } exit: mutex_unlock(&driver->diagchar_mutex); return ret; }
static int diagchar_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int index = -1, i = 0, ret = 0; int num_data = 0, data_type; #ifdef SDQXDM_DEBUG struct timeval t; #endif /* printk(KERN_INFO "%s:%s(parent:%s): tgid=%d\n", __func__, current->comm, current->parent->comm, current->tgid); */ for (i = 0; i < driver->num_clients; i++) if (driver->client_map[i].pid == current->tgid) index = i; if (index == -1) { DIAG_ERR("\n Client PID not found in table"); return -EINVAL; } wait_event_interruptible(driver->wait_q, driver->data_ready[index]); mutex_lock(&driver->diagchar_mutex); if ((driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE) && (driver-> logging_mode == MEMORY_DEVICE_MODE)) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); /* place holder for number of data field */ ret += 4; for (i = 0; i < driver->poolsize_write_struct; i++) { if (driver->buf_tbl[i].length > 0) { #ifdef DIAG_DEBUG printk(KERN_INFO "\n WRITING the buf address " "and length is %x , %d\n", (unsigned int) (driver->buf_tbl[i].buf), driver->buf_tbl[i].length); #endif num_data++; /* Copy the length of data being passed */ if (copy_to_user(buf+ret, (void *)&(driver-> buf_tbl[i].length), 4)) { num_data--; goto drop; } ret += 4; /* Copy the actual data being passed */ if (copy_to_user(buf+ret, (void *)driver-> buf_tbl[i].buf, driver->buf_tbl[i].length)) { ret -= 4; num_data--; goto drop; } ret += driver->buf_tbl[i].length; drop: #ifdef DIAG_DEBUG printk(KERN_INFO "\n DEQUEUE buf address and" " length is %x,%d\n", (unsigned int) (driver->buf_tbl[i].buf), driver-> buf_tbl[i].length); #endif diagmem_free(driver, (unsigned char *) (driver->buf_tbl[i].buf), POOL_TYPE_HDLC); driver->buf_tbl[i].length = 0; driver->buf_tbl[i].buf = 0; } } /* copy modem data */ if (driver->in_busy_1 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_1->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->buf_in_1), driver->write_ptr_1->length); driver->in_busy_1 = 0; } if (driver->in_busy_2 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_2->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->buf_in_2), driver->write_ptr_2->length); driver->in_busy_2 = 0; } /* copy q6 data */ if (driver->in_busy_qdsp_1 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_qdsp_1->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_qdsp_1), driver->write_ptr_qdsp_1->length); driver->in_busy_qdsp_1 = 0; } if (driver->in_busy_qdsp_2 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_qdsp_2->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_qdsp_2), driver-> write_ptr_qdsp_2->length); driver->in_busy_qdsp_2 = 0; } #if 0 /* def CONFIG_ARCH_MSM8X60_LTE */ if (driver->in_busy_sdio == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_mdm->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_sdio), driver-> write_ptr_mdm->length); driver->in_busy_sdio = 0; } #endif /* copy number of data fields */ COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4); ret -= 4; driver->data_ready[index] ^= MEMORY_DEVICE_LOG_TYPE; #if 0 /* def CONFIG_ARCH_MSM8X60_LTE */ if (mdm_diag) { if (driver->sdio_ch) queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); } #endif if (driver->ch) queue_work(driver->diag_wq, &(driver->diag_read_smd_work)); if (driver->chqdsp) queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work)); APPEND_DEBUG('n'); goto exit; } else if (driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE) { /* 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] ^= MEMORY_DEVICE_LOG_TYPE; } else if (driver->data_ready[index] & USERMODE_DIAGFWD) { data_type = USERMODE_DIAGFWD; driver->data_ready[index] ^= USERMODE_DIAGFWD; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); #ifdef SDQXDM_DEBUG do_gettimeofday(&t); if (driver->in_busy_1 && t.tv_sec > driver->write_ptr_1->second + 2) pr_info("[diag-dbg] late pkt now: %ld.%04ld pkt: %d\n", t.tv_sec, t.tv_usec/1000, driver->write_ptr_1->second); if (driver->in_busy_2 && t.tv_sec > driver->write_ptr_2->second + 2) pr_info("[diag-dbg] late pkt now: %ld.%04ld pkt: %d\n", t.tv_sec, t.tv_usec/1000, driver->write_ptr_2->second); #endif /* copy modem data */ if (driver->in_busy_1 == 1) { /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->buf_in_1), driver->write_ptr_1->length); driver->in_busy_1 = 0; } if (driver->in_busy_2 == 1) { /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->buf_in_2), driver->write_ptr_2->length); driver->in_busy_2 = 0; } /* copy q6 data */ if (driver->in_busy_qdsp_1 == 1) { /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_qdsp_1), driver->write_ptr_qdsp_1->length); driver->in_busy_qdsp_1 = 0; } if (driver->in_busy_qdsp_2 == 1) { /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_qdsp_2), driver-> write_ptr_qdsp_2->length); driver->in_busy_qdsp_2 = 0; } #if 0 /* def CONFIG_ARCH_MSM8X60_LTE */ if (driver->in_busy_sdio == 1) { /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_sdio), driver-> write_ptr_mdm->length); driver->in_busy_sdio = 0; } if (mdm_diag) { if (driver->sdio_ch) queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); } #endif if (driver->ch) queue_work(driver->diag_wq, &(driver->diag_read_smd_work)); if (driver->chqdsp) queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work)); #ifdef DIAG_DEBUG pr_info("%s() return %d byte\n", __func__, ret); #endif goto exit; } if (driver->data_ready[index] & DEINIT_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & DEINIT_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); driver->data_ready[index] ^= DEINIT_TYPE; goto exit; } if (driver->data_ready[index] & MSG_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & MSG_MASKS_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->msg_masks), MSG_MASK_SIZE); driver->data_ready[index] ^= MSG_MASKS_TYPE; goto exit; } if (driver->data_ready[index] & EVENT_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & EVENT_MASKS_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->event_masks), EVENT_MASK_SIZE); driver->data_ready[index] ^= EVENT_MASKS_TYPE; goto exit; } if (driver->data_ready[index] & LOG_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & LOG_MASKS_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->log_masks), LOG_MASK_SIZE); driver->data_ready[index] ^= LOG_MASKS_TYPE; goto exit; } if (driver->data_ready[index] & PKT_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & PKT_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->pkt_buf), driver->pkt_length); driver->data_ready[index] ^= PKT_TYPE; goto exit; } exit: if (ret) wake_lock_timeout(&driver->wake_lock, HZ / 2); mutex_unlock(&driver->diagchar_mutex); return ret; }
static int diagchar_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int index = -1, i = 0, ret = 0; int num_data = 0, data_type; for (i = 0; i < driver->num_clients; i++) if (driver->client_map[i].pid == current->tgid) index = i; if (index == -1) { pr_err("diag: Client PID not found in table"); return -EINVAL; } wait_event_interruptible(driver->wait_q, driver->data_ready[index]); mutex_lock(&driver->diagchar_mutex); if ((driver->data_ready[index] & USER_SPACE_LOG_TYPE) && (driver-> logging_mode == MEMORY_DEVICE_MODE)) { #ifdef CONFIG_DIAG_BRIDGE_CODE unsigned long spin_lock_flags; struct diag_write_device hsic_buf_tbl[NUM_HSIC_BUF_TBL_ENTRIES]; #endif pr_debug("diag: process woken up\n"); /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & USER_SPACE_LOG_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); /* place holder for number of data field */ ret += 4; for (i = 0; i < driver->poolsize_write_struct; i++) { if (driver->buf_tbl[i].length > 0) { #ifdef DIAG_DEBUG pr_debug("diag: WRITING the buf address " "and length is %x , %d\n", (unsigned int) (driver->buf_tbl[i].buf), driver->buf_tbl[i].length); #endif num_data++; /* Copy the length of data being passed */ if (copy_to_user(buf+ret, (void *)&(driver-> buf_tbl[i].length), 4)) { num_data--; goto drop; } ret += 4; /* Copy the actual data being passed */ if (copy_to_user(buf+ret, (void *)driver-> buf_tbl[i].buf, driver->buf_tbl[i].length)) { ret -= 4; num_data--; goto drop; } ret += driver->buf_tbl[i].length; drop: #ifdef DIAG_DEBUG pr_debug("diag: DEQUEUE buf address and" " length is %x,%d\n", (unsigned int) (driver->buf_tbl[i].buf), driver-> buf_tbl[i].length); #endif diagmem_free(driver, (unsigned char *) (driver->buf_tbl[i].buf), POOL_TYPE_HDLC); driver->buf_tbl[i].length = 0; driver->buf_tbl[i].buf = 0; } } /* copy modem data */ if (driver->in_busy_1 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_1->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->buf_in_1), driver->write_ptr_1->length); driver->in_busy_1 = 0; } if (driver->in_busy_2 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_2->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->buf_in_2), driver->write_ptr_2->length); driver->in_busy_2 = 0; } /* copy lpass data */ if (driver->in_busy_qdsp_1 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_qdsp_1->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_qdsp_1), driver->write_ptr_qdsp_1->length); driver->in_busy_qdsp_1 = 0; } if (driver->in_busy_qdsp_2 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_qdsp_2->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_qdsp_2), driver-> write_ptr_qdsp_2->length); driver->in_busy_qdsp_2 = 0; } /* copy wncss data */ if (driver->in_busy_wcnss_1 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_wcnss_1->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_wcnss_1), driver->write_ptr_wcnss_1->length); driver->in_busy_wcnss_1 = 0; } if (driver->in_busy_wcnss_2 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_wcnss_2->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_wcnss_2), driver->write_ptr_wcnss_2->length); driver->in_busy_wcnss_2 = 0; } #ifdef CONFIG_DIAG_SDIO_PIPE /* copy 9K data over SDIO */ if (driver->in_busy_sdio == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_mdm->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->buf_in_sdio), driver->write_ptr_mdm->length); driver->in_busy_sdio = 0; } #endif #ifdef CONFIG_DIAG_BRIDGE_CODE spin_lock_irqsave(&driver->hsic_spinlock, spin_lock_flags); for (i = 0; i < driver->poolsize_hsic_write; i++) { hsic_buf_tbl[i].buf = driver->hsic_buf_tbl[i].buf; driver->hsic_buf_tbl[i].buf = 0; hsic_buf_tbl[i].length = driver->hsic_buf_tbl[i].length; driver->hsic_buf_tbl[i].length = 0; } driver->num_hsic_buf_tbl_entries = 0; spin_unlock_irqrestore(&driver->hsic_spinlock, spin_lock_flags); for (i = 0; i < driver->poolsize_hsic_write; i++) { if (hsic_buf_tbl[i].length > 0) { pr_debug("diag: HSIC copy to user, i: %d, buf: %x, len: %d\n", i, (unsigned int)hsic_buf_tbl[i].buf, hsic_buf_tbl[i].length); num_data++; /* Copy the length of data being passed */ if (copy_to_user(buf+ret, (void *)&(hsic_buf_tbl[i].length), 4)) { num_data--; goto drop_hsic; } ret += 4; /* Copy the actual data being passed */ if (copy_to_user(buf+ret, (void *)hsic_buf_tbl[i].buf, hsic_buf_tbl[i].length)) { ret -= 4; num_data--; goto drop_hsic; } ret += hsic_buf_tbl[i].length; drop_hsic: /* Return the buffer to the pool */ diagmem_free(driver, (unsigned char *)(hsic_buf_tbl[i].buf), POOL_TYPE_HSIC); /* Call the write complete function */ diagfwd_write_complete_hsic(NULL); } } #endif /* copy number of data fields */ COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4); ret -= 4; driver->data_ready[index] ^= USER_SPACE_LOG_TYPE; if (driver->ch) queue_work(driver->diag_wq, &(driver->diag_read_smd_work)); if (driver->chqdsp) queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work)); if (driver->ch_wcnss) queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work)); #ifdef CONFIG_DIAG_SDIO_PIPE if (driver->sdio_ch) queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); #endif APPEND_DEBUG('n'); goto exit; } else if (driver->data_ready[index] & USER_SPACE_LOG_TYPE) { /* 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_LOG_TYPE; } if (driver->data_ready[index] & DEINIT_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & DEINIT_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); driver->data_ready[index] ^= DEINIT_TYPE; goto exit; } if (driver->data_ready[index] & MSG_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & MSG_MASKS_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->msg_masks), MSG_MASK_SIZE); driver->data_ready[index] ^= MSG_MASKS_TYPE; goto exit; } if (driver->data_ready[index] & EVENT_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & EVENT_MASKS_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->event_masks), EVENT_MASK_SIZE); driver->data_ready[index] ^= EVENT_MASKS_TYPE; goto exit; } if (driver->data_ready[index] & LOG_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & LOG_MASKS_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->log_masks), LOG_MASK_SIZE); driver->data_ready[index] ^= LOG_MASKS_TYPE; goto exit; } if (driver->data_ready[index] & PKT_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & PKT_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->pkt_buf), driver->pkt_length); driver->data_ready[index] ^= PKT_TYPE; goto exit; } if (driver->data_ready[index] & DCI_DATA_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & DCI_DATA_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, driver->write_ptr_dci->length, 4); /* check delayed vs immediate response */ if (*(uint8_t *)(driver->buf_in_dci+4) == DCI_CMD_CODE) COPY_USER_SPACE_OR_EXIT(buf+8, *(driver->buf_in_dci + 5), driver->write_ptr_dci->length); else COPY_USER_SPACE_OR_EXIT(buf+8, *(driver->buf_in_dci + 8), driver->write_ptr_dci->length); driver->in_busy_dci = 0; driver->data_ready[index] ^= DCI_DATA_TYPE; if (driver->ch_dci) queue_work(driver->diag_wq, &(driver->diag_read_smd_dci_work)); goto exit; } exit: mutex_unlock(&driver->diagchar_mutex); return ret; }
static int diagcharmdm_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int index = -1, i = 0, ret = 0; int num_data = 0, data_type; #if defined(CONFIG_MACH_MECHA) if (!sdio_diag_initialized) { DIAG_INFO("sdio diag isn't in embedded mode \n"); return 0; } #endif #ifdef DIAG_DEBUG DIAG_INFO("%s:%s(parent:%s): tgid=%d\n", __func__, current->comm, current->parent->comm, current->tgid); #endif for (i = 0; i < driver->num_mdmclients; i++) if (driver->mdmclient_map[i].pid == current->tgid) index = i; if (index == -1) { DIAG_ERR("\n Client PID not found in table"); return -EINVAL; } wait_event_interruptible(driver->mdmwait_q, driver->mdmdata_ready[index]); mutex_lock(&driver->diagcharmdm_mutex); if ((driver->mdmdata_ready[index] & MEMORY_DEVICE_LOG_TYPE) && (driver-> logging_mode == MEMORY_DEVICE_MODE)) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); /* place holder for number of data field */ ret += 4; #if defined(CONFIG_MACH_MECHA) /* copy modem data */ if (driver->in_busy_mdm_1 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_mdm_1->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->buf_in_mdm_1), driver->write_ptr_mdm_1->length); driver->in_busy_mdm_1 = 0; } if (driver->in_busy_mdm_2 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_mdm_2->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->buf_in_mdm_2), driver->write_ptr_mdm_2->length); driver->in_busy_mdm_2 = 0; } #endif #ifdef CONFIG_ARCH_MSM8X60_LTE if (driver->in_busy_sdio_1 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_mdm_1->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_sdio_1), driver-> write_ptr_mdm_1->length); driver->in_busy_sdio_1 = 0; } if (driver->in_busy_sdio_2 == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->write_ptr_mdm_2->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_sdio_2), driver-> write_ptr_mdm_2->length); driver->in_busy_sdio_2 = 0; } #endif /* copy number of data fields */ COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4); ret -= 4; driver->mdmdata_ready[index] ^= MEMORY_DEVICE_LOG_TYPE; #ifdef CONFIG_MACH_MECHA queue_work(driver->mdm_diag_workqueue, &(driver->diag_read_smd_mdm_work)); #endif #ifdef CONFIG_ARCH_MSM8X60_LTE if (driver->sdio_ch) queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); #endif goto exit; } else if (driver->mdmdata_ready[index] & MEMORY_DEVICE_LOG_TYPE) { /* In case, the thread wakes up and the logging mode is not memory device any more, the condition needs to be cleared */ driver->mdmdata_ready[index] ^= MEMORY_DEVICE_LOG_TYPE; } #ifdef CONFIG_ARCH_MSM8X60_LTE else if (driver->mdmdata_ready[index] & USERMODE_DIAGFWD) { data_type = USERMODE_DIAGFWD; driver->mdmdata_ready[index] ^= USERMODE_DIAGFWD; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); if (driver->in_busy_sdio_1 == 1) { /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_sdio_1), driver-> write_ptr_mdm_1->length); driver->in_busy_sdio_1 = 0; } if (driver->in_busy_sdio_2 == 1) { /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> buf_in_sdio_2), driver-> write_ptr_mdm_2->length); driver->in_busy_sdio_2 = 0; } if (driver->sdio_ch) queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); goto exit; } #endif if (driver->mdmdata_ready[index] & DEINIT_TYPE) { driver->mdmdata_ready[index] ^= DEINIT_TYPE; goto exit; } if (driver->mdmdata_ready[index] & MSG_MASKS_TYPE) { driver->mdmdata_ready[index] ^= MSG_MASKS_TYPE; goto exit; } if (driver->mdmdata_ready[index] & EVENT_MASKS_TYPE) { driver->mdmdata_ready[index] ^= EVENT_MASKS_TYPE; goto exit; } if (driver->mdmdata_ready[index] & LOG_MASKS_TYPE) { driver->mdmdata_ready[index] ^= LOG_MASKS_TYPE; goto exit; } if (driver->mdmdata_ready[index] & PKT_TYPE) { driver->mdmdata_ready[index] ^= PKT_TYPE; goto exit; } exit: mutex_unlock(&driver->diagcharmdm_mutex); return ret; }
static int diagchar_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { int index = -1, i = 0, ret = 0; int num_data = 0, data_type; for (i = 0; i < driver->num_clients; i++) if (driver->client_map[i].pid == current->tgid) index = i; if (index == -1) { printk(KERN_ALERT "\n Client PID not found in table"); return -EINVAL; } wait_event_interruptible(driver->wait_q, driver->data_ready[index]); mutex_lock(&driver->diagchar_mutex); if ((driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE) && (driver-> logging_mode == MEMORY_DEVICE_MODE)) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); /* place holder for number of data field */ ret += 4; for (i = 0; i < driver->poolsize_usb_struct; i++) { if (driver->buf_tbl[i].length > 0) { #ifdef DIAG_DEBUG printk(KERN_INFO "\n WRITING the buf address " "and length is %x , %d\n", (unsigned int) (driver->buf_tbl[i].buf), driver->buf_tbl[i].length); #endif num_data++; /* Copy the length of data being passed */ if (copy_to_user(buf+ret, (void *)&(driver-> buf_tbl[i].length), 4)) { num_data--; goto drop; } ret += 4; /* Copy the actual data being passed */ if (copy_to_user(buf+ret, (void *)driver-> buf_tbl[i].buf, driver->buf_tbl[i].length)) { ret -= 4; num_data--; goto drop; } ret += driver->buf_tbl[i].length; drop: #ifdef DIAG_DEBUG printk(KERN_INFO "\n DEQUEUE buf address and" " length is %x,%d\n", (unsigned int) (driver->buf_tbl[i].buf), driver-> buf_tbl[i].length); #endif diagmem_free(driver, (unsigned char *) (driver->buf_tbl[i].buf), POOL_TYPE_HDLC); driver->buf_tbl[i].length = 0; driver->buf_tbl[i].buf = 0; } } /* copy modem data */ if (driver->in_busy == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->usb_write_ptr->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->usb_buf_in), driver->usb_write_ptr->length); driver->in_busy = 0; } /* copy q6 data */ if (driver->in_busy_qdsp == 1) { num_data++; /*Copy the length of data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, (driver->usb_write_ptr_qdsp->length), 4); /*Copy the actual data being passed*/ COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver-> usb_buf_in_qdsp), driver->usb_write_ptr_qdsp->length); driver->in_busy_qdsp = 0; } /* copy number of data fields */ COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4); ret -= 4; driver->data_ready[index] ^= MEMORY_DEVICE_LOG_TYPE; if (driver->ch) queue_work(driver->diag_wq, &(driver->diag_read_smd_work)); if (driver->chqdsp) queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work)); APPEND_DEBUG('n'); goto exit; } else if (driver->data_ready[index] & MEMORY_DEVICE_LOG_TYPE) { /* 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] ^= MEMORY_DEVICE_LOG_TYPE; } if (driver->data_ready[index] & DEINIT_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & DEINIT_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); driver->data_ready[index] ^= DEINIT_TYPE; goto exit; } if (driver->data_ready[index] & MSG_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & MSG_MASKS_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->msg_masks), MSG_MASK_SIZE); driver->data_ready[index] ^= MSG_MASKS_TYPE; goto exit; } if (driver->data_ready[index] & EVENT_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & EVENT_MASKS_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->event_masks), EVENT_MASK_SIZE); driver->data_ready[index] ^= EVENT_MASKS_TYPE; goto exit; } if (driver->data_ready[index] & LOG_MASKS_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & LOG_MASKS_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->log_masks), LOG_MASK_SIZE); driver->data_ready[index] ^= LOG_MASKS_TYPE; goto exit; } if (driver->data_ready[index] & PKT_TYPE) { /*Copy the type of data being passed*/ data_type = driver->data_ready[index] & PKT_TYPE; COPY_USER_SPACE_OR_EXIT(buf, data_type, 4); COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->pkt_buf), driver->pkt_length); driver->data_ready[index] ^= PKT_TYPE; /* LGE_CHANGE_S [[email protected]] 2010-11-22 - fix diag packet drop issue */ driver->pkt_length = 0; /* LGE_CHANGE_E [[email protected]] 2010-11-22 */ goto exit; } exit: mutex_unlock(&driver->diagchar_mutex); return ret; }