diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 0a10aa2f8f5c..d7c5a3d1c4de 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -226,10 +226,7 @@ int dwc2_hsotg_tx_fifo_total_depth(struct dwc2_hsotg *hsotg) { int addr; int tx_addr_max; - u32 np_tx_fifo_size; - - np_tx_fifo_size = min_t(u32, hsotg->hw_params.dev_nperio_tx_fifo_size, - hsotg->params.g_np_tx_fifo_size); + u32 np_tx_fifo_size = hsotg->params.g_np_tx_fifo_size; /* Get Endpoint Info Control block size in DWORDs. */ tx_addr_max = hsotg->hw_params.total_fifo_size; diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 5d29c2157fbe..b25f7399b41c 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -767,6 +767,35 @@ static void dwc2_check_param_tx_fifo_sizes(struct dwc2_hsotg *hsotg) } } +static void dwc2_check_param_fifo_total(struct dwc2_hsotg *hsotg) +{ + struct dwc2_core_params *p = &hsotg->params; + u32 total_tx = 0; + u32 max_np; + int fifo_count; + int fifo; + + fifo_count = dwc2_hsotg_tx_fifo_count(hsotg); + for (fifo = 1; fifo <= fifo_count; fifo++) + total_tx += p->g_tx_fifo_size[fifo]; + + if (p->g_rx_fifo_size + p->g_np_tx_fifo_size + total_tx <= + hsotg->hw_params.total_fifo_size) + return; + + max_np = 16; + if (hsotg->hw_params.total_fifo_size > p->g_rx_fifo_size + total_tx) + max_np = hsotg->hw_params.total_fifo_size - + p->g_rx_fifo_size - total_tx; + if (max_np < 16) + max_np = 16; + + dev_warn(hsotg->dev, + "%s: FIFO sizes exceed total, clamping g_np_tx_fifo_size to %u\n", + __func__, max_np); + p->g_np_tx_fifo_size = max_np; +} + static void dwc2_check_param_eusb2_disc(struct dwc2_hsotg *hsotg) { u32 gsnpsid; @@ -879,9 +879,10 @@ static void dwc2_check_params(struct dwc2_hsotg *hsotg) CHECK_RANGE(g_rx_fifo_size, 16, hw->rx_fifo_size, hw->rx_fifo_size); CHECK_RANGE(g_np_tx_fifo_size, - 16, hw->dev_nperio_tx_fifo_size, + 16, hw->total_fifo_size, hw->dev_nperio_tx_fifo_size); dwc2_check_param_tx_fifo_sizes(hsotg); + dwc2_check_param_fifo_total(hsotg); } }