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); }
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; }
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); }
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); } }