Loading drivers/usb/dwc3/core.h +3 −2 Original line number Diff line number Diff line Loading @@ -845,8 +845,9 @@ struct dwc3_scratchpad_array { #define DWC3_GSI_EVT_BUF_ALLOC 10 #define DWC3_GSI_EVT_BUF_SETUP 11 #define DWC3_GSI_EVT_BUF_CLEANUP 12 #define DWC3_GSI_EVT_BUF_FREE 13 #define DWC3_CONTROLLER_NOTIFY_CLEAR_DB 14 #define DWC3_GSI_EVT_BUF_CLEAR 13 #define DWC3_GSI_EVT_BUF_FREE 14 #define DWC3_CONTROLLER_NOTIFY_CLEAR_DB 15 #define MAX_INTR_STATS 10 Loading drivers/usb/dwc3/dwc3-msm.c +20 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -920,6 +920,11 @@ static int gsi_startxfer_for_ep(struct usb_ep *ep) struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3 *dwc = dep->dwc; if (!(dep->flags & DWC3_EP_ENABLED)) { dbg_log_string("ep:%s disabled\n", ep->name); return -ESHUTDOWN; } memset(¶ms, 0, sizeof(params)); params.param0 = GSI_TRB_ADDR_BIT_53_MASK | GSI_TRB_ADDR_BIT_55_MASK; params.param0 |= (ep->ep_intr_num << 16); Loading Loading @@ -1091,6 +1096,11 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req) struct scatterlist *sg; struct sg_table *sgt; if (!(dep->flags & DWC3_EP_ENABLED)) { dbg_log_string("ep:%s disabled\n", ep->name); return -ESHUTDOWN; } dep->trb_pool = dma_zalloc_coherent(dwc->sysdev, num_trbs * sizeof(struct dwc3_trb), &dep->trb_pool_dma, GFP_KERNEL); Loading Loading @@ -2023,6 +2033,15 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event, dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT((i+1)), 0); } break; case DWC3_GSI_EVT_BUF_CLEAR: dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_CLEAR\n"); for (i = 0; i < mdwc->num_gsi_event_buffers; i++) { reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT((i+1))); reg &= DWC3_GEVNTCOUNT_MASK; dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT((i+1)), reg); dbg_log_string("remaining EVNTCOUNT(%d)=%d", i+1, reg); } break; case DWC3_GSI_EVT_BUF_FREE: dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_FREE\n"); if (!mdwc->gsi_ev_buff) Loading drivers/usb/dwc3/gadget.c +34 −1 Original line number Diff line number Diff line Loading @@ -2008,7 +2008,7 @@ static int dwc3_gadget_set_selfpowered(struct usb_gadget *g, #define DWC3_SOFT_RESET_TIMEOUT 10 /* 10 msec */ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) { u32 reg; u32 reg, reg1; u32 timeout = 1500; reg = dwc3_readl(dwc->regs, DWC3_DCTL); Loading @@ -2034,7 +2034,13 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) } else { dbg_event(0xFF, "Pullup_disable", is_on); dwc3_gadget_disable_irq(dwc); /* Mask all interrupts */ reg1 = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0)); reg1 |= DWC3_GEVNTSIZ_INTMASK; dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg1); dwc->pullups_connected = false; __dwc3_gadget_ep_disable(dwc->eps[0]); __dwc3_gadget_ep_disable(dwc->eps[1]); Loading @@ -2054,6 +2060,19 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) dwc3_writel(dwc->regs, DWC3_DCTL, reg); /* Controller is not halted until the events are acknowledged */ if (!is_on) { /* * Clear out any pending events (i.e. End Transfer Command * Complete). */ reg1 = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); reg1 &= DWC3_GEVNTCOUNT_MASK; dbg_log_string("remaining EVNTCOUNT(0)=%d", reg1); dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg1); dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_CLEAR, 0); } do { reg = dwc3_readl(dwc->regs, DWC3_DSTS); reg &= DWC3_DSTS_DEVCTRLHLT; Loading Loading @@ -3765,6 +3784,20 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc) evt = dwc->ev_buf; /* Controller is being halted, ignore the interrupts */ if (!dwc->pullups_connected) { /* * Even with controller halted, there is a possibility * that the interrupt line is kept asserted. * As per the databook (3.00A - 6.3.57) read the GEVNTCOUNT * to ensure that the interrupt line is de-asserted. */ count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); count &= DWC3_GEVNTCOUNT_MASK; dbg_event(0xFF, "NO_PULLUP", count); return IRQ_HANDLED; } /* * With PCIe legacy interrupt, test shows that top-half irq handler can * be called again after HW interrupt deassertion. Check if bottom-half Loading drivers/usb/gadget/function/f_gsi.c +41 −8 Original line number Diff line number Diff line Loading @@ -213,6 +213,8 @@ static int gsi_wakeup_host(struct f_gsi *gsi) return -ENODEV; } gsi->rwake_inprogress = true; /* * In Super-Speed mode, remote wakeup is not allowed for suspended * functions which have been disallowed by the host to issue Function Loading @@ -235,6 +237,9 @@ static int gsi_wakeup_host(struct f_gsi *gsi) else if (ret) log_event_err("wakeup failed. ret=%d.", ret); if (ret) gsi->rwake_inprogress = false; return ret; } Loading Loading @@ -512,6 +517,7 @@ int ipa_usb_notify_cb(enum ipa_usb_notify_event event, break; case IPA_USB_REMOTE_WAKEUP: if (!gsi->rwake_inprogress) gsi_wakeup_host(gsi); break; Loading Loading @@ -541,10 +547,22 @@ static int ipa_connect_channels(struct gsi_data_port *d_port) struct ipa_req_chan_out_params ipa_out_channel_out_params; log_event_dbg("%s: USB GSI IN OPS", __func__); usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, ret = usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, GSI_EP_OP_PREPARE_TRBS); usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, if (ret) { log_event_err("%s: GSI_EP_OP_PREPARE_TRBS failed: %d\n", __func__, ret); return ret; } ret = usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, GSI_EP_OP_STARTXFER); if (ret) { log_event_err("%s: GSI_EP_OP_STARTXFER failed: %d\n", __func__, ret); return ret; } d_port->in_xfer_rsc_index = usb_gsi_ep_op(d_port->in_ep, NULL, GSI_EP_OP_GET_XFER_IDX); Loading Loading @@ -585,10 +603,22 @@ static int ipa_connect_channels(struct gsi_data_port *d_port) if (d_port->out_ep) { log_event_dbg("%s: USB GSI OUT OPS", __func__); usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, ret = usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, GSI_EP_OP_PREPARE_TRBS); usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, if (ret) { log_event_err("%s: GSI_EP_OP_PREPARE_TRBS failed: %d\n", __func__, ret); return ret; } ret = usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, GSI_EP_OP_STARTXFER); if (ret) { log_event_err("%s: GSI_EP_OP_STARTXFER failed: %d\n", __func__, ret); return ret; } d_port->out_xfer_rsc_index = usb_gsi_ep_op(d_port->out_ep, NULL, GSI_EP_OP_GET_XFER_IDX); Loading Loading @@ -1137,8 +1167,9 @@ static void gsi_ctrl_clear_cpkt_queues(struct f_gsi *gsi, bool skip_req_q) { struct gsi_ctrl_pkt *cpkt = NULL; struct list_head *act, *tmp; unsigned long flags; spin_lock(&gsi->c_port.lock); spin_lock_irqsave(&gsi->c_port.lock, flags); if (skip_req_q) goto clean_resp_q; Loading @@ -1153,7 +1184,7 @@ static void gsi_ctrl_clear_cpkt_queues(struct f_gsi *gsi, bool skip_req_q) list_del(&cpkt->list); gsi_ctrl_pkt_free(cpkt); } spin_unlock(&gsi->c_port.lock); spin_unlock_irqrestore(&gsi->c_port.lock, flags); } static int gsi_ctrl_send_cpkt_tomodem(struct f_gsi *gsi, void *buf, size_t len) Loading Loading @@ -1402,7 +1433,7 @@ static long gsi_ctrl_dev_ioctl(struct file *fp, unsigned int cmd, ctrl_device); struct f_gsi *gsi; struct gsi_ctrl_pkt *cpkt; struct ep_info info = { {0} }; struct ep_info info = { {0}, {0} }; int val, ret = 0; unsigned long flags; Loading Loading @@ -2622,6 +2653,8 @@ static void gsi_resume(struct usb_function *f) gsi->host_supports_flow_control) rndis_flow_control(gsi->params, false); gsi->rwake_inprogress = false; post_event(&gsi->d_port, EVT_RESUMED); queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w); Loading drivers/usb/gadget/function/f_gsi.h +2 −0 Original line number Diff line number Diff line Loading @@ -280,6 +280,8 @@ struct f_gsi { struct gsi_ctrl_port c_port; bool rmnet_dtr_status; bool rwake_inprogress; /* To test remote wakeup using debugfs */ struct timer_list gsi_rw_timer; u8 debugfs_rw_timer_enable; Loading Loading
drivers/usb/dwc3/core.h +3 −2 Original line number Diff line number Diff line Loading @@ -845,8 +845,9 @@ struct dwc3_scratchpad_array { #define DWC3_GSI_EVT_BUF_ALLOC 10 #define DWC3_GSI_EVT_BUF_SETUP 11 #define DWC3_GSI_EVT_BUF_CLEANUP 12 #define DWC3_GSI_EVT_BUF_FREE 13 #define DWC3_CONTROLLER_NOTIFY_CLEAR_DB 14 #define DWC3_GSI_EVT_BUF_CLEAR 13 #define DWC3_GSI_EVT_BUF_FREE 14 #define DWC3_CONTROLLER_NOTIFY_CLEAR_DB 15 #define MAX_INTR_STATS 10 Loading
drivers/usb/dwc3/dwc3-msm.c +20 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -920,6 +920,11 @@ static int gsi_startxfer_for_ep(struct usb_ep *ep) struct dwc3_ep *dep = to_dwc3_ep(ep); struct dwc3 *dwc = dep->dwc; if (!(dep->flags & DWC3_EP_ENABLED)) { dbg_log_string("ep:%s disabled\n", ep->name); return -ESHUTDOWN; } memset(¶ms, 0, sizeof(params)); params.param0 = GSI_TRB_ADDR_BIT_53_MASK | GSI_TRB_ADDR_BIT_55_MASK; params.param0 |= (ep->ep_intr_num << 16); Loading Loading @@ -1091,6 +1096,11 @@ static int gsi_prepare_trbs(struct usb_ep *ep, struct usb_gsi_request *req) struct scatterlist *sg; struct sg_table *sgt; if (!(dep->flags & DWC3_EP_ENABLED)) { dbg_log_string("ep:%s disabled\n", ep->name); return -ESHUTDOWN; } dep->trb_pool = dma_zalloc_coherent(dwc->sysdev, num_trbs * sizeof(struct dwc3_trb), &dep->trb_pool_dma, GFP_KERNEL); Loading Loading @@ -2023,6 +2033,15 @@ static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event, dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT((i+1)), 0); } break; case DWC3_GSI_EVT_BUF_CLEAR: dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_CLEAR\n"); for (i = 0; i < mdwc->num_gsi_event_buffers; i++) { reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT((i+1))); reg &= DWC3_GEVNTCOUNT_MASK; dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT((i+1)), reg); dbg_log_string("remaining EVNTCOUNT(%d)=%d", i+1, reg); } break; case DWC3_GSI_EVT_BUF_FREE: dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_FREE\n"); if (!mdwc->gsi_ev_buff) Loading
drivers/usb/dwc3/gadget.c +34 −1 Original line number Diff line number Diff line Loading @@ -2008,7 +2008,7 @@ static int dwc3_gadget_set_selfpowered(struct usb_gadget *g, #define DWC3_SOFT_RESET_TIMEOUT 10 /* 10 msec */ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) { u32 reg; u32 reg, reg1; u32 timeout = 1500; reg = dwc3_readl(dwc->regs, DWC3_DCTL); Loading @@ -2034,7 +2034,13 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) } else { dbg_event(0xFF, "Pullup_disable", is_on); dwc3_gadget_disable_irq(dwc); /* Mask all interrupts */ reg1 = dwc3_readl(dwc->regs, DWC3_GEVNTSIZ(0)); reg1 |= DWC3_GEVNTSIZ_INTMASK; dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), reg1); dwc->pullups_connected = false; __dwc3_gadget_ep_disable(dwc->eps[0]); __dwc3_gadget_ep_disable(dwc->eps[1]); Loading @@ -2054,6 +2060,19 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on, int suspend) dwc3_writel(dwc->regs, DWC3_DCTL, reg); /* Controller is not halted until the events are acknowledged */ if (!is_on) { /* * Clear out any pending events (i.e. End Transfer Command * Complete). */ reg1 = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); reg1 &= DWC3_GEVNTCOUNT_MASK; dbg_log_string("remaining EVNTCOUNT(0)=%d", reg1); dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg1); dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_CLEAR, 0); } do { reg = dwc3_readl(dwc->regs, DWC3_DSTS); reg &= DWC3_DSTS_DEVCTRLHLT; Loading Loading @@ -3765,6 +3784,20 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3 *dwc) evt = dwc->ev_buf; /* Controller is being halted, ignore the interrupts */ if (!dwc->pullups_connected) { /* * Even with controller halted, there is a possibility * that the interrupt line is kept asserted. * As per the databook (3.00A - 6.3.57) read the GEVNTCOUNT * to ensure that the interrupt line is de-asserted. */ count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); count &= DWC3_GEVNTCOUNT_MASK; dbg_event(0xFF, "NO_PULLUP", count); return IRQ_HANDLED; } /* * With PCIe legacy interrupt, test shows that top-half irq handler can * be called again after HW interrupt deassertion. Check if bottom-half Loading
drivers/usb/gadget/function/f_gsi.c +41 −8 Original line number Diff line number Diff line Loading @@ -213,6 +213,8 @@ static int gsi_wakeup_host(struct f_gsi *gsi) return -ENODEV; } gsi->rwake_inprogress = true; /* * In Super-Speed mode, remote wakeup is not allowed for suspended * functions which have been disallowed by the host to issue Function Loading @@ -235,6 +237,9 @@ static int gsi_wakeup_host(struct f_gsi *gsi) else if (ret) log_event_err("wakeup failed. ret=%d.", ret); if (ret) gsi->rwake_inprogress = false; return ret; } Loading Loading @@ -512,6 +517,7 @@ int ipa_usb_notify_cb(enum ipa_usb_notify_event event, break; case IPA_USB_REMOTE_WAKEUP: if (!gsi->rwake_inprogress) gsi_wakeup_host(gsi); break; Loading Loading @@ -541,10 +547,22 @@ static int ipa_connect_channels(struct gsi_data_port *d_port) struct ipa_req_chan_out_params ipa_out_channel_out_params; log_event_dbg("%s: USB GSI IN OPS", __func__); usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, ret = usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, GSI_EP_OP_PREPARE_TRBS); usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, if (ret) { log_event_err("%s: GSI_EP_OP_PREPARE_TRBS failed: %d\n", __func__, ret); return ret; } ret = usb_gsi_ep_op(d_port->in_ep, &d_port->in_request, GSI_EP_OP_STARTXFER); if (ret) { log_event_err("%s: GSI_EP_OP_STARTXFER failed: %d\n", __func__, ret); return ret; } d_port->in_xfer_rsc_index = usb_gsi_ep_op(d_port->in_ep, NULL, GSI_EP_OP_GET_XFER_IDX); Loading Loading @@ -585,10 +603,22 @@ static int ipa_connect_channels(struct gsi_data_port *d_port) if (d_port->out_ep) { log_event_dbg("%s: USB GSI OUT OPS", __func__); usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, ret = usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, GSI_EP_OP_PREPARE_TRBS); usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, if (ret) { log_event_err("%s: GSI_EP_OP_PREPARE_TRBS failed: %d\n", __func__, ret); return ret; } ret = usb_gsi_ep_op(d_port->out_ep, &d_port->out_request, GSI_EP_OP_STARTXFER); if (ret) { log_event_err("%s: GSI_EP_OP_STARTXFER failed: %d\n", __func__, ret); return ret; } d_port->out_xfer_rsc_index = usb_gsi_ep_op(d_port->out_ep, NULL, GSI_EP_OP_GET_XFER_IDX); Loading Loading @@ -1137,8 +1167,9 @@ static void gsi_ctrl_clear_cpkt_queues(struct f_gsi *gsi, bool skip_req_q) { struct gsi_ctrl_pkt *cpkt = NULL; struct list_head *act, *tmp; unsigned long flags; spin_lock(&gsi->c_port.lock); spin_lock_irqsave(&gsi->c_port.lock, flags); if (skip_req_q) goto clean_resp_q; Loading @@ -1153,7 +1184,7 @@ static void gsi_ctrl_clear_cpkt_queues(struct f_gsi *gsi, bool skip_req_q) list_del(&cpkt->list); gsi_ctrl_pkt_free(cpkt); } spin_unlock(&gsi->c_port.lock); spin_unlock_irqrestore(&gsi->c_port.lock, flags); } static int gsi_ctrl_send_cpkt_tomodem(struct f_gsi *gsi, void *buf, size_t len) Loading Loading @@ -1402,7 +1433,7 @@ static long gsi_ctrl_dev_ioctl(struct file *fp, unsigned int cmd, ctrl_device); struct f_gsi *gsi; struct gsi_ctrl_pkt *cpkt; struct ep_info info = { {0} }; struct ep_info info = { {0}, {0} }; int val, ret = 0; unsigned long flags; Loading Loading @@ -2622,6 +2653,8 @@ static void gsi_resume(struct usb_function *f) gsi->host_supports_flow_control) rndis_flow_control(gsi->params, false); gsi->rwake_inprogress = false; post_event(&gsi->d_port, EVT_RESUMED); queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w); Loading
drivers/usb/gadget/function/f_gsi.h +2 −0 Original line number Diff line number Diff line Loading @@ -280,6 +280,8 @@ struct f_gsi { struct gsi_ctrl_port c_port; bool rmnet_dtr_status; bool rwake_inprogress; /* To test remote wakeup using debugfs */ struct timer_list gsi_rw_timer; u8 debugfs_rw_timer_enable; Loading