static void diagfwd_bridge_notifier(void *priv, unsigned event, struct diag_request *d_req) { int index; switch (event) { case USB_DIAG_CONNECT: queue_work(driver->diag_wq, &driver->diag_connect_work); break; case USB_DIAG_DISCONNECT: queue_work(driver->diag_wq, &driver->diag_disconnect_work); break; case USB_DIAG_READ_DONE: index = (int)(d_req->context); queue_work(diag_bridge[index].wq, &diag_bridge[index].usb_read_complete_work); break; case USB_DIAG_WRITE_DONE: index = (int)(d_req->context); if (index == SMUX && driver->diag_smux_enabled) diagfwd_write_complete_smux(); else if (index < MAX_HSIC_CH && diag_hsic[index].hsic_device_enabled) diagfwd_write_complete_hsic(d_req, index); break; default: pr_err("diag: in %s: Unknown event from USB diag:%u\n", __func__, event); break; } }
static void diagfwd_bridge_notifier(void *priv, unsigned event, struct diag_request *d_req) { switch (event) { case USB_DIAG_CONNECT: diagfwd_connect_bridge(1); break; case USB_DIAG_DISCONNECT: queue_work(driver->diag_bridge_wq, &driver->diag_disconnect_work); break; case USB_DIAG_READ_DONE: queue_work(driver->diag_bridge_wq, &driver->diag_usb_read_complete_work); break; case USB_DIAG_WRITE_DONE: if (driver->hsic_device_enabled) diagfwd_write_complete_hsic(); else if (driver->diag_smux_enabled) diagfwd_write_complete_smux(); break; default: pr_err("diag: in %s: Unknown event from USB diag:%u\n", __func__, event); break; } }
static int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr) { driver->in_busy_hsic_read_on_device = 0; driver->read_len_mdm = diag_read_ptr->actual; if (driver->diag_smux_enabled) { diagfwd_read_complete_smux(); return 0; } if (!driver->hsic_ch) { pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__); return 0; } #if DIAG_XPST && defined(CONFIG_DIAG_BRIDGE_CODE) if (!driver->in_busy_hsic_write && driver->usb_buf_mdm_out && (driver->read_len_mdm > 0) && !driver->nohdlc) { #else if (!driver->in_busy_hsic_write && driver->usb_buf_mdm_out && (driver->read_len_mdm > 0)) { #endif int err; driver->in_busy_hsic_write = 1; err = diag_bridge_write(driver->usb_buf_mdm_out, driver->read_len_mdm); if (err) { pr_err_ratelimited("diag: mdm data on hsic write err: %d\n", err); if ((-ENODEV) != err) driver->in_busy_hsic_write = 0; } } if (!driver->in_busy_hsic_write) queue_work(driver->diag_bridge_wq, &driver->diag_read_mdm_work); return 0; } static void diagfwd_bridge_notifier(void *priv, unsigned event, struct diag_request *d_req) { switch (event) { case USB_DIAG_CONNECT: diagfwd_connect_bridge(1); break; case USB_DIAG_DISCONNECT: queue_work(driver->diag_bridge_wq, &driver->diag_disconnect_work); break; case USB_DIAG_READ_DONE: queue_work(driver->diag_bridge_wq, &driver->diag_usb_read_complete_work); break; case USB_DIAG_WRITE_DONE: if (driver->hsic_device_enabled) diagfwd_write_complete_hsic(d_req); else if (driver->diag_smux_enabled) diagfwd_write_complete_smux(); break; default: pr_err("diag: in %s: Unknown event from USB diag:%u\n", __func__, event); break; } } static void diag_usb_read_complete_fn(struct work_struct *w) { diagfwd_read_complete_bridge(driver->usb_read_mdm_ptr); }
int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr) { int index = (int)(diag_read_ptr->context); diag_bridge[index].read_len = diag_read_ptr->actual; if (index == SMUX) { if (driver->diag_smux_enabled) { diagfwd_read_complete_smux(); return 0; } else { pr_warning("diag: incorrect callback for smux\n"); } } driver->in_busy_hsic_read_on_device = 0; if (!driver->hsic_ch) { pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__); return 0; } #if DIAG_XPST if (!driver->in_busy_hsic_write && diag_bridge[HSIC].usb_buf_out && (diag_bridge[HSIC].read_len > 0) && !driver->nohdlc) { #else if (!driver->in_busy_hsic_write && diag_bridge[HSIC].usb_buf_out && (diag_bridge[HSIC].read_len > 0)) { #endif int err; driver->in_busy_hsic_write = 1; err = diag_bridge_write(diag_bridge[HSIC].usb_buf_out, diag_bridge[HSIC].read_len); if (err) { pr_err_ratelimited("diag: mdm data on HSIC write err: %d\n", err); if ((-ENODEV) != err) driver->in_busy_hsic_write = 0; } } if (!driver->in_busy_hsic_write) queue_work(diag_bridge[HSIC].wq, &diag_bridge[HSIC].diag_read_work); return 0; } static void diagfwd_bridge_notifier(void *priv, unsigned event, struct diag_request *d_req) { int index; switch (event) { case USB_DIAG_CONNECT: diagfwd_connect_bridge(1); break; case USB_DIAG_DISCONNECT: queue_work(driver->diag_wq, &driver->diag_disconnect_work); break; case USB_DIAG_READ_DONE: index = (int)(d_req->context); queue_work(diag_bridge[index].wq, &diag_bridge[index].usb_read_complete_work); break; case USB_DIAG_WRITE_DONE: index = (int)(d_req->context); if (index == HSIC && driver->hsic_device_enabled) diagfwd_write_complete_hsic(d_req); else if (index == SMUX && driver->diag_smux_enabled) diagfwd_write_complete_smux(); break; default: pr_err("diag: in %s: Unknown event from USB diag:%u\n", __func__, event); break; } }
/* Called after the asychronous usb_diag_read() on mdm channel is complete */ int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr) { int index = (int)(diag_read_ptr->context); /* The read of the usb on the mdm (not HSIC/SMUX) has completed */ diag_bridge[index].read_len = diag_read_ptr->actual; if (index == SMUX) { if (driver->diag_smux_enabled) { diagfwd_read_complete_smux(); return 0; } else { pr_warning("diag: incorrect callback for smux\n"); } } /* If SMUX not enabled, check for HSIC */ diag_hsic[index].in_busy_hsic_read_on_device = 0; if (!diag_hsic[index].hsic_ch) { pr_err("DIAG in %s: hsic_ch == 0, ch %d\n", __func__, index); return 0; } /* * The read of the usb driver on the mdm channel has completed. * If there is no write on the HSIC in progress, check if the * read has data to pass on to the HSIC. If so, pass the usb * mdm data on to the HSIC. */ #if DIAG_XPST if (!diag_hsic[index].in_busy_hsic_write && diag_bridge[index].usb_buf_out && (diag_bridge[index].read_len > 0) && !driver->nohdlc) { #else if (!diag_hsic[index].in_busy_hsic_write && diag_bridge[index].usb_buf_out && (diag_bridge[index].read_len > 0)) { #endif /* * Initiate the HSIC write. The HSIC write is * asynchronous. When complete the write * complete callback function will be called */ int err; diag_hsic[index].in_busy_hsic_write = 1; err = diag_bridge_write(index, diag_bridge[index].usb_buf_out, diag_bridge[index].read_len); if (err) { pr_err_ratelimited("diag: mdm data on HSIC write err: %d\n", err); /* * If the error is recoverable, then clear * the write flag, so we will resubmit a * write on the next frame. Otherwise, don't * resubmit a write on the next frame. */ if ((-ENODEV) != err) diag_hsic[index].in_busy_hsic_write = 0; } } /* * If there is no write of the usb mdm data on the * HSIC channel */ if (!diag_hsic[index].in_busy_hsic_write) queue_work(diag_bridge[index].wq, &diag_bridge[index].diag_read_work); return 0; } static void diagfwd_bridge_notifier(void *priv, unsigned event, struct diag_request *d_req) { int index; switch (event) { case USB_DIAG_CONNECT: queue_work(driver->diag_wq, &driver->diag_connect_work); break; case USB_DIAG_DISCONNECT: queue_work(driver->diag_wq, &driver->diag_disconnect_work); break; case USB_DIAG_READ_DONE: index = (int)(d_req->context); queue_work(diag_bridge[index].wq, &diag_bridge[index].usb_read_complete_work); break; case USB_DIAG_WRITE_DONE: index = (int)(d_req->context); if (index == SMUX && driver->diag_smux_enabled) diagfwd_write_complete_smux(); else if (diag_hsic[index].hsic_device_enabled) diagfwd_write_complete_hsic(d_req, index); break; default: pr_err("diag: in %s: Unknown event from USB diag:%u\n", __func__, event); break; } }