Beispiel #1
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->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);
}
Beispiel #4
0
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);
	}
}
Beispiel #6
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->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;
}
Beispiel #8
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;
}
Beispiel #13
0
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;
}
Beispiel #14
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;
}
Beispiel #15
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);
}
Beispiel #16
0
/*
 * 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;
}
Beispiel #17
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);
}
Beispiel #23
0
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));
}
Beispiel #24
0
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;

}