int diag_md_copy_to_user(char __user *buf, int *pret) { int i, j; int err = 0; int ret = *pret; int num_data = 0; int remote_token; unsigned long flags; struct diag_md_info *ch = NULL; struct diag_buf_tbl_t *entry = NULL; for (i = 0; i < NUM_DIAG_MD_DEV && !err; i++) { ch = &diag_md[i]; for (j = 0; j < ch->num_tbl_entries && !err; j++) { entry = &ch->tbl[j]; if (!entry || entry->len <= 0 || entry->buf == NULL) continue; /* * If the data is from remote processor, copy the remote * token first */ if (i > 0) { remote_token = diag_get_remote(i); err = copy_to_user(buf + ret, &remote_token, sizeof(int)); if (err) goto drop_data; ret += sizeof(int); } /* Copy the length of data being passed */ err = copy_to_user(buf + ret, (void *)&(entry->len), sizeof(int)); if (err) goto drop_data; ret += sizeof(int); /* Copy the actual data being passed */ err = copy_to_user(buf + ret, (void *)entry->buf, entry->len); if (err) goto drop_data; ret += entry->len; /* * The data is now copied to the user space client, * Notify that the write is complete and delete its * entry from the table */ num_data++; drop_data: spin_lock_irqsave(&ch->lock, flags); if (ch->ops && ch->ops->write_done) ch->ops->write_done(entry->buf, entry->len, entry->ctx, ch->ctx); diag_ws_on_copy(DIAG_WS_MD); entry->buf = NULL; entry->len = 0; entry->ctx = 0; spin_unlock_irqrestore(&ch->lock, flags); } } *pret = ret; err = copy_to_user(buf + sizeof(int), (void *)&num_data, sizeof(int)); diag_ws_on_copy_complete(DIAG_WS_MD); return err; }
int diag_md_copy_to_user(char __user *buf, int *pret, size_t buf_size, struct diag_md_session_t *info) { int i, j; int err = 0; int ret = *pret; int num_data = 0; int remote_token; unsigned long flags; struct diag_md_info *ch = NULL; struct diag_buf_tbl_t *entry = NULL; uint8_t drain_again = 0; uint8_t peripheral = 0; struct diag_md_session_t *session_info = NULL; for (i = 0; i < NUM_DIAG_MD_DEV && !err; i++) { ch = &diag_md[i]; for (j = 0; j < ch->num_tbl_entries && !err; j++) { entry = &ch->tbl[j]; if (entry->len <= 0) continue; peripheral = GET_BUF_PERIPHERAL(entry->ctx); if (peripheral > NUM_PERIPHERALS) goto drop_data; session_info = diag_md_session_get_peripheral(peripheral); if (session_info && info && (session_info->pid != info->pid)) continue; if ((info && (info->peripheral_mask & MD_PERIPHERAL_MASK(peripheral)) == 0)) goto drop_data; if (i > 0) { if ((ret + (3 * sizeof(int)) + entry->len) >= buf_size) { drain_again = 1; break; } } else { if ((ret + (2 * sizeof(int)) + entry->len) >= buf_size) { drain_again = 1; break; } } if (i > 0) { remote_token = diag_get_remote(i); err = copy_to_user(buf + ret, &remote_token, sizeof(int)); if (err) goto drop_data; ret += sizeof(int); } err = copy_to_user(buf + ret, (void *)&(entry->len), sizeof(int)); if (err) goto drop_data; ret += sizeof(int); err = copy_to_user(buf + ret, (void *)entry->buf, entry->len); if (err) goto drop_data; ret += entry->len; num_data++; drop_data: spin_lock_irqsave(&ch->lock, flags); if (ch->ops && ch->ops->write_done) ch->ops->write_done(entry->buf, entry->len, entry->ctx, DIAG_MEMORY_DEVICE_MODE); diag_ws_on_copy(DIAG_WS_MUX); entry->buf = NULL; entry->len = 0; entry->ctx = 0; spin_unlock_irqrestore(&ch->lock, flags); } } *pret = ret; err = copy_to_user(buf + sizeof(int), (void *)&num_data, sizeof(int)); diag_ws_on_copy_complete(DIAG_WS_MUX); if (drain_again) chk_logging_wakeup(); return err; }
static int lge_dm_tty_read_thread(void *data) { int i = 0; struct dm_tty *lge_dm_tty_drv = NULL; int copy_data = 0; unsigned long flags; lge_dm_tty_drv = lge_dm_tty; while (1) { wait_event_interruptible(lge_dm_tty->waitq, lge_dm_tty->set_logging); mutex_lock(&driver->diagchar_mutex); if ((lge_dm_tty->set_logging == 1) && (driver->logging_mode == DM_APP_MODE)) { /* copy modem data */ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) { struct diag_smd_info *data = &driver->smd_data[i]; if (data->in_busy_1 == 1) { lge_dm_tty_modem_response( lge_dm_tty_drv, data->buf_in_1, data->write_ptr_1->length); diag_ws_on_copy(); copy_data = 1; spin_lock_irqsave(&data->in_busy_lock, flags); data->in_busy_1 = 0; spin_unlock_irqrestore(&data->in_busy_lock, flags); } if (data->in_busy_2 == 1) { lge_dm_tty_modem_response( lge_dm_tty_drv, data->buf_in_2, data->write_ptr_2->length); diag_ws_on_copy(); copy_data = 1; spin_lock_irqsave(&data->in_busy_lock, flags); data->in_busy_2 = 0; spin_unlock_irqrestore(&data->in_busy_lock, flags); } } if(lge_dm_tty_drv->logging_mode == DM_APP_SDM) { for (i = 0; i < NUM_SMD_CMD_CHANNELS; i++) { struct diag_smd_info *cmd = &driver->smd_cmd[i]; if (cmd->in_busy_1 == 1) { if(cmd->write_ptr_1->length > 0 && cmd->buf_in_1 != NULL){ lge_dm_tty_modem_response( lge_dm_tty_drv, cmd->buf_in_1, cmd->write_ptr_1->length); } cmd->in_busy_1 = 0; } } } lge_dm_tty->set_logging = 0; for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) { if (driver->smd_data[i].ch) queue_work(driver->diag_wq, &(driver->smd_data[i].diag_read_smd_work)); } } mutex_unlock(&driver->diagchar_mutex); 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++) flush_workqueue(driver->smd_data[i].wq); wake_up(&driver->smd_wait_q); diag_ws_on_copy_complete(); } if (kthread_should_stop()) break; mdelay(1); } return 0; }
static int lge_dm_tty_read_thread(void *data) { int j = 0; struct dm_tty *lge_dm_tty_drv = NULL; struct diag_buf_tbl_t *entry = NULL; unsigned long flags; int i = 0; lge_dm_tty_drv = lge_dm_tty; while (1) { wait_event_interruptible(lge_dm_tty->waitq, lge_dm_tty->set_logging); mutex_lock(&driver->diagchar_mutex); if ((lge_dm_tty->set_logging == 1) && (driver->logging_mode == DM_APP_MODE)) { lge_dm_tty->set_logging = 0; for (j = 0; j < lge_dm_tty->num_tbl_entries; j++) { entry = &lge_dm_tty->tbl[j]; if ((entry->len <= 0) || ((void *)entry->buf == NULL)) continue; lge_dm_tty_modem_response( lge_dm_tty_drv, Primary_modem_chip, (void *)entry->buf, entry->len); lge_dm_tty->ops->write_done(entry->buf, entry->len, entry->ctx, lge_dm_tty->ctx); diag_ws_on_copy(DIAG_WS_MD); spin_lock_irqsave(&entry->lock, flags); entry->buf = NULL; entry->len = 0; entry->ctx = 0; spin_unlock_irqrestore(&entry->lock, flags); } for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) { /* Poll SMD data channels to check for data */ queue_work(driver->smd_data[i].wq, &(driver->smd_data[i].diag_read_smd_work)); } for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) 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); if (kthread_should_stop()) break; mdelay(1); } return 0; }