The snps,reserved-endpoints property lists the reserved endpoints that shouldn't be used for normal transfers. Add support for that to the driver. While at it, make sure we don't crash by a sudden access to those endpoints in the gadget driver. Signed-off-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx> --- drivers/usb/dwc3/gadget.c | 60 +++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index d27af65eb08a..93b1e389a983 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -547,6 +547,7 @@ static int dwc3_gadget_set_xfer_resource(struct dwc3_ep *dep) int dwc3_gadget_start_config(struct dwc3 *dwc, unsigned int resource_index) { struct dwc3_gadget_ep_cmd_params params; + struct dwc3_ep *dep; u32 cmd; int i; int ret; @@ -563,8 +564,13 @@ int dwc3_gadget_start_config(struct dwc3 *dwc, unsigned int resource_index) return ret; /* Reset resource allocation flags */ - for (i = resource_index; i < dwc->num_eps && dwc->eps[i]; i++) - dwc->eps[i]->flags &= ~DWC3_EP_RESOURCE_ALLOCATED; + for (i = resource_index; i < dwc->num_eps; i++) { + dep = dwc->eps[i]; + if (!dep) + continue; + + dep->flags &= ~DWC3_EP_RESOURCE_ALLOCATED; + } return 0; } @@ -751,9 +757,11 @@ void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc) dwc->last_fifo_depth = fifo_depth; /* Clear existing TXFIFO for all IN eps except ep0 */ - for (num = 3; num < min_t(int, dwc->num_eps, DWC3_ENDPOINTS_NUM); - num += 2) { + for (num = 3; num < min_t(int, dwc->num_eps, DWC3_ENDPOINTS_NUM); num += 2) { dep = dwc->eps[num]; + if (!dep) + continue; + /* Don't change TXFRAMNUM on usb31 version */ size = DWC3_IP_IS(DWC3) ? 0 : dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1)) & @@ -3395,14 +3403,52 @@ static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum) return 0; } +static int dwc3_gadget_parse_reserved_endpoints(struct dwc3 *dwc, const char *propname, + u8 *eps, u8 num) +{ + u8 count; + int ret; + + if (!device_property_present(dwc->dev, propname)) + return 0; + + ret = device_property_count_u8(dwc->dev, propname); + if (ret < 0) + return ret; + count = ret; + + ret = device_property_read_u8_array(dwc->dev, propname, eps, min(num, count)); + if (ret) + return ret; + + return count; +} + static int dwc3_gadget_init_endpoints(struct dwc3 *dwc, u8 total) { + const char *propname = "snps,reserved-endpoints"; u8 epnum; + u8 eps[DWC3_ENDPOINTS_NUM]; + u8 count; + u8 num; + int ret; INIT_LIST_HEAD(&dwc->gadget->ep_list); + ret = dwc3_gadget_parse_reserved_endpoints(dwc, propname, eps, ARRAY_SIZE(eps)); + if (ret < 0) { + dev_err(dwc->dev, "failed to read %s\n", propname); + return ret; + } + count = ret; + for (epnum = 0; epnum < total; epnum++) { - int ret; + for (num = 0; num < count; num++) { + if (epnum == eps[num]) + break; + } + if (num < count) + continue; ret = dwc3_gadget_init_endpoint(dwc, epnum); if (ret) @@ -3669,6 +3715,8 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep, for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) { dep = dwc->eps[i]; + if (!dep) + continue; if (!(dep->flags & DWC3_EP_ENABLED)) continue; @@ -3818,6 +3866,8 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, u8 epnum = event->endpoint_number; dep = dwc->eps[epnum]; + if (!dep) + return; if (!(dep->flags & DWC3_EP_ENABLED)) { if ((epnum > 1) && !(dep->flags & DWC3_EP_TRANSFER_STARTED)) -- 2.43.0.rc1.1336.g36b5255a03ac