Re: [PATCH] usb: dwc3: gadget: Add TxFIFO resizing supports for single port RAM

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 11/8/2024 5:04 AM, Thinh Nguyen wrote:
> On Thu, Nov 07, 2024, Selvarasu Ganesan wrote:
>> This commit adds support for resizing the TxFIFO in USB2.0-only mode
>> where using single port RAM, and limit the use of extra FIFOs for bulk
> This should be split into 2 changes: 1 for adding support for
> single-port RAM, and the other for budgeting the bulk fifo setting.
>
> The first change is not a fix, and the latter may be a fix (may need
> more feedback from others).
Hi Thinh,
Thanks for reviewing.
Sure i will do split into 2 changes.
>> transfers in non-SS mode. It prevents the issue of limited RAM size
>> usage.
>>
>> Fixes: fad16c823e66 ("usb: dwc3: gadget: Refine the logic for resizing Tx FIFOs")
>> Cc: stable@xxxxxxxxxxxxxxx # 6.12.x: fad16c82: usb: dwc3: gadget: Refine the logic for resizing Tx FIFOs
>> Signed-off-by: Selvarasu Ganesan <selvarasu.g@xxxxxxxxxxx>
>> ---
>>   drivers/usb/dwc3/core.h   |  4 +++
>>   drivers/usb/dwc3/gadget.c | 56 ++++++++++++++++++++++++++++++---------
>>   2 files changed, 48 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>> index eaa55c0cf62f..8306b39e5c64 100644
>> --- a/drivers/usb/dwc3/core.h
>> +++ b/drivers/usb/dwc3/core.h
>> @@ -915,6 +915,7 @@ struct dwc3_hwparams {
>>   #define DWC3_MODE(n)		((n) & 0x7)
>>   
>>   /* HWPARAMS1 */
>> +#define DWC3_SPRAM_TYPE(n)	(((n) >> 23) & 1)
>>   #define DWC3_NUM_INT(n)		(((n) & (0x3f << 15)) >> 15)
>>   
>>   /* HWPARAMS3 */
>> @@ -925,6 +926,9 @@ struct dwc3_hwparams {
>>   #define DWC3_NUM_IN_EPS(p)	(((p)->hwparams3 &		\
>>   			(DWC3_NUM_IN_EPS_MASK)) >> 18)
>>   
>> +/* HWPARAMS6 */
>> +#define DWC3_RAM0_DEPTH(n)	(((n) & (0xffff0000)) >> 16)
>> +
>>   /* HWPARAMS7 */
>>   #define DWC3_RAM1_DEPTH(n)	((n) & 0xffff)
>>   
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index 2fed2aa01407..d3e25f7d7cd0 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -687,6 +687,42 @@ static int dwc3_gadget_calc_tx_fifo_size(struct dwc3 *dwc, int mult)
>>   	return fifo_size;
>>   }
>>   
>> +/**
>> + * dwc3_gadget_calc_ram_depth - calculates the ram depth for txfifo
>> + * @dwc: pointer to the DWC3 context
>> + */
>> +static int dwc3_gadget_calc_ram_depth(struct dwc3 *dwc)
>> +{
>> +	int ram_depth;
>> +	int fifo_0_start;
>> +	bool spram_type;
>> +	int tmp;
>> +
>> +	/* Check supporting RAM type by HW */
>> +	spram_type = DWC3_SPRAM_TYPE(dwc->hwparams.hwparams1);
>> +
>> +	/* If a single port RAM is utilized, then allocate TxFIFOs from
>> +	 * RAM0. otherwise, allocate them from RAM1.
>> +	 */
> Please use this comment block style
> /*
>   * xxxx
>   * xxxx
>   */
Sure, will update it in next version.
>> +	ram_depth = spram_type ? DWC3_RAM0_DEPTH(dwc->hwparams.hwparams6) :
>> +			DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
> Don't use spram_type as a boolean. Perhaps define a macro for type value
> 1 and 0 (for single vs 2-port)
Are you expecting something like below?

#define DWC3_SINGLE_PORT_RAM     1
#define DWC3_TW0_PORT_RAM        0

// ...

int ram_depth;
int fifo_0_start;
int spram_type;
int tmp;

/*
* Check supporting RAM type by HW. If a single port RAM
* is utilized, then allocate TxFIFOs from RAM0. otherwise,
* allocate them from RAM1.
*/
spram_type = DWC3_SPRAM_TYPE(dwc->hwparams.hwparams1);

/*
* In a single port RAM configuration, the available RAM is shared
* between the RX and TX FIFOs. This means that the txfifo can begin
* at a non-zero address.
*/

if (spram_type == DWC3_SINGLE_PORT_RAM) {

     ram_depth = DWC3_RAM0_DEPTH(dwc->hwparams.hwparams6);

     /* Check if TXFIFOs start at non-zero addr */
     tmp = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
     fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(tmp);

ram_depth -= (fifo_0_start >> 16);
} else
     ram_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);

return ram_depth;
>> +
>> +
>> +	/* In a single port RAM configuration, the available RAM is shared
>> +	 * between the RX and TX FIFOs. This means that the txfifo can begin
>> +	 * at a non-zero address.
>> +	 */
>> +	if (spram_type) {
> if (spram_type == DWC3_SPRAM_TYPE_SINGLE) {
> 	...
> }
>
>> +		/* Check if TXFIFOs start at non-zero addr */
>> +		tmp = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
>> +		fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(tmp);
>> +
>> +		ram_depth -= (fifo_0_start >> 16);
>> +	}
>> +
>> +	return ram_depth;
>> +}
>> +
>>   /**
>>    * dwc3_gadget_clear_tx_fifos - Clears txfifo allocation
>>    * @dwc: pointer to the DWC3 context
>> @@ -753,7 +789,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
>>   {
>>   	struct dwc3 *dwc = dep->dwc;
>>   	int fifo_0_start;
>> -	int ram1_depth;
>> +	int ram_depth;
>>   	int fifo_size;
>>   	int min_depth;
>>   	int num_in_ep;
>> @@ -773,7 +809,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
>>   	if (dep->flags & DWC3_EP_TXFIFO_RESIZED)
>>   		return 0;
>>   
>> -	ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
>> +	ram_depth = dwc3_gadget_calc_ram_depth(dwc);
>>   
>>   	switch (dwc->gadget->speed) {
>>   	case USB_SPEED_SUPER_PLUS:
>> @@ -792,10 +828,6 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
>>   			break;
>>   		}
>>   		fallthrough;
>> -	case USB_SPEED_FULL:
>> -		if (usb_endpoint_xfer_bulk(dep->endpoint.desc))
>> -			num_fifos = 2;
>> -		break;
> Please take out the fallthrough above if you remove this condition.
will update it in next version.
>
>>   	default:
>>   		break;
>>   	}
>> @@ -809,7 +841,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
>>   
>>   	/* Reserve at least one FIFO for the number of IN EPs */
>>   	min_depth = num_in_ep * (fifo + 1);
>> -	remaining = ram1_depth - min_depth - dwc->last_fifo_depth;
>> +	remaining = ram_depth - min_depth - dwc->last_fifo_depth;
>>   	remaining = max_t(int, 0, remaining);
>>   	/*
>>   	 * We've already reserved 1 FIFO per EP, so check what we can fit in
>> @@ -835,9 +867,9 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
>>   		dwc->last_fifo_depth += DWC31_GTXFIFOSIZ_TXFDEP(fifo_size);
>>   
>>   	/* Check fifo size allocation doesn't exceed available RAM size. */
>> -	if (dwc->last_fifo_depth >= ram1_depth) {
>> +	if (dwc->last_fifo_depth >= ram_depth) {
>>   		dev_err(dwc->dev, "Fifosize(%d) > RAM size(%d) %s depth:%d\n",
>> -			dwc->last_fifo_depth, ram1_depth,
>> +			dwc->last_fifo_depth, ram_depth,
>>   			dep->endpoint.name, fifo_size);
>>   		if (DWC3_IP_IS(DWC3))
>>   			fifo_size = DWC3_GTXFIFOSIZ_TXFDEP(fifo_size);
>> @@ -3090,7 +3122,7 @@ static int dwc3_gadget_check_config(struct usb_gadget *g)
>>   	struct dwc3 *dwc = gadget_to_dwc(g);
>>   	struct usb_ep *ep;
>>   	int fifo_size = 0;
>> -	int ram1_depth;
>> +	int ram_depth;
>>   	int ep_num = 0;
>>   
>>   	if (!dwc->do_fifo_resize)
>> @@ -3113,8 +3145,8 @@ static int dwc3_gadget_check_config(struct usb_gadget *g)
>>   	fifo_size += dwc->max_cfg_eps;
>>   
>>   	/* Check if we can fit a single fifo per endpoint */
>> -	ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
>> -	if (fifo_size > ram1_depth)
>> +	ram_depth = dwc3_gadget_calc_ram_depth(dwc);
>> +	if (fifo_size > ram_depth)
>>   		return -ENOMEM;
>>   
>>   	return 0;
>> -- 
>> 2.17.1
>>
> We may need to think a little more on how to budgeting the resource
> properly to accomodate for different requirements. If there's no single
> formula to satisfy for all platform, perhaps we may need to introduce
> parameters that users can set base on the needs of their application.
Agree. Need to introduce some parameters to control the required fifos 
by user that based their usecase.
Here's a rephrased version of your proposal:

To address the issue of determining the required number of FIFOs for 
different types of transfers, we propose introducing dynamic FIFO 
calculation for all type of EP transfers based on the maximum packet 
size, and remove hard code value for required fifos in driver,  
Additionally, we suggest introducing DT properties(tx-fifo-max-num-iso, 
tx-fifo-max-bulk and tx-fifo-max-intr) for all types of transfers 
(except control EP) to allow users to control the required FIFOs instead 
of relying solely on the tx-fifo-max-num. This approach will provide 
more flexibility and customization options for users based on their 
specific use cases.

Please let me know if you have any comments on the above approach.

Thanks,
Selva
>
> I'd like to Ack on the new change that checks single-port RAM. For the
> budgeting of fifo, let's keep the discussion going a little more.
>
> Thanks,
> Thinh








[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux