linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Felipe Balbi <balbi@kernel.org>
To: Thinh Nguyen <Thinh.Nguyen@synopsys.com>,
	Wesley Cheng <wcheng@codeaurora.org>,
	"gregkh@linuxfoundation.org" <gregkh@linuxfoundation.org>,
	"agross@kernel.org" <agross@kernel.org>,
	"bjorn.andersson@linaro.org" <bjorn.andersson@linaro.org>,
	"robh+dt@kernel.org" <robh+dt@kernel.org>,
	"frowand.list@gmail.com" <frowand.list@gmail.com>
Cc: "linux-usb@vger.kernel.org" <linux-usb@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"linux-arm-msm@vger.kernel.org" <linux-arm-msm@vger.kernel.org>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	"jackp@codeaurora.org" <jackp@codeaurora.org>
Subject: Re: [PATCH v14 3/6] usb: dwc3: Resize TX FIFOs to meet EP bursting requirements
Date: Tue, 13 Jul 2021 11:39:13 +0300	[thread overview]
Message-ID: <87czrmzjym.fsf@kernel.org> (raw)
In-Reply-To: <b65463e9-3a8d-1ee5-3e26-09990aa8ec53@synopsys.com>

[-- Attachment #1: Type: text/plain, Size: 13470 bytes --]


Hi,

Thinh Nguyen <Thinh.Nguyen@synopsys.com> writes:
> Wesley Cheng wrote:
>> Some devices have USB compositions which may require multiple endpoints
>> that support EP bursting.  HW defined TX FIFO sizes may not always be
>> sufficient for these compositions.  By utilizing flexible TX FIFO
>> allocation, this allows for endpoints to request the required FIFO depth to
>> achieve higher bandwidth.  With some higher bMaxBurst configurations, using
>> a larger TX FIFO size results in better TX throughput.
>> 
>> By introducing the check_config() callback, the resizing logic can fetch
>> the maximum number of endpoints used in the USB composition (can contain
>> multiple configurations), which helps ensure that the resizing logic can
>> fulfill the configuration(s), or return an error to the gadget layer
>> otherwise during bind time.
>> 
>> Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
>> ---
>>  drivers/usb/dwc3/core.c   |  15 +++
>>  drivers/usb/dwc3/core.h   |  16 ++++
>>  drivers/usb/dwc3/ep0.c    |   2 +
>>  drivers/usb/dwc3/gadget.c | 232 ++++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 265 insertions(+)
>> 
>> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
>> index ba74ad7..b194aecd 100644
>> --- a/drivers/usb/dwc3/core.c
>> +++ b/drivers/usb/dwc3/core.c
>> @@ -1267,6 +1267,7 @@ static void dwc3_get_properties(struct dwc3 *dwc)
>>  	u8			rx_max_burst_prd;
>>  	u8			tx_thr_num_pkt_prd;
>>  	u8			tx_max_burst_prd;
>> +	u8			tx_fifo_resize_max_num;
>>  	const char		*usb_psy_name;
>>  	int			ret;
>>  
>> @@ -1282,6 +1283,13 @@ static void dwc3_get_properties(struct dwc3 *dwc)
>>  	 */
>>  	hird_threshold = 12;
>>  
>> +	/*
>> +	 * default to a TXFIFO size large enough to fit 6 max packets.  This
>> +	 * allows for systems with larger bus latencies to have some headroom
>> +	 * for endpoints that have a large bMaxBurst value.
>> +	 */
>> +	tx_fifo_resize_max_num = 6;
>> +
>>  	dwc->maximum_speed = usb_get_maximum_speed(dev);
>>  	dwc->max_ssp_rate = usb_get_maximum_ssp_rate(dev);
>>  	dwc->dr_mode = usb_get_dr_mode(dev);
>> @@ -1325,6 +1333,11 @@ static void dwc3_get_properties(struct dwc3 *dwc)
>>  				&tx_thr_num_pkt_prd);
>>  	device_property_read_u8(dev, "snps,tx-max-burst-prd",
>>  				&tx_max_burst_prd);
>> +	dwc->do_fifo_resize = device_property_read_bool(dev,
>> +							"tx-fifo-resize");
>> +	if (dwc->do_fifo_resize)
>> +		device_property_read_u8(dev, "tx-fifo-max-num",
>> +					&tx_fifo_resize_max_num);
>
> Why is this check here? The dwc->tx_fifo_resize_max_num should store
> whatever property the user sets. Whether the driver wants to use this

Ack!

> property should depend on "dwc->do_fifo_resize". Also why don't we have
> "snps," prefix to be consistent with the other properties?

Ack!

> Can we enforce to a single property? If the designer wants to enable
> this feature, he/she can to provide the tx-fifo-max-num. This would
> simplify the driver a bit. Since this is to optimize for performance,
> the user should know/want/test the specific value if they want to set
> for their setup and not hoping that the default setting not break their
> setup. So we can remove the "do_fifo_resize" property and just check
> whether tx_fifo_resize_max_num is set.

Ack!

All very valid points :-)

>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>> index dccdf13..735e9be 100644
>> --- a/drivers/usb/dwc3/core.h
>> +++ b/drivers/usb/dwc3/core.h
>> @@ -1023,6 +1023,7 @@ struct dwc3_scratchpad_array {
>>   * @rx_max_burst_prd: max periodic ESS receive burst size
>>   * @tx_thr_num_pkt_prd: periodic ESS transmit packet count
>>   * @tx_max_burst_prd: max periodic ESS transmit burst size
>> + * @tx_fifo_resize_max_num: max number of fifos allocated during txfifo resize
>>   * @hsphy_interface: "utmi" or "ulpi"
>>   * @connected: true when we're connected to a host, false otherwise
>>   * @delayed_status: true when gadget driver asks for delayed status
>> @@ -1037,6 +1038,7 @@ struct dwc3_scratchpad_array {
>>   *	1	- utmi_l1_suspend_n
>>   * @is_fpga: true when we are using the FPGA board
>>   * @pending_events: true when we have pending IRQs to be handled
>> + * @do_fifo_resize: true when txfifo resizing is enabled for dwc3 endpoints
>>   * @pullups_connected: true when Run/Stop bit is set
>>   * @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
>>   * @three_stage_setup: set if we perform a three phase setup
>> @@ -1079,6 +1081,11 @@ struct dwc3_scratchpad_array {
>>   * @dis_split_quirk: set to disable split boundary.
>>   * @imod_interval: set the interrupt moderation interval in 250ns
>>   *			increments or 0 to disable.
>> + * @max_cfg_eps: current max number of IN eps used across all USB configs.
>> + * @last_fifo_depth: last fifo depth used to determine next fifo ram start
>> + *		     address.
>> + * @num_ep_resized: carries the current number endpoints which have had its tx
>> + *		    fifo resized.
>>   */
>>  struct dwc3 {
>>  	struct work_struct	drd_work;
>> @@ -1233,6 +1240,7 @@ struct dwc3 {
>>  	u8			rx_max_burst_prd;
>>  	u8			tx_thr_num_pkt_prd;
>>  	u8			tx_max_burst_prd;
>> +	u8			tx_fifo_resize_max_num;
>>  
>>  	const char		*hsphy_interface;
>>  
>> @@ -1246,6 +1254,7 @@ struct dwc3 {
>>  	unsigned		is_utmi_l1_suspend:1;
>>  	unsigned		is_fpga:1;
>>  	unsigned		pending_events:1;
>> +	unsigned		do_fifo_resize:1;
>>  	unsigned		pullups_connected:1;
>>  	unsigned		setup_packet_pending:1;
>>  	unsigned		three_stage_setup:1;
>> @@ -1281,6 +1290,10 @@ struct dwc3 {
>>  	unsigned		dis_split_quirk:1;
>>  
>>  	u16			imod_interval;
>> +
>> +	int			max_cfg_eps;
>> +	int			last_fifo_depth;
>> +	int			num_ep_resized;
>>  };
>>  
>>  #define INCRX_BURST_MODE 0
>> @@ -1512,6 +1525,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
>>  		struct dwc3_gadget_ep_cmd_params *params);
>>  int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd,
>>  		u32 param);
>> +void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc);
>>  #else
>>  static inline int dwc3_gadget_init(struct dwc3 *dwc)
>>  { return 0; }
>> @@ -1531,6 +1545,8 @@ static inline int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
>>  static inline int dwc3_send_gadget_generic_command(struct dwc3 *dwc,
>>  		int cmd, u32 param)
>>  { return 0; }
>> +static inline void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc)
>> +{ }
>>  #endif
>>  
>>  #if IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
>> diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
>> index 3cd2942..d28d085 100644
>> --- a/drivers/usb/dwc3/ep0.c
>> +++ b/drivers/usb/dwc3/ep0.c
>> @@ -619,6 +619,8 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
>>  		return -EINVAL;
>>  
>>  	case USB_STATE_ADDRESS:
>> +		dwc3_gadget_clear_tx_fifos(dwc);
>> +
>>  		ret = dwc3_ep0_delegate_req(dwc, ctrl);
>>  		/* if the cfg matches and the cfg is non zero */
>>  		if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
>> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
>> index af6d7f1..e56f1a6 100644
>> --- a/drivers/usb/dwc3/gadget.c
>> +++ b/drivers/usb/dwc3/gadget.c
>> @@ -632,6 +632,187 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
>>  		bool interrupt);
>>  
>>  /**
>> + * dwc3_gadget_calc_tx_fifo_size - calculates the txfifo size value
>> + * @dwc: pointer to the DWC3 context
>> + * @nfifos: number of fifos to calculate for
>> + *
>> + * Calculates the size value based on the equation below:
>> + *
>> + * DWC3 revision 280A and prior:
>> + * fifo_size = mult * (max_packet / mdwidth) + 1;
>> + *
>> + * DWC3 revision 290A and onwards:
>> + * fifo_size = mult * ((max_packet + mdwidth)/mdwidth + 1) + 1
>> + *
>> + * The max packet size is set to 1024, as the txfifo requirements mainly apply
>> + * to super speed USB use cases.  However, it is safe to overestimate the fifo
>> + * allocations for other scenarios, i.e. high speed USB.
>> + */
>> +static int dwc3_gadget_calc_tx_fifo_size(struct dwc3 *dwc, int mult)
>> +{
>> +	int max_packet = 1024;
>> +	int fifo_size;
>> +	int mdwidth;
>> +
>> +	mdwidth = dwc3_mdwidth(dwc);
>> +
>> +	/* MDWIDTH is represented in bits, we need it in bytes */
>> +	mdwidth >>= 3;
>> +
>> +	if (DWC3_VER_IS_PRIOR(DWC3, 290A))
>> +		fifo_size = mult * (max_packet / mdwidth) + 1;
>> +	else
>> +		fifo_size = mult * ((max_packet + mdwidth) / mdwidth) + 1;
>> +	return fifo_size;
>> +}
>> +
>> +/**
>> + * dwc3_gadget_clear_tx_fifo_size - Clears txfifo allocation
>> + * @dwc: pointer to the DWC3 context
>> + *
>> + * Iterates through all the endpoint registers and clears the previous txfifo
>> + * allocations.
>> + */
>> +void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc)
>> +{
>> +	struct dwc3_ep *dep;
>> +	int fifo_depth;
>> +	int size;
>> +	int num;
>> +
>> +	if (!dwc->do_fifo_resize)
>> +		return;
>> +
>> +	/* Read ep0IN related TXFIFO size */
>> +	dep = dwc->eps[1];
>> +	size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
>> +	if (DWC3_IP_IS(DWC3))
>> +		fifo_depth = DWC3_GTXFIFOSIZ_TXFDEP(size);
>> +	else
>> +		fifo_depth = DWC31_GTXFIFOSIZ_TXFDEP(size);
>> +
>> +	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) {
>> +		dep = dwc->eps[num];
>> +		/* Don't change TXFRAMNUM on usb31 version */
>> +		size = DWC3_IP_IS(DWC3) ? 0 :
>> +			dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1)) &
>> +				   DWC31_GTXFIFOSIZ_TXFRAMNUM;
>> +
>> +		dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1), size);
>> +	}
>> +	dwc->num_ep_resized = 0;
>> +}
>> +
>> +/*
>> + * dwc3_gadget_resize_tx_fifos - reallocate fifo spaces for current use-case
>> + * @dwc: pointer to our context structure
>> + *
>> + * This function will a best effort FIFO allocation in order
>> + * to improve FIFO usage and throughput, while still allowing
>> + * us to enable as many endpoints as possible.
>> + *
>> + * Keep in mind that this operation will be highly dependent
>> + * on the configured size for RAM1 - which contains TxFifo -,
>> + * the amount of endpoints enabled on coreConsultant tool, and
>> + * the width of the Master Bus.
>> + *
>> + * In general, FIFO depths are represented with the following equation:
>> + *
>> + * fifo_size = mult * ((max_packet + mdwidth)/mdwidth + 1) + 1
>> + *
>> + * In conjunction with dwc3_gadget_check_config(), this resizing logic will
>> + * ensure that all endpoints will have enough internal memory for one max
>> + * packet per endpoint.
>> + */
>> +static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
>> +{
>> +	struct dwc3 *dwc = dep->dwc;
>> +	int fifo_0_start;
>> +	int ram1_depth;
>> +	int fifo_size;
>> +	int min_depth;
>> +	int num_in_ep;
>> +	int remaining;
>> +	int num_fifos = 1;
>> +	int fifo;
>> +	int tmp;
>> +
>> +	if (!dwc->do_fifo_resize)
>> +		return 0;
>> +
>> +	/* resize IN endpoints except ep0 */
>> +	if (!usb_endpoint_dir_in(dep->endpoint.desc) || dep->number <= 1)
>> +		return 0;
>
>> +
>> +	ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
>> +
>> +	if ((dep->endpoint.maxburst > 1 &&
>> +	     usb_endpoint_xfer_bulk(dep->endpoint.desc)) ||
>> +	    usb_endpoint_xfer_isoc(dep->endpoint.desc))
>> +		num_fifos = 3;
>> +
>> +	if (dep->endpoint.maxburst > 6 &&
>> +	    usb_endpoint_xfer_bulk(dep->endpoint.desc) && DWC3_IP_IS(DWC31))
>> +		num_fifos = dwc->tx_fifo_resize_max_num;
>
> Why only bulk? Isoc should be at least equal or more than bulk.
> Also, make this applicable to DWC_usb32 also.

this should be applicable to all DWC3 versions, no? dwc3, 31 and 32.

>> @@ -648,6 +829,10 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
>>  	int			ret;
>>  
>>  	if (!(dep->flags & DWC3_EP_ENABLED)) {
>> +		ret = dwc3_gadget_resize_tx_fifos(dep);
>> +		if (ret)
>> +			return ret;
>> +
>>  		ret = dwc3_gadget_start_config(dep);
>>  		if (ret)
>>  			return ret;
>> @@ -2498,6 +2683,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
>>  
>>  	spin_lock_irqsave(&dwc->lock, flags);
>>  	dwc->gadget_driver	= NULL;
>> +	dwc->max_cfg_eps = 0;
>>  	spin_unlock_irqrestore(&dwc->lock, flags);
>>  
>>  	free_irq(dwc->irq_gadget, dwc->ev_buf);
>> @@ -2585,6 +2771,51 @@ static int dwc3_gadget_vbus_draw(struct usb_gadget *g, unsigned int mA)
>>  	return ret;
>>  }
>>  
>> +/**
>> + * dwc3_gadget_check_config - ensure dwc3 can support the USB configuration
>> + * @g: pointer to the USB gadget
>> + *
>> + * Used to record the maximum number of endpoints being used in a USB composite
>> + * device. (across all configurations)  This is to be used in the calculation
>> + * of the TXFIFO sizes when resizing internal memory for individual endpoints.
>> + * It will help ensured that the resizing logic reserves enough space for at
>> + * least one max packet.
>> + */
>> +static int dwc3_gadget_check_config(struct usb_gadget *g)

Might be better to pass the actual config being used. And, instead of
check_config, perhaps validate_config is a little more fitting.

-- 
balbi

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 511 bytes --]

  reply	other threads:[~2021-07-13  8:39 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-10  9:13 [PATCH v14 0/6] Re-introduce TX FIFO resize for larger EP bursting Wesley Cheng
2021-07-10  9:13 ` [PATCH v14 1/6] usb: gadget: udc: core: Introduce check_config to verify USB configuration Wesley Cheng
2021-07-10  9:13 ` [PATCH v14 2/6] usb: gadget: configfs: Check USB configuration before adding Wesley Cheng
2021-07-10  9:13 ` [PATCH v14 3/6] usb: dwc3: Resize TX FIFOs to meet EP bursting requirements Wesley Cheng
2021-07-12 23:38   ` Thinh Nguyen
2021-07-13  8:39     ` Felipe Balbi [this message]
2021-07-14  2:58       ` Thinh Nguyen
2021-07-14  3:10       ` Thinh Nguyen
2021-07-14  6:40         ` Felipe Balbi
2021-07-14  6:52           ` gregkh
2021-07-14  7:30           ` Wesley Cheng
2021-07-20 11:41             ` gregkh
2021-07-21  6:23               ` Wesley Cheng
2021-07-14  6:51         ` gregkh
2021-07-14  2:59     ` Thinh Nguyen
2021-07-10  9:13 ` [PATCH v14 4/6] of: Add stub for of_add_property() Wesley Cheng
2021-07-10  9:13 ` [PATCH v14 5/6] usb: dwc3: dwc3-qcom: Enable tx-fifo-resize property by default Wesley Cheng
2021-07-10  9:13 ` [PATCH v14 6/6] dt-bindings: usb: dwc3: Update dwc3 TX fifo properties Wesley Cheng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87czrmzjym.fsf@kernel.org \
    --to=balbi@kernel.org \
    --cc=Thinh.Nguyen@synopsys.com \
    --cc=agross@kernel.org \
    --cc=bjorn.andersson@linaro.org \
    --cc=devicetree@vger.kernel.org \
    --cc=frowand.list@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jackp@codeaurora.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=robh+dt@kernel.org \
    --cc=wcheng@codeaurora.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).