Skip to content

Commit e3c0c3c

Browse files
Selvarasu GanesanSasha Levin
authored andcommitted
usb: dwc3: gadget: Add missing check for single port RAM in TxFIFO resizing logic
[ Upstream commit 61eb055 ] The existing implementation of the TxFIFO resizing logic only supports scenarios where more than one port RAM is used. However, there is a need to resize the TxFIFO in USB2.0-only mode where only a single port RAM is available. This commit introduces the necessary changes to support TxFIFO resizing in such scenarios by adding a missing check for single port RAM. This fix addresses certain platform configurations where the existing TxFIFO resizing logic does not work properly due to the absence of support for single port RAM. By adding this missing check, we ensure that the TxFIFO resizing logic works correctly in all scenarios, including those with a single port RAM. Fixes: 9f607a3 ("usb: dwc3: Resize TX FIFOs to meet EP bursting requirements") Cc: stable@vger.kernel.org # 6.12.x: fad16c8: usb: dwc3: gadget: Refine the logic for resizing Tx FIFOs Signed-off-by: Selvarasu Ganesan <selvarasu.g@samsung.com> Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Link: https://lore.kernel.org/r/20241112044807.623-1-selvarasu.g@samsung.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 5caedf4 commit e3c0c3c

File tree

2 files changed

+50
-8
lines changed

2 files changed

+50
-8
lines changed

drivers/usb/dwc3/core.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,7 @@ struct dwc3_hwparams {
899899
#define DWC3_MODE(n) ((n) & 0x7)
900900

901901
/* HWPARAMS1 */
902+
#define DWC3_SPRAM_TYPE(n) (((n) >> 23) & 1)
902903
#define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15)
903904

904905
/* HWPARAMS3 */
@@ -909,6 +910,9 @@ struct dwc3_hwparams {
909910
#define DWC3_NUM_IN_EPS(p) (((p)->hwparams3 & \
910911
(DWC3_NUM_IN_EPS_MASK)) >> 18)
911912

913+
/* HWPARAMS6 */
914+
#define DWC3_RAM0_DEPTH(n) (((n) & (0xffff0000)) >> 16)
915+
912916
/* HWPARAMS7 */
913917
#define DWC3_RAM1_DEPTH(n) ((n) & 0xffff)
914918

drivers/usb/dwc3/gadget.c

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,44 @@ static int dwc3_gadget_calc_tx_fifo_size(struct dwc3 *dwc, int mult)
687687
return fifo_size;
688688
}
689689

690+
/**
691+
* dwc3_gadget_calc_ram_depth - calculates the ram depth for txfifo
692+
* @dwc: pointer to the DWC3 context
693+
*/
694+
static int dwc3_gadget_calc_ram_depth(struct dwc3 *dwc)
695+
{
696+
int ram_depth;
697+
int fifo_0_start;
698+
bool is_single_port_ram;
699+
700+
/* Check supporting RAM type by HW */
701+
is_single_port_ram = DWC3_SPRAM_TYPE(dwc->hwparams.hwparams1);
702+
703+
/*
704+
* If a single port RAM is utilized, then allocate TxFIFOs from
705+
* RAM0. otherwise, allocate them from RAM1.
706+
*/
707+
ram_depth = is_single_port_ram ? DWC3_RAM0_DEPTH(dwc->hwparams.hwparams6) :
708+
DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
709+
710+
/*
711+
* In a single port RAM configuration, the available RAM is shared
712+
* between the RX and TX FIFOs. This means that the txfifo can begin
713+
* at a non-zero address.
714+
*/
715+
if (is_single_port_ram) {
716+
u32 reg;
717+
718+
/* Check if TXFIFOs start at non-zero addr */
719+
reg = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
720+
fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(reg);
721+
722+
ram_depth -= (fifo_0_start >> 16);
723+
}
724+
725+
return ram_depth;
726+
}
727+
690728
/**
691729
* dwc3_gadget_clear_tx_fifos - Clears txfifo allocation
692730
* @dwc: pointer to the DWC3 context
@@ -753,7 +791,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
753791
{
754792
struct dwc3 *dwc = dep->dwc;
755793
int fifo_0_start;
756-
int ram1_depth;
794+
int ram_depth;
757795
int fifo_size;
758796
int min_depth;
759797
int num_in_ep;
@@ -773,7 +811,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
773811
if (dep->flags & DWC3_EP_TXFIFO_RESIZED)
774812
return 0;
775813

776-
ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
814+
ram_depth = dwc3_gadget_calc_ram_depth(dwc);
777815

778816
if ((dep->endpoint.maxburst > 1 &&
779817
usb_endpoint_xfer_bulk(dep->endpoint.desc)) ||
@@ -794,7 +832,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
794832

795833
/* Reserve at least one FIFO for the number of IN EPs */
796834
min_depth = num_in_ep * (fifo + 1);
797-
remaining = ram1_depth - min_depth - dwc->last_fifo_depth;
835+
remaining = ram_depth - min_depth - dwc->last_fifo_depth;
798836
remaining = max_t(int, 0, remaining);
799837
/*
800838
* We've already reserved 1 FIFO per EP, so check what we can fit in
@@ -820,9 +858,9 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
820858
dwc->last_fifo_depth += DWC31_GTXFIFOSIZ_TXFDEP(fifo_size);
821859

822860
/* Check fifo size allocation doesn't exceed available RAM size. */
823-
if (dwc->last_fifo_depth >= ram1_depth) {
861+
if (dwc->last_fifo_depth >= ram_depth) {
824862
dev_err(dwc->dev, "Fifosize(%d) > RAM size(%d) %s depth:%d\n",
825-
dwc->last_fifo_depth, ram1_depth,
863+
dwc->last_fifo_depth, ram_depth,
826864
dep->endpoint.name, fifo_size);
827865
if (DWC3_IP_IS(DWC3))
828866
fifo_size = DWC3_GTXFIFOSIZ_TXFDEP(fifo_size);
@@ -3078,7 +3116,7 @@ static int dwc3_gadget_check_config(struct usb_gadget *g)
30783116
struct dwc3 *dwc = gadget_to_dwc(g);
30793117
struct usb_ep *ep;
30803118
int fifo_size = 0;
3081-
int ram1_depth;
3119+
int ram_depth;
30823120
int ep_num = 0;
30833121

30843122
if (!dwc->do_fifo_resize)
@@ -3101,8 +3139,8 @@ static int dwc3_gadget_check_config(struct usb_gadget *g)
31013139
fifo_size += dwc->max_cfg_eps;
31023140

31033141
/* Check if we can fit a single fifo per endpoint */
3104-
ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
3105-
if (fifo_size > ram1_depth)
3142+
ram_depth = dwc3_gadget_calc_ram_depth(dwc);
3143+
if (fifo_size > ram_depth)
31063144
return -ENOMEM;
31073145

31083146
return 0;

0 commit comments

Comments
 (0)