예제 #1
0
static void smd_notify(void *ctxt, unsigned event)
{
	struct diag_smd_info *smd_info = NULL;

	smd_info = (struct diag_smd_info *)ctxt;
	if (!smd_info)
		return;

	switch (event) {
	case SMD_EVENT_OPEN:
		atomic_set(&smd_info->opened, 1);
		smd_info->fifo_size = smd_write_avail(smd_info->hdl);
		DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s channel opened\n",
			 smd_info->name);
		queue_work(smd_info->wq, &(smd_info->open_work));
		break;
	case SMD_EVENT_CLOSE:
		atomic_set(&smd_info->opened, 0);
		DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s channel closed\n",
			 smd_info->name);
		queue_work(smd_info->wq, &(smd_info->close_work));
		break;
	case SMD_EVENT_DATA:
		diag_ws_on_notify();
		queue_work(smd_info->wq, &(smd_info->read_work));
		break;
	}

	wake_up_interruptible(&smd_info->read_wait_q);
}
예제 #2
0
static void socket_data_ready(struct sock *sk_ptr, int bytes)
{
	unsigned long flags;
	struct diag_socket_info *info = NULL;

	if (!sk_ptr) {
		pr_err_ratelimited("diag: In %s, invalid sk_ptr", __func__);
		return;
	}

	info = (struct diag_socket_info *)(sk_ptr->sk_user_data);
	if (!info) {
		pr_err_ratelimited("diag: In %s, invalid info\n", __func__);
		return;
	}

	spin_lock_irqsave(&info->lock, flags);
	info->data_ready++;
	spin_unlock_irqrestore(&info->lock, flags);
	diag_ws_on_notify();

	/*
	 * Initialize read buffers for the servers. The servers must read data
	 * first to get the address of its clients.
	 */
	if (!atomic_read(&info->opened) && info->port_type == PORT_TYPE_SERVER)
		diagfwd_buffers_init(info->fwd_ctxt);

	queue_work(info->wq, &(info->read_work));
	wake_up_interruptible(&info->read_wait_q);
	return;
}
예제 #3
0
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_ws_on_notify();
			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);
}
예제 #4
0
static void diag_hsic_read_complete_callback(void *ctxt, char *buf,
					int buf_size, int actual_size)
{
	int err = 0;
	int index = (int)ctxt;
	static DEFINE_RATELIMIT_STATE(rl, 10*HZ, 1);

	if (!diag_hsic[index].hsic_ch) {
		/*
		 * The HSIC channel is closed. Return the buffer to
		 * the pool.  Do not send it on.
		 */
		diagmem_free(driver, buf, index+POOL_TYPE_HSIC);
		pr_debug("diag: In %s: 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
			 */
			diag_bridge[index].write_len = actual_size;
			if (driver->logging_mode == MEMORY_DEVICE_MODE)
				diag_ws_on_notify();
			err = diag_device_write((void *)buf, index+HSIC_DATA,
									NULL);
			/* If an error, return buffer to the pool */
			if (err) {
				if (driver->logging_mode == MEMORY_DEVICE_MODE)
					diag_ws_release();
				diagmem_free(driver, buf, index +
							POOL_TYPE_HSIC);
				if (__ratelimit(&rl))
					pr_err("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, index+POOL_TYPE_HSIC);
		pr_debug("diag: In %s: error status: %d\n", __func__,
			actual_size);
	}

	/*
	 * Actual Size is a negative error value when read complete
	 * fails. Don't queue a read in this case. Doing so will not let
	 * HSIC to goto suspend.
	 *
	 * Queue another read only when the read completes successfully
	 * and Diag is either in Memory device mode or USB is connected.
	 */
	if (actual_size >= 0 && (driver->logging_mode == MEMORY_DEVICE_MODE ||
				 diag_bridge[index].usb_connected)) {
		queue_work(diag_bridge[index].wq,
				 &diag_hsic[index].diag_read_hsic_work);
	}
}