Loading drivers/usb/dwc3/core.h +15 −13 Original line number Diff line number Diff line Loading @@ -516,6 +516,19 @@ struct dwc3_trb; /** * struct dwc3_gadget_ep_cmd_params - representation of endpoint command * parameters * @param2: third parameter * @param1: second parameter * @param0: first parameter */ struct dwc3_gadget_ep_cmd_params { u32 param2; u32 param1; u32 param0; }; /** * struct dwc3_event_buffer - Software event buffer representation * @buf: _THE_ buffer Loading Loading @@ -606,6 +619,7 @@ struct dwc3_ep_events { * @dbg_ep_events_diff: differential events counter for endpoint * @dbg_ep_events_ts: timestamp for previous event counters * @fifo_depth: allocated TXFIFO depth * @ep_cfg_init_params: Used by GSI EP to save EP_CFG init_cmd params */ struct dwc3_ep { struct usb_ep endpoint; Loading Loading @@ -661,6 +675,7 @@ struct dwc3_ep { struct dwc3_ep_events dbg_ep_events_diff; struct timespec dbg_ep_events_ts; int fifo_depth; struct dwc3_gadget_ep_cmd_params ep_cfg_init_params; }; enum dwc3_phy { Loading Loading @@ -1306,19 +1321,6 @@ union dwc3_event { struct dwc3_event_gevt gevt; }; /** * struct dwc3_gadget_ep_cmd_params - representation of endpoint command * parameters * @param2: third parameter * @param1: second parameter * @param0: first parameter */ struct dwc3_gadget_ep_cmd_params { u32 param2; u32 param1; u32 param0; }; /* * DWC3 Features to be used as Driver Data */ Loading drivers/usb/dwc3/dwc3-msm.c +109 −5 Original line number Diff line number Diff line Loading @@ -309,6 +309,9 @@ struct dwc3_msm { struct mutex suspend_resume_mutex; enum usb_device_speed override_usb_speed; u64 dummy_gsi_db; dma_addr_t dummy_gsi_db_dma; }; #define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */ Loading Loading @@ -974,6 +977,12 @@ static void gsi_store_ringbase_dbl_info(struct usb_ep *ep, ep->name, request->db_reg_phs_addr_lsb, (unsigned long long)request->mapped_db_reg_phs_addr_lsb); /* * Replace dummy doorbell address with real one as IPA connection * is setup now and GSI must be ready to handle doorbell updates. */ dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_H(n), 0x0); dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_L(n), (u32)request->mapped_db_reg_phs_addr_lsb); dev_dbg(mdwc->dev, "Ring Base Addr %d: %x (LSB)\n", n, Loading Loading @@ -1232,6 +1241,7 @@ static void gsi_free_trbs(struct usb_ep *ep, struct usb_gsi_request *req) } sg_free_table(&req->sgt_trb_xfer_ring); } /* * Configures GSI EPs. For GSI EPs we need to set interrupter numbers. * Loading @@ -1246,9 +1256,20 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request) struct dwc3_gadget_ep_cmd_params params; const struct usb_endpoint_descriptor *desc = ep->desc; const struct usb_ss_ep_comp_descriptor *comp_desc = ep->comp_desc; int n = ep->ep_intr_num - 1; u32 reg; int ret; /* setup dummy doorbell as IPA connection isn't setup yet */ dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_H(n), (u32)((u64)mdwc->dummy_gsi_db_dma >> 32)); dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_L(n), (u32)mdwc->dummy_gsi_db_dma); dev_dbg(mdwc->dev, "Dummy DB Addr %pK: %llx %x (LSB)\n", &mdwc->dummy_gsi_db, (unsigned long long)mdwc->dummy_gsi_db_dma, (u32)mdwc->dummy_gsi_db_dma); memset(¶ms, 0x00, sizeof(params)); /* Configure GSI EP */ Loading @@ -1274,10 +1295,8 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request) /* Set interrupter number for GSI endpoints */ params.param1 |= DWC3_DEPCFG_INT_NUM(ep->ep_intr_num); /* Enable XferInProgress and XferComplete Interrupts */ params.param1 |= DWC3_DEPCFG_XFER_COMPLETE_EN; params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN; params.param1 |= DWC3_DEPCFG_FIFO_ERROR_EN; /* EP Events are enabled later once DBL_ADDR is updated */ /* * We must use the lower 16 TX FIFOs even though * HW might have more Loading @@ -1291,6 +1310,9 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request) dev_dbg(mdwc->dev, "Set EP config to params = %x %x %x, for %s\n", params.param0, params.param1, params.param2, dep->name); /* params are used later when EP_CONFIG is modified to enable events */ dep->ep_cfg_init_params = params; dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, ¶ms); /* Set XferRsc Index for GSI EP */ Loading @@ -1315,6 +1337,57 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request) } /* * Enables events for GSI EPs. Modify EP_CONFIG to enable EP events * after GSI wrapper is initialized for the endpoint. * * @usb_ep - pointer to usb_ep instance. */ static void gsi_enable_ep_events(struct usb_ep *ep) { struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3_msm *mdwc = dev_get_drvdata(dep->dwc->dev->parent); struct dwc3_gadget_ep_cmd_params params; /* EP is already configured, just update params to enable events */ params = dep->ep_cfg_init_params; /* Enable XferInProgress and XferComplete Interrupts */ params.param1 |= DWC3_DEPCFG_XFER_COMPLETE_EN; params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN; params.param1 |= DWC3_DEPCFG_FIFO_ERROR_EN; params.param0 |= DWC3_DEPCFG_ACTION_MODIFY; dev_dbg(mdwc->dev, "Modify EP config to params = %x %x %x, for %s\n", params.param0, params.param1, params.param2, dep->name); dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, ¶ms); } /* * Disables events for GSI EPs. Modify EP_CONFIG to disable EP events * to prevent USB GSI wrapper from ringing any doorbell. * * @usb_ep - pointer to usb_ep instance. */ static void gsi_disable_ep_events(struct usb_ep *ep) { struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3_msm *mdwc = dev_get_drvdata(dep->dwc->dev->parent); struct dwc3_gadget_ep_cmd_params params; /* EP is already enabled, just restore init_params to disable events */ params = dep->ep_cfg_init_params; params.param0 |= DWC3_DEPCFG_ACTION_MODIFY; dev_dbg(mdwc->dev, "Modify EP config to params = %x %x %x, for %s\n", params.param0, params.param1, params.param2, dep->name); dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, ¶ms); } /* * Enables USB wrapper for GSI * Loading Loading @@ -1352,6 +1425,16 @@ static void gsi_set_clear_dbell(struct usb_ep *ep, struct dwc3 *dwc = dep->dwc; struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent); /* * Disable EP events if doorbell needs to be blocked to avoid issues * due to another GSI interface endpoint enabling doorbell say on resume * as there is no control of doorbell per endpoint. */ if (block_db) gsi_disable_ep_events(ep); else gsi_enable_ep_events(ep); dwc3_msm_write_reg_field(mdwc->base, GSI_GENERAL_CFG_REG, BLOCK_GSI_WR_GO_MASK, block_db); } Loading Loading @@ -1462,7 +1545,9 @@ static int dwc3_msm_gsi_ep_op(struct usb_ep *ep, break; case GSI_EP_OP_SET_CLR_BLOCK_DBL: block_db = *((bool *)op_data); spin_lock_irqsave(&dwc->lock, flags); gsi_set_clear_dbell(ep, block_db); spin_unlock_irqrestore(&dwc->lock, flags); break; case GSI_EP_OP_CHECK_FOR_SUSPEND: ret = gsi_check_ready_to_suspend(mdwc); Loading Loading @@ -1967,6 +2052,19 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event, } mdwc->gsi_ev_buff[i] = evt; } /* * Set-up dummy buffer to use as doorbell while IPA GSI * connection is in progress. */ mdwc->dummy_gsi_db_dma = dma_map_single(dwc->sysdev, &mdwc->dummy_gsi_db, sizeof(mdwc->dummy_gsi_db), DMA_FROM_DEVICE); if (dma_mapping_error(dwc->sysdev, mdwc->dummy_gsi_db_dma)) { dev_err(dwc->dev, "failed to map dummy doorbell buffer\n"); mdwc->dummy_gsi_db_dma = (dma_addr_t)NULL; } break; case DWC3_GSI_EVT_BUF_SETUP: dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_SETUP\n"); Loading Loading @@ -2040,6 +2138,12 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event, dma_free_coherent(dwc->sysdev, evt->length, evt->buf, evt->dma); } if (mdwc->dummy_gsi_db_dma) { dma_unmap_single(dwc->sysdev, mdwc->dummy_gsi_db_dma, sizeof(mdwc->dummy_gsi_db), DMA_FROM_DEVICE); mdwc->dummy_gsi_db_dma = (dma_addr_t)NULL; } break; case DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER: dwc3_msm_dbm_disable_updxfer(dwc, value); Loading drivers/usb/gadget/function/f_gsi.c +36 −17 Original line number Diff line number Diff line Loading @@ -746,33 +746,34 @@ static void ipa_data_path_enable(struct gsi_data_port *d_port) bool block_db = false; log_event_dbg("IN: db_reg_phs_addr_lsb = %x", gsi->d_port.in_request.db_reg_phs_addr_lsb); usb_gsi_ep_op(gsi->d_port.in_ep, &gsi->d_port.in_request, d_port->in_request.db_reg_phs_addr_lsb); usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, GSI_EP_OP_STORE_DBL_INFO); if (gsi->d_port.out_ep) { if (d_port->out_ep) { log_event_dbg("OUT: db_reg_phs_addr_lsb = %x", gsi->d_port.out_request.db_reg_phs_addr_lsb); usb_gsi_ep_op(gsi->d_port.out_ep, &gsi->d_port.out_request, d_port->out_request.db_reg_phs_addr_lsb); usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, GSI_EP_OP_STORE_DBL_INFO); } usb_gsi_ep_op(gsi->d_port.in_ep, &gsi->d_port.in_request, usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, GSI_EP_OP_ENABLE_GSI); /* Unblock doorbell to GSI */ usb_gsi_ep_op(d_port->in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); usb_gsi_ep_op(gsi->d_port.in_ep, &gsi->d_port.in_request, usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, GSI_EP_OP_RING_DB); if (gsi->d_port.out_ep) usb_gsi_ep_op(gsi->d_port.out_ep, &gsi->d_port.out_request, if (d_port->out_ep) { usb_gsi_ep_op(d_port->out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, GSI_EP_OP_RING_DB); } } static void ipa_disconnect_handler(struct gsi_data_port *d_port) { Loading @@ -792,9 +793,12 @@ static void ipa_disconnect_handler(struct gsi_data_port *d_port) &gsi->d_port.in_request, GSI_EP_OP_DISABLE); } if (gsi->d_port.out_ep) if (gsi->d_port.out_ep) { usb_gsi_ep_op(d_port->out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); usb_gsi_ep_op(gsi->d_port.out_ep, &gsi->d_port.out_request, GSI_EP_OP_DISABLE); } gsi->d_port.net_ready_trigger = false; } Loading Loading @@ -846,6 +850,10 @@ static int ipa_suspend_work_handler(struct gsi_data_port *d_port) block_db = false; usb_gsi_ep_op(d_port->in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); if (d_port->out_ep) usb_gsi_ep_op(d_port->out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); goto done; } Loading @@ -864,6 +872,9 @@ static int ipa_suspend_work_handler(struct gsi_data_port *d_port) block_db = false; usb_gsi_ep_op(d_port->in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); if (d_port->out_ep) usb_gsi_ep_op(d_port->out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); gsi_wakeup_host(gsi); } else if (ret == -EINPROGRESS) { d_port->sm_state = STATE_SUSPEND_IN_PROGRESS; Loading Loading @@ -895,6 +906,9 @@ static void ipa_resume_work_handler(struct gsi_data_port *d_port) block_db = false; usb_gsi_ep_op(d_port->in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); if (d_port->out_ep) usb_gsi_ep_op(d_port->out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); } static void ipa_work_handler(struct work_struct *w) Loading Loading @@ -1059,9 +1073,11 @@ static void ipa_work_handler(struct work_struct *w) log_event_dbg("%s: ST_CON_HOST_NRDY\n", __func__); block_db = true; /* stop USB ringing doorbell to GSI(OUT_EP) */ /* stop USB ringing doorbell to GSI(both EPs) */ usb_gsi_ep_op(d_port->in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); usb_gsi_ep_op(d_port->out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); gsi_rndis_ipa_reset_trigger(d_port); usb_gsi_ep_op(d_port->in_ep, NULL, GSI_EP_OP_ENDXFER); Loading Loading @@ -2637,6 +2653,9 @@ static void gsi_suspend(struct usb_function *f) block_db = true; usb_gsi_ep_op(gsi->d_port.in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); if (gsi->d_port.out_ep) usb_gsi_ep_op(gsi->d_port.out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); post_event(&gsi->d_port, EVT_SUSPEND); queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w); log_event_dbg("gsi suspended"); Loading Loading
drivers/usb/dwc3/core.h +15 −13 Original line number Diff line number Diff line Loading @@ -516,6 +516,19 @@ struct dwc3_trb; /** * struct dwc3_gadget_ep_cmd_params - representation of endpoint command * parameters * @param2: third parameter * @param1: second parameter * @param0: first parameter */ struct dwc3_gadget_ep_cmd_params { u32 param2; u32 param1; u32 param0; }; /** * struct dwc3_event_buffer - Software event buffer representation * @buf: _THE_ buffer Loading Loading @@ -606,6 +619,7 @@ struct dwc3_ep_events { * @dbg_ep_events_diff: differential events counter for endpoint * @dbg_ep_events_ts: timestamp for previous event counters * @fifo_depth: allocated TXFIFO depth * @ep_cfg_init_params: Used by GSI EP to save EP_CFG init_cmd params */ struct dwc3_ep { struct usb_ep endpoint; Loading Loading @@ -661,6 +675,7 @@ struct dwc3_ep { struct dwc3_ep_events dbg_ep_events_diff; struct timespec dbg_ep_events_ts; int fifo_depth; struct dwc3_gadget_ep_cmd_params ep_cfg_init_params; }; enum dwc3_phy { Loading Loading @@ -1306,19 +1321,6 @@ union dwc3_event { struct dwc3_event_gevt gevt; }; /** * struct dwc3_gadget_ep_cmd_params - representation of endpoint command * parameters * @param2: third parameter * @param1: second parameter * @param0: first parameter */ struct dwc3_gadget_ep_cmd_params { u32 param2; u32 param1; u32 param0; }; /* * DWC3 Features to be used as Driver Data */ Loading
drivers/usb/dwc3/dwc3-msm.c +109 −5 Original line number Diff line number Diff line Loading @@ -309,6 +309,9 @@ struct dwc3_msm { struct mutex suspend_resume_mutex; enum usb_device_speed override_usb_speed; u64 dummy_gsi_db; dma_addr_t dummy_gsi_db_dma; }; #define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */ Loading Loading @@ -974,6 +977,12 @@ static void gsi_store_ringbase_dbl_info(struct usb_ep *ep, ep->name, request->db_reg_phs_addr_lsb, (unsigned long long)request->mapped_db_reg_phs_addr_lsb); /* * Replace dummy doorbell address with real one as IPA connection * is setup now and GSI must be ready to handle doorbell updates. */ dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_H(n), 0x0); dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_L(n), (u32)request->mapped_db_reg_phs_addr_lsb); dev_dbg(mdwc->dev, "Ring Base Addr %d: %x (LSB)\n", n, Loading Loading @@ -1232,6 +1241,7 @@ static void gsi_free_trbs(struct usb_ep *ep, struct usb_gsi_request *req) } sg_free_table(&req->sgt_trb_xfer_ring); } /* * Configures GSI EPs. For GSI EPs we need to set interrupter numbers. * Loading @@ -1246,9 +1256,20 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request) struct dwc3_gadget_ep_cmd_params params; const struct usb_endpoint_descriptor *desc = ep->desc; const struct usb_ss_ep_comp_descriptor *comp_desc = ep->comp_desc; int n = ep->ep_intr_num - 1; u32 reg; int ret; /* setup dummy doorbell as IPA connection isn't setup yet */ dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_H(n), (u32)((u64)mdwc->dummy_gsi_db_dma >> 32)); dwc3_msm_write_reg(mdwc->base, GSI_DBL_ADDR_L(n), (u32)mdwc->dummy_gsi_db_dma); dev_dbg(mdwc->dev, "Dummy DB Addr %pK: %llx %x (LSB)\n", &mdwc->dummy_gsi_db, (unsigned long long)mdwc->dummy_gsi_db_dma, (u32)mdwc->dummy_gsi_db_dma); memset(¶ms, 0x00, sizeof(params)); /* Configure GSI EP */ Loading @@ -1274,10 +1295,8 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request) /* Set interrupter number for GSI endpoints */ params.param1 |= DWC3_DEPCFG_INT_NUM(ep->ep_intr_num); /* Enable XferInProgress and XferComplete Interrupts */ params.param1 |= DWC3_DEPCFG_XFER_COMPLETE_EN; params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN; params.param1 |= DWC3_DEPCFG_FIFO_ERROR_EN; /* EP Events are enabled later once DBL_ADDR is updated */ /* * We must use the lower 16 TX FIFOs even though * HW might have more Loading @@ -1291,6 +1310,9 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request) dev_dbg(mdwc->dev, "Set EP config to params = %x %x %x, for %s\n", params.param0, params.param1, params.param2, dep->name); /* params are used later when EP_CONFIG is modified to enable events */ dep->ep_cfg_init_params = params; dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, ¶ms); /* Set XferRsc Index for GSI EP */ Loading @@ -1315,6 +1337,57 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request) } /* * Enables events for GSI EPs. Modify EP_CONFIG to enable EP events * after GSI wrapper is initialized for the endpoint. * * @usb_ep - pointer to usb_ep instance. */ static void gsi_enable_ep_events(struct usb_ep *ep) { struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3_msm *mdwc = dev_get_drvdata(dep->dwc->dev->parent); struct dwc3_gadget_ep_cmd_params params; /* EP is already configured, just update params to enable events */ params = dep->ep_cfg_init_params; /* Enable XferInProgress and XferComplete Interrupts */ params.param1 |= DWC3_DEPCFG_XFER_COMPLETE_EN; params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN; params.param1 |= DWC3_DEPCFG_FIFO_ERROR_EN; params.param0 |= DWC3_DEPCFG_ACTION_MODIFY; dev_dbg(mdwc->dev, "Modify EP config to params = %x %x %x, for %s\n", params.param0, params.param1, params.param2, dep->name); dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, ¶ms); } /* * Disables events for GSI EPs. Modify EP_CONFIG to disable EP events * to prevent USB GSI wrapper from ringing any doorbell. * * @usb_ep - pointer to usb_ep instance. */ static void gsi_disable_ep_events(struct usb_ep *ep) { struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3_msm *mdwc = dev_get_drvdata(dep->dwc->dev->parent); struct dwc3_gadget_ep_cmd_params params; /* EP is already enabled, just restore init_params to disable events */ params = dep->ep_cfg_init_params; params.param0 |= DWC3_DEPCFG_ACTION_MODIFY; dev_dbg(mdwc->dev, "Modify EP config to params = %x %x %x, for %s\n", params.param0, params.param1, params.param2, dep->name); dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, ¶ms); } /* * Enables USB wrapper for GSI * Loading Loading @@ -1352,6 +1425,16 @@ static void gsi_set_clear_dbell(struct usb_ep *ep, struct dwc3 *dwc = dep->dwc; struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent); /* * Disable EP events if doorbell needs to be blocked to avoid issues * due to another GSI interface endpoint enabling doorbell say on resume * as there is no control of doorbell per endpoint. */ if (block_db) gsi_disable_ep_events(ep); else gsi_enable_ep_events(ep); dwc3_msm_write_reg_field(mdwc->base, GSI_GENERAL_CFG_REG, BLOCK_GSI_WR_GO_MASK, block_db); } Loading Loading @@ -1462,7 +1545,9 @@ static int dwc3_msm_gsi_ep_op(struct usb_ep *ep, break; case GSI_EP_OP_SET_CLR_BLOCK_DBL: block_db = *((bool *)op_data); spin_lock_irqsave(&dwc->lock, flags); gsi_set_clear_dbell(ep, block_db); spin_unlock_irqrestore(&dwc->lock, flags); break; case GSI_EP_OP_CHECK_FOR_SUSPEND: ret = gsi_check_ready_to_suspend(mdwc); Loading Loading @@ -1967,6 +2052,19 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event, } mdwc->gsi_ev_buff[i] = evt; } /* * Set-up dummy buffer to use as doorbell while IPA GSI * connection is in progress. */ mdwc->dummy_gsi_db_dma = dma_map_single(dwc->sysdev, &mdwc->dummy_gsi_db, sizeof(mdwc->dummy_gsi_db), DMA_FROM_DEVICE); if (dma_mapping_error(dwc->sysdev, mdwc->dummy_gsi_db_dma)) { dev_err(dwc->dev, "failed to map dummy doorbell buffer\n"); mdwc->dummy_gsi_db_dma = (dma_addr_t)NULL; } break; case DWC3_GSI_EVT_BUF_SETUP: dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_SETUP\n"); Loading Loading @@ -2040,6 +2138,12 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event, dma_free_coherent(dwc->sysdev, evt->length, evt->buf, evt->dma); } if (mdwc->dummy_gsi_db_dma) { dma_unmap_single(dwc->sysdev, mdwc->dummy_gsi_db_dma, sizeof(mdwc->dummy_gsi_db), DMA_FROM_DEVICE); mdwc->dummy_gsi_db_dma = (dma_addr_t)NULL; } break; case DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER: dwc3_msm_dbm_disable_updxfer(dwc, value); Loading
drivers/usb/gadget/function/f_gsi.c +36 −17 Original line number Diff line number Diff line Loading @@ -746,33 +746,34 @@ static void ipa_data_path_enable(struct gsi_data_port *d_port) bool block_db = false; log_event_dbg("IN: db_reg_phs_addr_lsb = %x", gsi->d_port.in_request.db_reg_phs_addr_lsb); usb_gsi_ep_op(gsi->d_port.in_ep, &gsi->d_port.in_request, d_port->in_request.db_reg_phs_addr_lsb); usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, GSI_EP_OP_STORE_DBL_INFO); if (gsi->d_port.out_ep) { if (d_port->out_ep) { log_event_dbg("OUT: db_reg_phs_addr_lsb = %x", gsi->d_port.out_request.db_reg_phs_addr_lsb); usb_gsi_ep_op(gsi->d_port.out_ep, &gsi->d_port.out_request, d_port->out_request.db_reg_phs_addr_lsb); usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, GSI_EP_OP_STORE_DBL_INFO); } usb_gsi_ep_op(gsi->d_port.in_ep, &gsi->d_port.in_request, usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, GSI_EP_OP_ENABLE_GSI); /* Unblock doorbell to GSI */ usb_gsi_ep_op(d_port->in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); usb_gsi_ep_op(gsi->d_port.in_ep, &gsi->d_port.in_request, usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, GSI_EP_OP_RING_DB); if (gsi->d_port.out_ep) usb_gsi_ep_op(gsi->d_port.out_ep, &gsi->d_port.out_request, if (d_port->out_ep) { usb_gsi_ep_op(d_port->out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, GSI_EP_OP_RING_DB); } } static void ipa_disconnect_handler(struct gsi_data_port *d_port) { Loading @@ -792,9 +793,12 @@ static void ipa_disconnect_handler(struct gsi_data_port *d_port) &gsi->d_port.in_request, GSI_EP_OP_DISABLE); } if (gsi->d_port.out_ep) if (gsi->d_port.out_ep) { usb_gsi_ep_op(d_port->out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); usb_gsi_ep_op(gsi->d_port.out_ep, &gsi->d_port.out_request, GSI_EP_OP_DISABLE); } gsi->d_port.net_ready_trigger = false; } Loading Loading @@ -846,6 +850,10 @@ static int ipa_suspend_work_handler(struct gsi_data_port *d_port) block_db = false; usb_gsi_ep_op(d_port->in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); if (d_port->out_ep) usb_gsi_ep_op(d_port->out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); goto done; } Loading @@ -864,6 +872,9 @@ static int ipa_suspend_work_handler(struct gsi_data_port *d_port) block_db = false; usb_gsi_ep_op(d_port->in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); if (d_port->out_ep) usb_gsi_ep_op(d_port->out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); gsi_wakeup_host(gsi); } else if (ret == -EINPROGRESS) { d_port->sm_state = STATE_SUSPEND_IN_PROGRESS; Loading Loading @@ -895,6 +906,9 @@ static void ipa_resume_work_handler(struct gsi_data_port *d_port) block_db = false; usb_gsi_ep_op(d_port->in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); if (d_port->out_ep) usb_gsi_ep_op(d_port->out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); } static void ipa_work_handler(struct work_struct *w) Loading Loading @@ -1059,9 +1073,11 @@ static void ipa_work_handler(struct work_struct *w) log_event_dbg("%s: ST_CON_HOST_NRDY\n", __func__); block_db = true; /* stop USB ringing doorbell to GSI(OUT_EP) */ /* stop USB ringing doorbell to GSI(both EPs) */ usb_gsi_ep_op(d_port->in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); usb_gsi_ep_op(d_port->out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); gsi_rndis_ipa_reset_trigger(d_port); usb_gsi_ep_op(d_port->in_ep, NULL, GSI_EP_OP_ENDXFER); Loading Loading @@ -2637,6 +2653,9 @@ static void gsi_suspend(struct usb_function *f) block_db = true; usb_gsi_ep_op(gsi->d_port.in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); if (gsi->d_port.out_ep) usb_gsi_ep_op(gsi->d_port.out_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); post_event(&gsi->d_port, EVT_SUSPEND); queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w); log_event_dbg("gsi suspended"); Loading