int diagfwd_write_complete(struct diag_request *diag_write_ptr) { unsigned char *buf = diag_write_ptr->buf; /*Determine if the write complete is for data from arm9/apps/q6 */ /* Need a context variable here instead */ if (buf == (void *)driver->buf_in_1) { driver->in_busy_1 = 0; APPEND_DEBUG('o'); queue_work(driver->diag_wq, &(driver->diag_read_smd_work)); } else if (buf == (void *)driver->buf_in_2) { driver->in_busy_2 = 0; APPEND_DEBUG('O'); queue_work(driver->diag_wq, &(driver->diag_read_smd_work)); } else if (buf == (void *)driver->buf_in_qdsp_1) { driver->in_busy_qdsp_1 = 0; APPEND_DEBUG('p'); queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work)); } else if (buf == (void *)driver->buf_in_qdsp_2) { driver->in_busy_qdsp_2 = 0; APPEND_DEBUG('P'); queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work)); } else { diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)diag_write_ptr, POOL_TYPE_WRITE_STRUCT); APPEND_DEBUG('q'); } return 0; }
int diagfwd_write_complete(struct diag_request *diag_write_ptr) { unsigned char *buf = diag_write_ptr->buf; /*Determine if the write complete is for data from arm9/apps/q6 */ /* Need a context variable here instead */ if (buf == (void *)driver->usb_buf_in) { driver->in_busy = 0; APPEND_DEBUG('o'); spin_lock(&diagchar_smd_lock); __diag_smd_send_req(NON_SMD_CONTEXT); spin_unlock(&diagchar_smd_lock); } else if (buf == (void *)driver->usb_buf_in_qdsp) { driver->in_busy_qdsp = 0; APPEND_DEBUG('p'); spin_lock(&diagchar_smd_qdsp_lock); __diag_smd_qdsp_send_req(NON_SMD_CONTEXT); spin_unlock(&diagchar_smd_qdsp_lock); } else { diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)diag_write_ptr, POOL_TYPE_USB_STRUCT); APPEND_DEBUG('q'); } return 0; }
static void diag_process_hsic_work_fn(struct work_struct *work) { struct diag_hsic_dci_dev *hsic_struct = container_of(work, struct diag_hsic_dci_dev, diag_process_hsic_work); int index = hsic_struct->id; if (!diag_hsic_dci[index].data) { diagmem_free(driver, diag_hsic_dci[index].data_buf, POOL_TYPE_HSIC_DCI + index); return; } if (diag_hsic_dci[index].data_len <= 0) { diagmem_free(driver, diag_hsic_dci[index].data_buf, POOL_TYPE_HSIC_DCI + index); return; } diag_process_hsic_dci_read_data(index, diag_hsic_dci[index].data, diag_hsic_dci[index].data_len); diagmem_free(driver, diag_hsic_dci[index].data_buf, POOL_TYPE_HSIC_DCI + index); queue_work(diag_bridge_dci[index].wq, &diag_hsic_dci[index].diag_read_hsic_work); }
int diagfwd_write_complete(struct diag_request *diag_write_ptr) { unsigned char *buf = diag_write_ptr->buf; unsigned long flags = 0; if (buf == (void *)driver->usb_buf_in) { driver->in_busy = 0; APPEND_DEBUG('o'); spin_lock_irqsave(&diagchar_smd_lock, flags); __diag_smd_send_req(NON_SMD_CONTEXT); spin_unlock_irqrestore(&diagchar_smd_lock, flags); } else if (buf == (void *)driver->usb_buf_in_qdsp) { driver->in_busy_qdsp = 0; APPEND_DEBUG('p'); spin_lock_irqsave(&diagchar_smd_qdsp_lock, flags); __diag_smd_qdsp_send_req(NON_SMD_CONTEXT); spin_unlock_irqrestore(&diagchar_smd_qdsp_lock, flags); } else { diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)diag_write_ptr, POOL_TYPE_USB_STRUCT); APPEND_DEBUG('q'); } return 0; }
static void diag_hsic_read_complete_callback(void *ctxt, char *buf, int buf_size, int actual_size) { int err = -2; if (!driver->hsic_ch) { /* * The hsic channel is closed. Return the buffer to * the pool. Do not send it on. */ diagmem_free(driver, buf, POOL_TYPE_HSIC); pr_debug("diag: In %s: driver->hsic_ch == 0, actual_size: %d\n", __func__, actual_size); return; } /* * Note that zero length is valid and still needs to be sent to * the USB only when we are logging data to the USB */ if ((actual_size > 0) || ((actual_size == 0) && (driver->logging_mode == USB_MODE))) { if (!buf) { pr_err("diag: Out of diagmem for HSIC\n"); } else { /* * Send data in buf to be written on the * appropriate device, e.g. USB MDM channel */ driver->write_len_mdm = actual_size; err = diag_device_write((void *)buf, HSIC_DATA, NULL); /* If an error, return buffer to the pool */ if (err) { diagmem_free(driver, buf, POOL_TYPE_HSIC); pr_err_ratelimited("diag: In %s, error calling diag_device_write, err: %d\n", __func__, err); } } } else { /* * The buffer has an error status associated with it. Do not * pass it on. Note that -ENOENT is sent when the diag bridge * is closed. */ diagmem_free(driver, buf, POOL_TYPE_HSIC); pr_debug("diag: In %s: error status: %d\n", __func__, actual_size); } /* * If for some reason there was no hsic data to write to the * mdm channel, set up another read */ if (err && ((driver->logging_mode == MEMORY_DEVICE_MODE) || (driver->usb_mdm_connected && !driver->hsic_suspend))) { queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work); } }
int diagfwd_write_complete(struct diag_request *diag_write_ptr) { unsigned char *buf = diag_write_ptr->buf; /*Determine if the write complete is for data from arm9/apps/q6 */ /* Need a context variable here instead */ if (buf == (void *)driver->buf_in_1) { driver->in_busy_1 = 0; APPEND_DEBUG('o'); queue_work(driver->diag_wq, &(driver->diag_read_smd_work)); } else if (buf == (void *)driver->buf_in_2) { driver->in_busy_2 = 0; APPEND_DEBUG('O'); queue_work(driver->diag_wq, &(driver->diag_read_smd_work)); } else if (buf == (void *)driver->buf_in_qdsp_1) { driver->in_busy_qdsp_1 = 0; APPEND_DEBUG('p'); queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work)); } else if (buf == (void *)driver->buf_in_qdsp_2) { driver->in_busy_qdsp_2 = 0; APPEND_DEBUG('P'); queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work)); } else if (driver->in_busy_dmrounter == 1) { driver->in_busy_dmrounter = 0; } #if defined(CONFIG_ARCH_MSM8X60_LTE) else if (buf == (void *)driver->buf_in_sdio_1) { driver->in_busy_sdio_1 = 0; APPEND_DEBUG('q'); queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); } else if (buf == (void *)driver->buf_in_sdio_2) { driver->in_busy_sdio_2 = 0; APPEND_DEBUG('Q'); queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); } #endif #if defined(CONFIG_MACH_MECHA) else if (buf == (void *)driver->buf_in_mdm_1) { driver->in_busy_mdm_1 = 0; queue_work(driver->mdm_diag_workqueue, &(driver->diag_read_smd_mdm_work)); } else if (buf == (void *)driver->buf_in_mdm_2) { driver->in_busy_mdm_2 = 0; queue_work(driver->mdm_diag_workqueue, &(driver->diag_read_smd_mdm_work)); } #endif else { diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)diag_write_ptr, POOL_TYPE_WRITE_STRUCT); APPEND_DEBUG('q'); } return 0; }
int diagfwd_write_complete(struct diag_request *diag_write_ptr) { unsigned char *buf = diag_write_ptr->buf; /*Determine if the write complete is for data from modem/apps/q6 */ /* Need a context variable here instead */ if (buf == (void *)driver->buf_in_1) { driver->in_busy_1 = 0; APPEND_DEBUG('o'); queue_work(driver->diag_wq, &(driver->diag_read_smd_work)); } else if (buf == (void *)driver->buf_in_2) { driver->in_busy_2 = 0; APPEND_DEBUG('O'); queue_work(driver->diag_wq, &(driver->diag_read_smd_work)); } else if (buf == (void *)driver->buf_in_qdsp_1) { driver->in_busy_qdsp_1 = 0; APPEND_DEBUG('p'); queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work)); } else if (buf == (void *)driver->buf_in_qdsp_2) { driver->in_busy_qdsp_2 = 0; APPEND_DEBUG('P'); queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work)); } else if (is_wcnss_used && buf == (void *)driver->buf_in_wcnss) { driver->in_busy_wcnss = 0; APPEND_DEBUG('R'); queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work)); #if DIAG_XPST } else if (driver->in_busy_dmrounter == 1) { driver->in_busy_dmrounter = 0; #endif } #ifdef CONFIG_DIAG_SDIO_PIPE else if (buf == (void *)driver->buf_in_sdio_1) { driver->in_busy_sdio_1 = 0; APPEND_DEBUG('q'); queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); } else if (buf == (void *)driver->buf_in_sdio_2) { driver->in_busy_sdio_2 = 0; APPEND_DEBUG('Q'); queue_work(driver->diag_sdio_wq, &(driver->diag_read_sdio_work)); } #endif else { diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)diag_write_ptr, POOL_TYPE_WRITE_STRUCT); APPEND_DEBUG('q'); } return 0; }
static void diag_hsic_read_complete_callback(void *ctxt, char *buf, int buf_size, int actual_size) { #if DIAG_XPST && defined(CONFIG_DIAGFWD_BRIDGE_CODE) int type; static int pkt_hdr = DIAG_BODY_OF_NEXT_PKT, first_pkt = 1; #endif int err = -2; if (!driver->hsic_ch) { diagmem_free(driver, buf, POOL_TYPE_HSIC); pr_debug("diag: In %s: driver->hsic_ch == 0, actual_size: %d\n", __func__, actual_size); return; } if ((actual_size > 0) || ((actual_size == 0) && (driver->logging_mode == USB_MODE))) { if (!buf) { pr_err("diag: Out of diagmem for HSIC\n"); } else { DIAGFWD_9K_RAWDATA(buf, "9K", DIAG_DBG_READ); /* * Send data in buf to be written on the * appropriate device, e.g. USB MDM channel */ diag_bridge[HSIC].write_len = actual_size; err = diag_device_write((void *)buf, HSIC_DATA, NULL); if (err) { diagmem_free(driver, buf, POOL_TYPE_HSIC); pr_err_ratelimited("diag: In %s, error calling diag_device_write, err: %d\n", __func__, err); } } } else { diagmem_free(driver, buf, POOL_TYPE_HSIC); pr_debug("diag: In %s: error status: %d\n", __func__, actual_size); } if (err && ((driver->logging_mode == MEMORY_DEVICE_MODE) || (diag_bridge[HSIC].usb_connected && !driver->hsic_suspend))) { queue_work(diag_bridge[HSIC].wq, &driver->diag_read_hsic_work); } }
static void diag_hsic_read_complete(void *ctxt, char *buf, int len, int actual_size) { int err = 0; int index = (int)(uintptr_t)ctxt; struct diag_hsic_info *ch = NULL; if (index < 0 || index >= NUM_HSIC_DEV) { pr_err_ratelimited("diag: In %s, invalid HSIC index %d\n", __func__, index); return; } ch = &diag_hsic[index]; /* * Don't pass on the buffer if the channel is closed when a pending read * completes. Also, actual size can be negative error codes - do not * pass on the buffer. */ if (!ch->opened || actual_size <= 0) goto fail; err = diag_remote_dev_read_done(ch->dev_id, buf, actual_size); if (err) goto fail; return; fail: diagmem_free(driver, buf, ch->mempool); queue_work(ch->hsic_wq, &ch->read_work); return; }
static void hsic_read_work_fn(struct work_struct *work) { int err = 0; unsigned char *buf = NULL; struct diag_hsic_info *ch = container_of(work, struct diag_hsic_info, read_work); if (!ch || !ch->enabled || !ch->opened) return; do { buf = diagmem_alloc(driver, DIAG_MDM_BUF_SIZE, ch->mempool); if (!buf) { err = -ENOMEM; break; } err = diag_bridge_read(ch->id, buf, DIAG_MDM_BUF_SIZE); if (err) { diagmem_free(driver, buf, ch->mempool); pr_err_ratelimited("diag: Unable to read from HSIC channel %d, err: %d\n", ch->id, err); break; } } while (buf); /* Read from the HSIC channel continously if the channel is present */ if (!err) queue_work(ch->hsic_wq, &ch->read_work); }
static void diag_hsic_dci_read_complete_callback(void *ctxt, char *buf, int buf_size, int actual_size) { int index = (int)ctxt; if (!diag_hsic_dci[index].hsic_ch) { /* * The HSIC channel is closed. Return the buffer to * the pool. Do not send it on. */ diagmem_free(driver, buf, POOL_TYPE_HSIC_DCI + index); pr_debug("diag: In %s: hsic_ch == 0, actual_size: %d\n", __func__, actual_size); return; } if (actual_size > 0 && actual_size <= READ_HSIC_BUF_SIZE_DCI) { if (!buf) { pr_err("diag: Out of diagmem for HSIC\n"); } else { diag_dci_try_activate_wakeup_source(); diag_hsic_dci[index].data_len = actual_size; diag_hsic_dci[index].data_buf = buf; memcpy(diag_hsic_dci[index].data, buf, actual_size); queue_work(diag_bridge_dci[index].wq, &diag_hsic_dci[index].diag_process_hsic_work); } } else { /* * The buffer has an error status associated with it. Do not * pass it on. Note that -ENOENT is sent when the diag bridge * is closed. */ diagmem_free(driver, buf, POOL_TYPE_HSIC_DCI + index); pr_debug("diag: In %s: error status: %d\n", __func__, actual_size); } /* * Actual Size can be negative error codes. In such cases, don't * queue another read. The HSIC channel can goto suspend. * Queuing a read will prevent HSIC from going to suspend. */ if (actual_size >= 0) queue_work(diag_bridge_dci[index].wq, &diag_hsic_dci[index].diag_read_hsic_work); }
int diag_usb_write(int id, unsigned char *buf, int len, int ctxt) { int err = 0; struct diag_request *req = NULL; struct diag_usb_info *usb_info = NULL; if (id < 0 || id >= NUM_DIAG_USB_DEV) { pr_err_ratelimited("diag: In %s, Incorrect id %d\n", __func__, id); return -EINVAL; } usb_info = &diag_usb[id]; req = diagmem_alloc(driver, sizeof(struct diag_request), usb_info->mempool); if (!req) { /* * This should never happen. It either means that we are * trying to write more buffers than the max supported by * this particualar diag USB channel at any given instance, * or the previous write ptrs are stuck in the USB layer. */ pr_err_ratelimited("diag: In %s, cannot retrieve USB write ptrs for USB channel %s\n", __func__, usb_info->name); return -ENOMEM; } req->buf = buf; req->length = len; req->context = (void *)(uintptr_t)ctxt; if (!usb_info->hdl || !usb_info->connected) { pr_debug_ratelimited("diag: USB ch %s is not connected\n", usb_info->name); diagmem_free(driver, req, usb_info->mempool); return -ENODEV; } err = usb_diag_write(usb_info->hdl, req); if (err) { pr_err_ratelimited("diag: In %s, error writing to usb channel %s, err: %d\n", __func__, usb_info->name, err); diagmem_free(driver, req, usb_info->mempool); } return err; }
int diagfwd_write_complete(struct diag_request *diag_write_ptr) { unsigned char *buf = diag_write_ptr->buf; int found_it = 0; int i; /* Determine if the write complete is for data from modem/apps/q6 */ /* Need a context variable here instead */ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) { struct diag_smd_info *data = &(driver->smd_data[i]); if (buf == (void *)data->buf_in_1) { data->in_busy_1 = 0; queue_work(driver->diag_wq, &(data->diag_read_smd_work)); found_it = 1; break; } else if (buf == (void *)data->buf_in_2) { data->in_busy_2 = 0; queue_work(driver->diag_wq, &(data->diag_read_smd_work)); found_it = 1; break; } } #ifdef CONFIG_DIAG_SDIO_PIPE if (!found_it) { if (buf == (void *)driver->buf_in_sdio) { if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) diagfwd_write_complete_sdio(); else pr_err("diag: Incorrect buffer pointer while WRITE"); found_it = 1; } } #endif if (!found_it) { diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)diag_write_ptr, POOL_TYPE_WRITE_STRUCT); } return 0; }
int diagfwd_write_complete(struct diag_request *diag_write_ptr) { unsigned char *buf = diag_write_ptr->buf; /*Determine if the write complete is for data from modem/apps/q6 */ /* Need a context variable here instead */ if (buf == (void *)driver->buf_in_1) { driver->in_busy_1 = 0; APPEND_DEBUG('o'); queue_work(driver->diag_wq, &(driver->diag_read_smd_work)); } else if (buf == (void *)driver->buf_in_2) { driver->in_busy_2 = 0; APPEND_DEBUG('O'); queue_work(driver->diag_wq, &(driver->diag_read_smd_work)); } else if (buf == (void *)driver->buf_in_qdsp_1) { driver->in_busy_qdsp_1 = 0; APPEND_DEBUG('p'); queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work)); } else if (buf == (void *)driver->buf_in_qdsp_2) { driver->in_busy_qdsp_2 = 0; APPEND_DEBUG('P'); queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work)); } else if (buf == (void *)driver->buf_in_wcnss) { driver->in_busy_wcnss = 0; APPEND_DEBUG('R'); queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work)); } #ifdef CONFIG_DIAG_SDIO_PIPE else if (buf == (void *)driver->buf_in_sdio) if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) diagfwd_write_complete_sdio(); else pr_err("diag: Incorrect buffer pointer while WRITE"); #endif else { diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)diag_write_ptr, POOL_TYPE_WRITE_STRUCT); APPEND_DEBUG('q'); } return 0; }
static void diag_read_hsic_work_fn(struct work_struct *work) { unsigned char *buf_in_hsic = NULL; int num_reads_submitted = 0; int err = 0; int write_ptrs_available; if (!driver->hsic_ch) { pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__); return; } if (driver->logging_mode == MEMORY_DEVICE_MODE) write_ptrs_available = driver->poolsize_hsic_write - driver->num_hsic_buf_tbl_entries; else write_ptrs_available = driver->poolsize_hsic_write - driver->count_hsic_write_pool; do { if (write_ptrs_available <= 0) break; write_ptrs_available--; if (!driver->hsic_ch) break; buf_in_hsic = diagmem_alloc(driver, READ_HSIC_BUF_SIZE, POOL_TYPE_HSIC); if (buf_in_hsic) { pr_debug("diag: read from HSIC\n"); num_reads_submitted++; err = diag_bridge_read((char *)buf_in_hsic, READ_HSIC_BUF_SIZE); if (err) { num_reads_submitted--; diagmem_free(driver, buf_in_hsic, POOL_TYPE_HSIC); pr_err_ratelimited("diag: Error initiating HSIC read, err: %d\n", err); break; } } } while (buf_in_hsic); if ((driver->count_hsic_pool < driver->poolsize_hsic) && (num_reads_submitted == 0) && (err != -ENODEV) && (driver->hsic_ch != 0)) queue_work(diag_bridge[HSIC].wq, &driver->diag_read_hsic_work); }
/* * diagfwd_write_complete_hsic is called after the asynchronous * usb_diag_write() on mdm channel is complete */ int diagfwd_write_complete_hsic(struct diag_request *diag_write_ptr, int index) { unsigned char *buf = (diag_write_ptr) ? diag_write_ptr->buf : NULL; if (buf) { /* Return buffers to their pools */ diagmem_free(driver, (unsigned char *)buf, index + POOL_TYPE_HSIC); diagmem_free(driver, (unsigned char *)diag_write_ptr, index + POOL_TYPE_HSIC_WRITE); } if (!diag_hsic[index].hsic_ch) { pr_err("diag: In %s: hsic_ch == 0\n", __func__); return 0; } /* Read data from the HSIC */ queue_work(diag_bridge[index].wq, &diag_hsic[index].diag_read_hsic_work); return 0; }
int diag_usb_write(int id, unsigned char *buf, int len, int ctxt) { int err = 0; struct diag_request *req = NULL; struct diag_usb_info *usb_info = NULL; if (id < 0 || id >= NUM_DIAG_USB_DEV) { pr_err_ratelimited("diag: In %s, Incorrect id %d\n", __func__, id); return -EINVAL; } usb_info = &diag_usb[id]; req = diagmem_alloc(driver, sizeof(struct diag_request), usb_info->mempool); if (!req) { pr_err_ratelimited("diag: In %s, cannot retrieve USB write ptrs for USB channel %s\n", __func__, usb_info->name); return -ENOMEM; } req->buf = buf; req->length = len; req->context = (void *)(uintptr_t)ctxt; if (!usb_info->hdl || !usb_info->connected) { pr_debug_ratelimited("diag: USB ch %s is not connected\n", usb_info->name); diagmem_free(driver, req, usb_info->mempool); return -ENODEV; } err = usb_diag_write(usb_info->hdl, req); if (err) { pr_err_ratelimited("diag: In %s, error writing to usb channel %s, err: %d\n", __func__, usb_info->name, err); diagmem_free(driver, req, usb_info->mempool); } return err; }
int diagfwd_write_complete_hsic(struct diag_request *diag_write_ptr) { unsigned char *buf = (diag_write_ptr) ? diag_write_ptr->buf : NULL; if (buf) { diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HSIC); diagmem_free(driver, (unsigned char *)diag_write_ptr, POOL_TYPE_HSIC_WRITE); } if (!driver->hsic_ch) { pr_err("diag: In %s: driver->hsic_ch == 0\n", __func__); return 0; } queue_work(driver->diag_bridge_wq, &driver->diag_read_hsic_work); return 0; }
void diag_drain_work_fn(struct work_struct *work) { int err = 0; timer_in_progress = 0; mutex_lock(&driver->diagchar_mutex); if (buf_hdlc) { err = diag_device_write(buf_hdlc, APPS_DATA, NULL); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> write_ptr_svc, POOL_TYPE_WRITE_STRUCT); } buf_hdlc = NULL; diag_printk(1,"diag:%s Number of bytes written " "from timer is %d ",__func__, driver->used); driver->used = 0; } mutex_unlock(&driver->diagchar_mutex); }
static int hsic_fwd_complete(int id, unsigned char *buf, int len, int ctxt) { if (id < 0 || id >= NUM_HSIC_DEV) { pr_err_ratelimited("diag: In %s, invalid index %d\n", __func__, id); return -EINVAL; } if (!buf) return -EIO; diagmem_free(driver, buf, diag_hsic[id].mempool); queue_work(diag_hsic[id].hsic_wq, &(diag_hsic[id].read_work)); return 0; }
void diag_drain_work_fn(struct work_struct *work) { int err = 0; timer_in_progress = 0; mutex_lock(&driver->diagchar_mutex); if (buf_hdlc) { err = diag_device_write(buf_hdlc, APPS_DATA, NULL); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> usb_write_ptr_svc, POOL_TYPE_USB_STRUCT); } buf_hdlc = NULL; #ifdef DIAG_DEBUG printk(KERN_INFO "\n Number of bytes written " "from timer is %d ", driver->used); #endif driver->used = 0; } mutex_unlock(&driver->diagchar_mutex); }
void lge_dm_usb_fn(struct work_struct *work) { int err = 0; struct diag_usb_info *usb_info = NULL; #ifndef CONFIG_DIAGFWD_BRIDGE_CODE usb_info = &diag_usb[DIAG_MUX_LOCAL]; #else usb_info = &diag_usb[DIAG_MUX_MDM]; #endif err = usb_diag_write(usb_info->hdl, lge_dm_tty->dm_usb_req); if (err) diagmem_free(driver, lge_dm_tty->dm_usb_req, usb_info->mempool); }
static void diag_usb_write_done(struct diag_usb_info *ch, struct diag_request *req) { int ctxt = 0; if (!ch || !req) return; ch->write_cnt++; ctxt = (int)(uintptr_t)req->context; if (ch->ops && ch->ops->write_done) ch->ops->write_done(req->buf, req->actual, ctxt, ch->ctxt); diagmem_free(driver, req, ch->mempool); queue_work(ch->usb_wq, &(ch->read_work)); }
void diag_clear_hsic_tbl(void) { int i; driver->num_hsic_buf_tbl_entries = 0; for (i = 0; i < driver->poolsize_hsic_write; i++) { if (driver->hsic_buf_tbl[i].buf) { /* Return the buffer to the pool */ diagmem_free(driver, (unsigned char *) (driver->hsic_buf_tbl[i].buf), POOL_TYPE_HSIC); driver->hsic_buf_tbl[i].buf = 0; } driver->hsic_buf_tbl[i].length = 0; } }
static void diag_send_diag_mode_update_remote(int token, int real_time) { unsigned char *buf = NULL; int err = 0; struct diag_dci_header_t dci_header; int dci_header_size = sizeof(struct diag_dci_header_t); int msg_size = sizeof(struct diag_ctrl_msg_diagmode); uint32_t write_len = 0; if (token < 0 || token >= NUM_DCI_PROC) { pr_err("diag: Invalid remote device channel in %s, token: %d\n", __func__, token); return; } if (real_time != MODE_REALTIME && real_time != MODE_NONREALTIME) { pr_err("diag: Invalid real time value in %s, type: %d\n", __func__, real_time); return; } buf = dci_get_buffer_from_bridge(token); if (!buf) { pr_err("diag: In %s, unable to get dci buffers to write data\n", __func__); return; } /* Frame the DCI header */ dci_header.start = CONTROL_CHAR; dci_header.version = 1; dci_header.length = msg_size + 1; dci_header.cmd_code = DCI_CONTROL_PKT_CODE; memcpy(buf + write_len, &dci_header, dci_header_size); write_len += dci_header_size; diag_create_diag_mode_ctrl_pkt(buf + write_len, real_time); write_len += msg_size; *(buf + write_len) = CONTROL_CHAR; /* End Terminator */ write_len += sizeof(uint8_t); err = diagfwd_bridge_write(TOKEN_TO_BRIDGE(token), buf, write_len); if (err != write_len) { pr_err("diag: cannot send nrt mode ctrl pkt, err: %d\n", err); diagmem_free(driver, buf, dci_ops_tbl[token].mempool); } else { driver->real_time_mode[token + 1] = real_time; } }
static void diag_hsic_dci_write_complete_callback(void *ctxt, char *buf, int buf_size, int actual_size) { int index = (int)ctxt; /* The write of the data to the HSIC bridge is complete */ diag_hsic_dci[index].in_busy_hsic_write = 0; if (!diag_hsic_dci[index].hsic_ch) { pr_err("DIAG in %s: hsic_ch == 0, ch = %d\n", __func__, index); return; } if (actual_size < 0) pr_err("DIAG in %s: actual_size: %d\n", __func__, actual_size); diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HSIC_DCI_WRITE + index); queue_work(diag_bridge_dci[index].wq, &diag_hsic_dci[index].diag_read_hsic_work); }
static int diagchar_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { int err, ret = 0, pkt_type; #ifdef DIAG_DEBUG int length = 0, i; #endif struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 }; struct diag_hdlc_dest_type enc = { NULL, NULL, 0 }; void *buf_copy = NULL; int payload_size; #ifdef CONFIG_DIAG_OVER_USB if (((driver->logging_mode == USB_MODE) && (!driver->usb_connected)) || (driver->logging_mode == NO_LOGGING_MODE)) { /*Drop the diag payload */ return -EIO; } #endif /* DIAG over USB */ /* Get the packet type F3/log/event/Pkt response */ err = copy_from_user((&pkt_type), buf, 4); /* First 4 bytes indicate the type of payload - ignore these */ payload_size = count - 4; if (pkt_type == USER_SPACE_LOG_TYPE) { err = copy_from_user(driver->user_space_data, buf + 4, payload_size); /* Check masks for On-Device logging */ if (driver->mask_check) { if (!mask_request_validate(driver->user_space_data)) { pr_alert("diag: mask request Invalid\n"); return -EFAULT; } } buf = buf + 4; #ifdef DIAG_DEBUG pr_debug("diag: user space data %d\n", payload_size); for (i = 0; i < payload_size; i++) pr_debug("\t %x", *((driver->user_space_data)+i)); #endif #ifdef CONFIG_DIAG_SDIO_PIPE /* send masks to 9k too */ if (driver->sdio_ch) { wait_event_interruptible(driver->wait_q, (sdio_write_avail(driver->sdio_ch) >= payload_size)); if (driver->sdio_ch && (payload_size > 0)) { sdio_write(driver->sdio_ch, (void *) (driver->user_space_data), payload_size); } } #endif /* send masks to modem now */ diag_process_hdlc((void *)(driver->user_space_data), payload_size); return 0; } buf_copy = diagmem_alloc(driver, payload_size, POOL_TYPE_COPY); if (!buf_copy) { driver->dropped_count++; return -ENOMEM; } err = copy_from_user(buf_copy, buf + 4, payload_size); if (err) { printk(KERN_INFO "diagchar : copy_from_user failed\n"); ret = -EFAULT; goto fail_free_copy; } #ifdef DIAG_DEBUG printk(KERN_DEBUG "data is -->\n"); for (i = 0; i < payload_size; i++) printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_copy)+i)); #endif send.state = DIAG_STATE_START; send.pkt = buf_copy; send.last = (void *)(buf_copy + payload_size - 1); send.terminate = 1; #ifdef DIAG_DEBUG pr_debug("diag: Already used bytes in buffer %d, and" " incoming payload size is %d\n", driver->used, payload_size); printk(KERN_DEBUG "hdlc encoded data is -->\n"); for (i = 0; i < payload_size + 8; i++) { printk(KERN_DEBUG "\t %x \t", *(((unsigned char *)buf_hdlc)+i)); if (*(((unsigned char *)buf_hdlc)+i) != 0x7e) length++; } #endif mutex_lock(&driver->diagchar_mutex); if (!buf_hdlc) buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC); if (!buf_hdlc) { ret = -ENOMEM; goto fail_free_hdlc; } if (HDLC_OUT_BUF_SIZE - driver->used <= (2*payload_size) + 3) { err = diag_device_write(buf_hdlc, APPS_DATA, NULL); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> write_ptr_svc, POOL_TYPE_WRITE_STRUCT); ret = -EIO; goto fail_free_hdlc; } buf_hdlc = NULL; driver->used = 0; buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC); if (!buf_hdlc) { ret = -ENOMEM; goto fail_free_hdlc; } } enc.dest = buf_hdlc + driver->used; enc.dest_last = (void *)(buf_hdlc + driver->used + 2*payload_size + 3); diag_hdlc_encode(&send, &enc); /* This is to check if after HDLC encoding, we are still within the limits of aggregation buffer. If not, we write out the current buffer and start aggregation in a newly allocated buffer */ if ((unsigned int) enc.dest >= (unsigned int)(buf_hdlc + HDLC_OUT_BUF_SIZE)) { err = diag_device_write(buf_hdlc, APPS_DATA, NULL); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> write_ptr_svc, POOL_TYPE_WRITE_STRUCT); ret = -EIO; goto fail_free_hdlc; } buf_hdlc = NULL; driver->used = 0; buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE, POOL_TYPE_HDLC); if (!buf_hdlc) { ret = -ENOMEM; goto fail_free_hdlc; } enc.dest = buf_hdlc + driver->used; enc.dest_last = (void *)(buf_hdlc + driver->used + (2*payload_size) + 3); diag_hdlc_encode(&send, &enc); } driver->used = (uint32_t) enc.dest - (uint32_t) buf_hdlc; if (pkt_type == DATA_TYPE_RESPONSE) { err = diag_device_write(buf_hdlc, APPS_DATA, NULL); if (err) { /*Free the buffer right away if write failed */ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC); diagmem_free(driver, (unsigned char *)driver-> write_ptr_svc, POOL_TYPE_WRITE_STRUCT); ret = -EIO; goto fail_free_hdlc; } buf_hdlc = NULL; driver->used = 0; } mutex_unlock(&driver->diagchar_mutex); diagmem_free(driver, buf_copy, POOL_TYPE_COPY); if (!timer_in_progress) { timer_in_progress = 1; ret = mod_timer(&drain_timer, jiffies + msecs_to_jiffies(500)); } return 0; fail_free_hdlc: buf_hdlc = NULL; driver->used = 0; diagmem_free(driver, buf_copy, POOL_TYPE_COPY); mutex_unlock(&driver->diagchar_mutex); return ret; fail_free_copy: diagmem_free(driver, buf_copy, POOL_TYPE_COPY); 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)) { /*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 lge_dm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { short result; #ifdef CONFIG_DIAGFWD_BRIDGE_CODE short modem_number = Secondary_modem_chip; #else short modem_number = Primary_modem_chip; #endif /*CONFIG_DIAGFWD_BRIDGE_CODE*/ struct dm_tty *lge_dm_tty_drv = NULL; int status = 0; /* */ int i; int index=MODEM_DATA; #ifdef CONFIG_DIAGFWD_BRIDGE_CODE unsigned long spin_lock_flags; #endif result = 0; lge_dm_tty_drv = lge_dm_tty; tty->driver_data = lge_dm_tty_drv; lge_dm_tty_drv->tty_str = tty; if (_IOC_TYPE(cmd) != DM_TTY_IOCTL_MAGIC) return -EINVAL; switch (cmd) { case DM_TTY_MODEM_OPEN_SDM: if(lge_dm_tty_drv->logging_mode == DM_APP_SDM) { pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "already DM_TTY_MODEM_OPEN_SDM\n", __func__); result = TRUE; if (copy_to_user((void *)arg, (const void *)&result, sizeof(result)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "already DM_TTY_MODEM_OPEN_SDM" "result = %d\n", __func__, result); break; } lge_dm_tty_drv->logging_mode = DM_APP_SDM; pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_MODEM_OPEN_SDM\n", __func__); #ifdef CONFIG_DIAGFWD_BRIDGE_CODE if ((diag_bridge[index].usb_connected == 1) && (diag_hsic[index].count_hsic_pool == N_MDM_WRITE)) { spin_lock_irqsave(&diag_hsic[HSIC].hsic_spinlock,spin_lock_flags); diag_hsic[index].count_hsic_pool = 0; spin_unlock_irqrestore(&diag_hsic[HSIC].hsic_spinlock,spin_lock_flags); } diag_hsic[index].num_hsic_buf_tbl_entries = 0; for (i = 0; i < diag_hsic[index].poolsize_hsic_write; i++) { if (diag_hsic[index].hsic_buf_tbl[index].buf) { /* Return the buffer to the pool */ diagmem_free(driver, (unsigned char *) (diag_hsic[index].hsic_buf_tbl[index].buf), POOL_TYPE_HSIC); diag_hsic[index].hsic_buf_tbl[index].buf = 0; } diag_hsic[index].hsic_buf_tbl[index].length = 0; } diagfwd_disconnect_bridge(1); diagfwd_cancel_hsic(REOPEN_HSIC); // QCT 161032 migration - NEED TO CHECK diagfwd_connect_bridge(0); #endif /* CONFIG_DIAGFWD_BRIDGE_CODE */ /* change path to DM APP */ mutex_lock(&driver->diagchar_mutex); driver->logging_mode = DM_APP_MODE; mutex_unlock(&driver->diagchar_mutex); if (modem_number == Primary_modem_chip) { for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) { driver->smd_data[i].in_busy_1 = 0; driver->smd_data[i].in_busy_2 = 0; /* Poll SMD channels to check for data*/ if (driver->smd_data[i].ch) queue_work(driver->diag_wq, &(driver->smd_data[i]. diag_read_smd_work)); }// end of for loop } else if (modem_number == Secondary_modem_chip) { #ifdef CONFIG_DIAGFWD_BRIDGE_CODE /* Read data from the hsic */ if (diag_hsic[index].hsic_ch) queue_work(diag_bridge[index].wq, &(diag_hsic[index]. diag_read_hsic_work)); #endif /* CONFIG_DIAGFWD_BRIDGE_CODE */ } else { pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_MODEM_OPEN_SDM" "error modem_number = %d\n", __func__, modem_number); } result = TRUE; if (copy_to_user((void *)arg, (const void *)&result, sizeof(result)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_MODEM_OPEN_SDM" "result = %d\n", __func__, result); break; case DM_TTY_MODEM_CLOSE_SDM: lge_dm_tty_drv->logging_mode = DM_APP_ODM; pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_MODEM_CLOSE_SDM, modem_number = %d\n", __func__, modem_number); lge_dm_tty_drv->set_logging = 0; /* change path to USB driver */ mutex_lock(&driver->diagchar_mutex); driver->logging_mode = USB_MODE; mutex_unlock(&driver->diagchar_mutex); if (driver->usb_connected == 0) diagfwd_disconnect(); else diagfwd_connect(); result = TRUE; #ifdef CONFIG_DIAGFWD_BRIDGE_CODE diag_hsic[index].num_hsic_buf_tbl_entries = 0; for (i = 0; i < diag_hsic[index].poolsize_hsic_write; i++) { if (diag_hsic[index].hsic_buf_tbl[index].buf) { /* Return the buffer to the pool */ diagmem_free(driver, (unsigned char *) (diag_hsic[index].hsic_buf_tbl[index].buf), POOL_TYPE_HSIC); diag_hsic[index].hsic_buf_tbl[index].buf = 0; } diag_hsic[index].hsic_buf_tbl[index].length = 0; } diagfwd_cancel_hsic(REOPEN_HSIC); // QCT 161032 migration - NEED TO CHECK diagfwd_connect_bridge(0); #endif if (copy_to_user((void *)arg, (const void *)&result, sizeof(result)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_MODEM_CLOSE_SDM" "result = %d\n", __func__, result); break; case DM_TTY_MODEM_OPEN_ODM: lge_dm_tty_drv->logging_mode = DM_APP_ODM; pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_MODEM_OPEN_ODM\n", __func__); #ifdef CONFIG_DIAGFWD_BRIDGE_CODE if ((diag_bridge[index].usb_connected == 1) && (diag_hsic[index].count_hsic_pool == N_MDM_WRITE)) { spin_lock_irqsave(&diag_hsic[HSIC].hsic_spinlock,spin_lock_flags); diag_hsic[index].count_hsic_pool = 0; spin_unlock_irqrestore(&diag_hsic[HSIC].hsic_spinlock,spin_lock_flags); } diag_hsic[index].num_hsic_buf_tbl_entries = 0; for (i = 0; i < diag_hsic[index].poolsize_hsic_write; i++) { if (diag_hsic[index].hsic_buf_tbl[index].buf) { /* Return the buffer to the pool */ diagmem_free(driver, (unsigned char *) (diag_hsic[index].hsic_buf_tbl[index].buf), POOL_TYPE_HSIC); diag_hsic[index].hsic_buf_tbl[index].buf = 0; } diag_hsic[index].hsic_buf_tbl[index].length = 0; } diagfwd_disconnect_bridge(1); diagfwd_cancel_hsic(REOPEN_HSIC); // QCT 161032 migration - NEED TO CHECK diagfwd_connect_bridge(0); #endif /* CONFIG_DIAGFWD_BRIDGE_CODE */ /* change path to DM DEV */ mutex_lock(&driver->diagchar_mutex); driver->logging_mode = DM_APP_MODE; mutex_unlock(&driver->diagchar_mutex); if (modem_number == Primary_modem_chip) { for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) { driver->smd_data[i].in_busy_1 = 0; driver->smd_data[i].in_busy_2 = 0; /* Poll SMD channels to check for data*/ if (driver->smd_data[i].ch) queue_work(driver->diag_wq, &(driver->smd_data[i]. diag_read_smd_work)); }// end of for loop } else if (modem_number == Secondary_modem_chip) { #ifdef CONFIG_DIAGFWD_BRIDGE_CODE /* Read data from the hsic */ if (diag_hsic[index].hsic_ch) queue_work(diag_bridge[index].wq, &(diag_hsic[index]. diag_read_hsic_work)); #endif /* CONFIG_DIAGFWD_BRIDGE_CODE */ } else { pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_MODEM_OPEN_ODM" "error modem_number = %d\n", __func__, modem_number); } result = TRUE; if (copy_to_user((void *)arg, (const void *)&result, sizeof(result)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_MODEM_OPEN_ODM" "result = %d\n", __func__, result); break; case DM_TTY_MODEM_CLOSE_ODM: lge_dm_tty_drv->logging_mode = DM_APP_ODM; pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_MODEM_CLOSE_ODM, modem_number = %d\n", __func__, modem_number); lge_dm_tty_drv->set_logging = 0; /* change path to USB driver */ mutex_lock(&driver->diagchar_mutex); driver->logging_mode = USB_MODE; mutex_unlock(&driver->diagchar_mutex); if (driver->usb_connected == 0) diagfwd_disconnect(); else diagfwd_connect(); result = TRUE; #ifdef CONFIG_DIAGFWD_BRIDGE_CODE diag_hsic[index].num_hsic_buf_tbl_entries = 0; for (i = 0; i < diag_hsic[index].poolsize_hsic_write; i++) { if (diag_hsic[index].hsic_buf_tbl[index].buf) { /* Return the buffer to the pool */ diagmem_free(driver, (unsigned char *) (diag_hsic[index].hsic_buf_tbl[index].buf), POOL_TYPE_HSIC); diag_hsic[index].hsic_buf_tbl[index].buf = 0; } diag_hsic[index].hsic_buf_tbl[index].length = 0; } diagfwd_cancel_hsic(REOPEN_HSIC); // QCT 161032 migration - NEED TO CHECK diagfwd_connect_bridge(0); #endif if (copy_to_user((void *)arg, (const void *)&result, sizeof(result)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_MODEM_CLOSE_ODM" "result = %d\n", __func__, result); break; case DM_TTY_MODEM_RESET: // not supported //status = subsys_modem_restart(); result = TRUE; if (copy_to_user((void *)arg, (const void *)&status, sizeof(result)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_MODEM_RESET" "result = %d\n", __func__, result); break; case DM_TTY_MODEM_CRASH: #ifdef CONFIG_DIAG_BRIDGE_CODE status = subsys_modem_restart(); result = TRUE; #else subsystem_restart("modem"); result = TRUE; #endif if (copy_to_user((void *)arg, (const void *)&result, sizeof(result)) == 0) pr_info(DM_TTY_MODULE_NAME ": %s: lge_dm_tty_ioctl " "DM_TTY_MODEM_CRASH" "result = %d\n", __func__, result); break; case DM_TTY_MODEM_DEBUGGER: /* */ break; default: pr_info(DM_TTY_MODULE_NAME ": %s:" "lge_dm_tty_ioctl error\n", __func__); break; } return 0; }
static void lge_dm_tty_close(struct tty_struct *tty, struct file *file) { int index=MODEM_DATA; int i; struct dm_tty *lge_dm_tty_drv = NULL; lge_dm_tty_drv = lge_dm_tty; tty->driver_data = lge_dm_tty_drv; lge_dm_tty_drv->tty_str = tty; clear_bit(TTY_NO_WRITE_SPLIT, &lge_dm_tty_drv->tty_str->flags); if (!tty) { pr_err(DM_TTY_MODULE_NAME ": %s: NULL tty", __func__); return; } lge_dm_tty_drv = tty->driver_data; if (!lge_dm_tty_drv) { pr_err(DM_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv", __func__); return; } if (lge_dm_tty_drv->tty_state != DM_TTY_OPEN) { pr_err(DM_TTY_MODULE_NAME ": %s: TTY device was not opened\n", __func__); return; } lge_dm_tty_drv->logging_mode = DM_APP_ODM; lge_dm_tty_drv->set_logging = 1; wake_up_interruptible(&lge_dm_tty_drv->waitq); kthread_stop(lge_dm_tty_drv->tty_ts); lge_dm_tty_drv->tty_state = DM_TTY_CLOSED; pr_info(DM_TTY_MODULE_NAME ": %s: TTY device closed\n", __func__); cancel_work_sync(&(lge_dm_tty_drv->dm_usb_work)); destroy_workqueue(lge_dm_tty_drv->dm_wq); #ifdef CONFIG_DIAGFWD_BRIDGE_CODE diag_hsic[index].num_hsic_buf_tbl_entries = 0; for (i = 0; i < diag_hsic[index].poolsize_hsic_write; i++) { if (diag_hsic[index].hsic_buf_tbl[index].buf) { /* Return the buffer to the pool */ diagmem_free(driver, (unsigned char *) (diag_hsic[index].hsic_buf_tbl[index].buf), POOL_TYPE_HSIC); diag_hsic[index].hsic_buf_tbl[index].buf = 0; } diag_hsic[index].hsic_buf_tbl[index].length = 0; } diagfwd_cancel_hsic(REOPEN_HSIC); // QCT 161032 migration - NEED TO CHECK diagfwd_connect_bridge(0); #endif return; }