요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
===============================================================
Synopsys DesignWare Core SuperSpeed USB 3.0 Controller
===============================================================
:Author: Felipe Balbi <felipe.balbi@linux.intel.com>
:Date: April 2017
Introduction
============
The *Synopsys DesignWare Core SuperSpeed USB 3.0 Controller*
(hereinafter referred to as *DWC3*) is a USB SuperSpeed compliant
controller which can be configured in one of 4 ways:
1. Peripheral-only configuration
2. Host-only configuration
3. Dual-Role configuration
4. Hub configuration
Linux currently supports several versions of this controller. In all
likelihood, the version in your SoC is already supported. At the time
of this writing, known tested versions range from 2.02a to 3.10a. As a
rule of thumb, anything above 2.02a should work reliably well.
Currently, we have many known users for this driver. In alphabetical
order:
1. Cavium
2. Intel Corporation
3. Qualcomm
4. Rockchip
5. ST
6. Samsung
7. Texas Instruments
8. Xilinx
Summary of Features
======================
For details about features supported by your version of DWC3, consult
your IP team and/or *Synopsys DesignWare Core SuperSpeed USB 3.0
Controller Databook*. Following is a list of features supported by the
driver at the time of this writing:
1. Up to 16 bidirectional endpoints (including the control
pipe - ep0)
2. Flexible endpoint configuration
3. Simultaneous IN and OUT transfer support
4. Scatter-list support
5. Up to 256 TRBs [#trb]_ per endpoint
6. Support for all transfer types (*Control*, *Bulk*,
*Interrupt*, and *Isochronous*)
7. SuperSpeed Bulk Streams
8. Link Power Management
9. Trace Events for debugging
10. DebugFS [#debugfs]_ interface
These features have all been exercised with many of the **in-tree**
gadget drivers. We have verified both *ConfigFS* [#configfs]_ and
legacy gadget drivers.
Driver Design
==============
The DWC3 driver sits on the *drivers/usb/dwc3/* directory. All files
related to this driver are in this one directory. This makes it easy
for new-comers to read the code and understand how it behaves.
Because of DWC3's configuration flexibility, the driver is a little
complex in some places but it should be rather straightforward to
understand.
The biggest part of the driver refers to the Gadget API.
Known Limitations
===================
Like any other HW, DWC3 has its own set of limitations. To avoid
constant questions about such problems, we decided to document them
here and have a single location to where we could point users.
OUT Transfer Size Requirements
---------------------------------
According to Synopsys Databook, all OUT transfer TRBs [#trb]_ must
have their *size* field set to a value which is integer divisible by
the endpoint's *wMaxPacketSize*. This means that *e.g.* in order to
receive a Mass Storage *CBW* [#cbw]_, req->length must either be set
to a value that's divisible by *wMaxPacketSize* (1024 on SuperSpeed,
512 on HighSpeed, etc), or DWC3 driver must add a Chained TRB pointing
to a throw-away buffer for the remaining length. Without this, OUT
transfers will **NOT** start.
Note that as of this writing, this won't be a problem because DWC3 is
fully capable of appending a chained TRB for the remaining length and
completely hide this detail from the gadget driver. It's still worth
mentioning because this seems to be the largest source of queries
about DWC3 and *non-working transfers*.
TRB Ring Size Limitation
-------------------------
We, currently, have a hard limit of 256 TRBs [#trb]_ per endpoint,
with the last TRB being a Link TRB [#link_trb]_ pointing back to the
first. This limit is arbitrary but it has the benefit of adding up to
exactly 4096 bytes, or 1 Page.
DWC3 driver will try its best to cope with more than 255 requests and,
for the most part, it should work normally. However this is not
something that has been exercised very frequently. If you experience
any problems, see section **Reporting Bugs** below.
Reporting Bugs
================
Whenever you encounter a problem with DWC3, first and foremost you
should make sure that:
1. You're running latest tag from `Linus' tree`_
2. You can reproduce the error without any out-of-tree changes
to DWC3
3. You have checked that it's not a fault on the host machine
After all these are verified, then here's how to capture enough
information so we can be of any help to you.
Required Information
---------------------
DWC3 relies exclusively on Trace Events for debugging. Everything is
exposed there, with some extra bits being exposed to DebugFS
[#debugfs]_.
In order to capture DWC3's Trace Events you should run the following
commands **before** plugging the USB cable to a host machine:
.. code-block:: sh
# mkdir -p /d
# mkdir -p /t
# mount -t debugfs none /d
# mount -t tracefs none /t
# echo 81920 > /t/buffer_size_kb
# echo 1 > /t/events/dwc3/enable
After this is done, you can connect your USB cable and reproduce the
problem. As soon as the fault is reproduced, make a copy of files
``trace`` and ``regdump``, like so:
.. code-block:: sh
# cp /t/trace /root/trace.txt
# cat /d/*dwc3*/regdump > /root/regdump.txt
Make sure to compress ``trace.txt`` and ``regdump.txt`` in a tarball
and email it to `me`_ with `linux-usb`_ in Cc. If you want to be extra
sure that I'll help you, write your subject line in the following
format:
**[BUG REPORT] usb: dwc3: Bug while doing XYZ**
On the email body, make sure to detail what you doing, which gadget
driver you were using, how to reproduce the problem, what SoC you're
using, which OS (and its version) was running on the Host machine.
With all this information, we should be able to understand what's
going on and be helpful to you.
Debugging
===========
First and foremost a disclaimer::
DISCLAIMER: The information available on DebugFS and/or TraceFS can
change at any time at any Major Linux Kernel Release. If writing
scripts, do **NOT** assume information to be available in the
current format.
With that out of the way, let's carry on.
If you're willing to debug your own problem, you deserve a round of
applause :-)
Anyway, there isn't much to say here other than Trace Events will be
really helpful in figuring out issues with DWC3. Also, access to
Synopsys Databook will be **really** valuable in this case.
A USB Sniffer can be helpful at times but it's not entirely required,
there's a lot that can be understood without looking at the wire.
Feel free to email `me`_ and Cc `linux-usb`_ if you need any help.
``DebugFS``
-------------
``DebugFS`` is very good for gathering snapshots of what's going on
with DWC3 and/or any endpoint.
On DWC3's ``DebugFS`` directory, you will find the following files and
directories:
``ep[0..15]{in,out}/``
``link_state``
``regdump``
``testmode``
``link_state``
``````````````
When read, ``link_state`` will print out one of ``U0``, ``U1``,
``U2``, ``U3``, ``SS.Disabled``, ``RX.Detect``, ``SS.Inactive``,
``Polling``, ``Recovery``, ``Hot Reset``, ``Compliance``,
``Loopback``, ``Reset``, ``Resume`` or ``UNKNOWN link state``.
This file can also be written to in order to force link to one of the
states above.
``regdump``
`````````````
File name is self-explanatory. When read, ``regdump`` will print out a
register dump of DWC3. Note that this file can be grepped to find the
information you want.
``testmode``
``````````````
When read, ``testmode`` will print out a name of one of the specified
USB 2.0 Testmodes (``test_j``, ``test_k``, ``test_se0_nak``,
``test_packet``, ``test_force_enable``) or the string ``no test`` in
case no tests are currently being executed.
In order to start any of these test modes, the same strings can be
written to the file and DWC3 will enter the requested test mode.
``ep[0..15]{in,out}``
``````````````````````
For each endpoint we expose one directory following the naming
convention ``ep$num$dir`` *(ep0in, ep0out, ep1in, ...)*. Inside each
of these directories you will find the following files:
``descriptor_fetch_queue``
``event_queue``
``rx_fifo_queue``
``rx_info_queue``
``rx_request_queue``
``transfer_type``
``trb_ring``
``tx_fifo_queue``
``tx_request_queue``
With access to Synopsys Databook, you can decode the information on
them.
``transfer_type``
~~~~~~~~~~~~~~~~~~
When read, ``transfer_type`` will print out one of ``control``,
``bulk``, ``interrupt`` or ``isochronous`` depending on what the
endpoint descriptor says. If the endpoint hasn't been enabled yet, it
will print ``--``.
``trb_ring``
~~~~~~~~~~~~~
When read, ``trb_ring`` will print out details about all TRBs on the
ring. It will also tell you where our enqueue and dequeue pointers are
located in the ring:
.. code-block:: sh
buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo
000000002c754000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c75c000,512,normal,1,0,1,0,0,1 D
0000000000000000,0,UNKNOWN,0,0,0,0,0,0 E
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
00000000381ab000,0,link,0,0,0,0,0,1
Trace Events
-------------
DWC3 also provides several trace events which help us gathering
information about the behavior of the driver during runtime.
In order to use these events, you must enable ``CONFIG_FTRACE`` in
your kernel config.
For details about how enable DWC3 events, see section **Reporting
Bugs**.
The following subsections will give details about each Event Class and
each Event defined by DWC3.
MMIO
```````
It is sometimes useful to look at every MMIO access when looking for
bugs. Because of that, DWC3 offers two Trace Events (one for
dwc3_readl() and one for dwc3_writel()). ``TP_printk`` follows::
TP_printk("addr %p value %08x", __entry->base + __entry->offset,
__entry->value)
Interrupt Events
````````````````
Every IRQ event can be logged and decoded into a human readable
string. Because every event will be different, we don't give an
example other than the ``TP_printk`` format used::
TP_printk("event (%08x): %s", __entry->event,
dwc3_decode_event(__entry->event, __entry->ep0state))
Control Request
`````````````````
Every USB Control Request can be logged to the trace buffer. The
output format is::
TP_printk("%s", dwc3_decode_ctrl(__entry->bRequestType,
__entry->bRequest, __entry->wValue,
__entry->wIndex, __entry->wLength)
)
Note that Standard Control Requests will be decoded into
human-readable strings with their respective arguments. Class and
Vendor requests will be printed out a sequence of 8 bytes in hex
format.
Lifetime of a ``struct usb_request``
```````````````````````````````````````
The entire lifetime of a ``struct usb_request`` can be tracked on the
trace buffer. We have one event for each of allocation, free,
queueing, dequeueing, and giveback. Output format is::
TP_printk("%s: req %p length %u/%u %s%s%s ==> %d",
__get_str(name), __entry->req, __entry->actual, __entry->length,
__entry->zero ? "Z" : "z",
__entry->short_not_ok ? "S" : "s",
__entry->no_interrupt ? "i" : "I",
__entry->status
)
Generic Commands
````````````````````
We can log and decode every Generic Command with its completion
code. Format is::
TP_printk("cmd '%s' [%x] param %08x --> status: %s",
dwc3_gadget_generic_cmd_string(__entry->cmd),
__entry->cmd, __entry->param,
dwc3_gadget_generic_cmd_status_string(__entry->status)
)
Endpoint Commands
````````````````````
Endpoints commands can also be logged together with completion
code. Format is::
TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x --> status: %s",
__get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd),
__entry->cmd, __entry->param0,
__entry->param1, __entry->param2,
dwc3_ep_cmd_status_string(__entry->cmd_status)
)
Lifetime of a ``TRB``
``````````````````````
A ``TRB`` Lifetime is simple. We are either preparing a ``TRB`` or
completing it. With these two events, we can see how a ``TRB`` changes
over time. Format is::
TP_printk("%s: %d/%d trb %p buf %08x%08x size %s%d ctrl %08x (%c%c%c%c:%c%c:%s)",
__get_str(name), __entry->queued, __entry->allocated,
__entry->trb, __entry->bph, __entry->bpl,
({char *s;
int pcm = ((__entry->size >> 24) & 3) + 1;
switch (__entry->type) {
case USB_ENDPOINT_XFER_INT:
case USB_ENDPOINT_XFER_ISOC:
switch (pcm) {
case 1:
s = "1x ";
break;
case 2:
s = "2x ";
break;
case 3:
s = "3x ";
break;
}
default:
s = "";
} s; }),
DWC3_TRB_SIZE_LENGTH(__entry->size), __entry->ctrl,
__entry->ctrl & DWC3_TRB_CTRL_HWO ? 'H' : 'h',
__entry->ctrl & DWC3_TRB_CTRL_LST ? 'L' : 'l',
__entry->ctrl & DWC3_TRB_CTRL_CHN ? 'C' : 'c',
__entry->ctrl & DWC3_TRB_CTRL_CSP ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_ISP_IMI ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_IOC ? 'C' : 'c',
dwc3_trb_type_string(DWC3_TRBCTL_TYPE(__entry->ctrl))
)
Lifetime of an Endpoint
```````````````````````
And endpoint's lifetime is summarized with enable and disable
operations, both of which can be traced. Format is::
TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c%c:%c:%c",
__get_str(name), __entry->maxpacket,
__entry->maxpacket_limit, __entry->max_streams,
__entry->maxburst, __entry->trb_enqueue,
__entry->trb_dequeue,
__entry->flags & DWC3_EP_ENABLED ? 'E' : 'e',
__entry->flags & DWC3_EP_STALL ? 'S' : 's',
__entry->flags & DWC3_EP_WEDGE ? 'W' : 'w',
__entry->flags & DWC3_EP_TRANSFER_STARTED ? 'B' : 'b',
__entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p',
__entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e',
__entry->direction ? '<' : '>'
)
Structures, Methods and Definitions
====================================
.. kernel-doc:: drivers/usb/dwc3/core.h
:doc: main data structures
:internal:
.. kernel-doc:: drivers/usb/dwc3/gadget.h
:doc: gadget-only helpers
:internal:
.. kernel-doc:: drivers/usb/dwc3/gadget.c
:doc: gadget-side implementation
:internal:
.. kernel-doc:: drivers/usb/dwc3/core.c
:doc: core driver (probe, PM, etc)
:internal:
.. [#trb] Transfer Request Block
.. [#link_trb] Transfer Request Block pointing to another Transfer
Request Block.
.. [#debugfs] The Debug File System
.. [#configfs] The Config File System
.. [#cbw] Command Block Wrapper
.. _Linus' tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
.. _me: felipe.balbi@linux.intel.com
.. _linux-usb: linux-usb@vger.kernel.org
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
DWC3 소개, 기능, 드라이버 설계
1-74*Synopsys DesignWare Core SuperSpeed USB 3.0 Controller*(이하 *DWC3*)는 USB SuperSpeed 규격을 따르는 컨트롤러이며 peripheral 전용, host 전용, dual-role, hub의 네 가지 형태로 구성할 수 있습니다.
Linux는 이 컨트롤러의 여러 버전을 지원합니다. 작성 당시 검증된 범위는 2.02a부터 3.10a까지이며, 일반적으로 2.02a보다 새 버전은 안정적으로 동작할 것으로 기대됩니다. 알려진 사용자는 Cavium, Intel Corporation, Qualcomm, Rockchip, ST, Samsung, Texas Instruments, Xilinx입니다.
개별 DWC3 버전이 제공하는 기능은 IP 팀 또는 *Synopsys DesignWare Core SuperSpeed USB 3.0 Controller Databook*에서 확인해야 합니다. 드라이버는 제어 파이프 `ep0`을 포함한 최대 16개 양방향 endpoint, 유연한 endpoint 구성, 동시 IN/OUT 전송, scatter-list, endpoint당 최대 256개 TRB, 모든 전송 유형, SuperSpeed Bulk Streams, Link Power Management, Trace Events, DebugFS를 지원합니다.
이 기능들은 여러 in-tree gadget driver에서 검증되었으며 *ConfigFS*와 기존 gadget driver 모두 시험되었습니다.
DWC3 드라이버 관련 파일은 모두 `drivers/usb/dwc3/`에 모여 있습니다. 구성 유연성 때문에 일부는 복잡하지만 전체 흐름은 비교적 직접적이며, 가장 큰 부분은 Gadget API 구현입니다.
===============================================================
Synopsys DesignWare Core SuperSpeed USB 3.0 Controller
===============================================================
:Author: Felipe Balbi <felipe.balbi@linux.intel.com>
:Date: April 2017
Introduction
============
The *Synopsys DesignWare Core SuperSpeed USB 3.0 Controller*
(hereinafter referred to as *DWC3*) is a USB SuperSpeed compliant
controller which can be configured in one of 4 ways:
1. Peripheral-only configuration
2. Host-only configuration
3. Dual-Role configuration
4. Hub configuration
Linux currently supports several versions of this controller. In all
likelihood, the version in your SoC is already supported. At the time
of this writing, known tested versions range from 2.02a to 3.10a. As a
rule of thumb, anything above 2.02a should work reliably well.
Currently, we have many known users for this driver. In alphabetical
order:
1. Cavium
2. Intel Corporation
3. Qualcomm
4. Rockchip
5. ST
6. Samsung
7. Texas Instruments
8. Xilinx
Summary of Features
======================
For details about features supported by your version of DWC3, consult
your IP team and/or *Synopsys DesignWare Core SuperSpeed USB 3.0
Controller Databook*. Following is a list of features supported by the
driver at the time of this writing:
1. Up to 16 bidirectional endpoints (including the control
pipe - ep0)
2. Flexible endpoint configuration
3. Simultaneous IN and OUT transfer support
4. Scatter-list support
5. Up to 256 TRBs [#trb]_ per endpoint
6. Support for all transfer types (*Control*, *Bulk*,
*Interrupt*, and *Isochronous*)
7. SuperSpeed Bulk Streams
8. Link Power Management
9. Trace Events for debugging
10. DebugFS [#debugfs]_ interface
These features have all been exercised with many of the **in-tree**
gadget drivers. We have verified both *ConfigFS* [#configfs]_ and
legacy gadget drivers.
Driver Design
==============
The DWC3 driver sits on the *drivers/usb/dwc3/* directory. All files
related to this driver are in this one directory. This makes it easy
for new-comers to read the code and understand how it behaves.
Because of DWC3's configuration flexibility, the driver is a little
complex in some places but it should be rather straightforward to
understand.
The biggest part of the driver refers to the Gadget API.
알려진 제한 사항
75-112DWC3에도 하드웨어 고유의 제한이 있으며, 반복되는 문제를 한곳에서 설명하기 위해 이 절에 정리합니다.
Synopsys Databook에 따르면 모든 OUT 전송 TRB의 `size` 필드는 endpoint의 `wMaxPacketSize`로 나누어떨어져야 합니다. 예를 들어 Mass Storage `CBW`를 받으려면 `req->length`를 `wMaxPacketSize`의 배수로 설정하거나, 남는 길이를 버릴 buffer를 가리키는 chained TRB를 DWC3 드라이버가 추가해야 합니다. 그렇지 않으면 OUT 전송은 시작되지 않습니다.
현재 드라이버는 남은 길이에 대한 chained TRB를 자동으로 붙여 이 세부 사항을 gadget driver에서 숨길 수 있습니다. 다만 DWC3에서 전송이 동작하지 않는다는 문의의 가장 흔한 원인이므로 이 제약을 알아둘 필요가 있습니다.
endpoint마다 TRB는 256개로 제한되며 마지막 항목은 첫 항목을 가리키는 Link TRB입니다. 이 값은 임의로 정한 제한이지만 전체가 정확히 4096바이트, 즉 한 페이지가 되는 장점이 있습니다.
드라이버는 255개를 넘는 request도 가능한 한 처리하며 대개 정상 동작합니다. 그러나 충분히 자주 검증된 경로는 아니므로 문제가 생기면 아래의 **Reporting Bugs** 절을 따라야 합니다.
OUT TRB 크기가 packet 경계에 맞지 않을 때 드라이버가 보완하는 흐름입니다.
Known Limitations
===================
Like any other HW, DWC3 has its own set of limitations. To avoid
constant questions about such problems, we decided to document them
here and have a single location to where we could point users.
OUT Transfer Size Requirements
---------------------------------
According to Synopsys Databook, all OUT transfer TRBs [#trb]_ must
have their *size* field set to a value which is integer divisible by
the endpoint's *wMaxPacketSize*. This means that *e.g.* in order to
receive a Mass Storage *CBW* [#cbw]_, req->length must either be set
to a value that's divisible by *wMaxPacketSize* (1024 on SuperSpeed,
512 on HighSpeed, etc), or DWC3 driver must add a Chained TRB pointing
to a throw-away buffer for the remaining length. Without this, OUT
transfers will **NOT** start.
Note that as of this writing, this won't be a problem because DWC3 is
fully capable of appending a chained TRB for the remaining length and
completely hide this detail from the gadget driver. It's still worth
mentioning because this seems to be the largest source of queries
about DWC3 and *non-working transfers*.
TRB Ring Size Limitation
-------------------------
We, currently, have a hard limit of 256 TRBs [#trb]_ per endpoint,
with the last TRB being a Link TRB [#link_trb]_ pointing back to the
first. This limit is arbitrary but it has the benefit of adding up to
exactly 4096 bytes, or 1 Page.
DWC3 driver will try its best to cope with more than 255 requests and,
for the most part, it should work normally. However this is not
something that has been exercised very frequently. If you experience
any problems, see section **Reporting Bugs** below.
버그 보고에 필요한 정보
113-168DWC3 문제를 보고하기 전에 `Linus' tree`의 최신 tag를 사용 중인지, DWC3에 대한 out-of-tree 변경 없이 재현되는지, host machine의 결함이 아닌지 먼저 확인합니다.
DWC3 디버깅은 Trace Events에 전적으로 의존하며 일부 추가 정보는 DebugFS에 노출됩니다. USB cable을 host에 연결하기 전에 debugfs와 tracefs를 mount하고 trace buffer를 81920 KiB로 설정한 뒤 DWC3 event를 활성화합니다.
문제를 재현한 직후 `/t/trace`를 `/root/trace.txt`로 복사하고 각 DWC3 DebugFS 디렉터리의 `regdump`를 `/root/regdump.txt`에 모읍니다. 두 파일을 tarball로 압축하여 저자에게 보내고 `linux-usb`를 Cc에 넣습니다.
메일 제목은 **[BUG REPORT] usb: dwc3: Bug while doing XYZ** 형식을 사용합니다. 본문에는 수행한 작업, 사용한 gadget driver, 재현 절차, SoC, host에서 실행한 OS와 버전을 자세히 적어야 합니다.
Reporting Bugs
================
Whenever you encounter a problem with DWC3, first and foremost you
should make sure that:
1. You're running latest tag from `Linus' tree`_
2. You can reproduce the error without any out-of-tree changes
to DWC3
3. You have checked that it's not a fault on the host machine
After all these are verified, then here's how to capture enough
information so we can be of any help to you.
Required Information
---------------------
DWC3 relies exclusively on Trace Events for debugging. Everything is
exposed there, with some extra bits being exposed to DebugFS
[#debugfs]_.
In order to capture DWC3's Trace Events you should run the following
commands **before** plugging the USB cable to a host machine:
.. code-block:: sh
# mkdir -p /d
# mkdir -p /t
# mount -t debugfs none /d
# mount -t tracefs none /t
# echo 81920 > /t/buffer_size_kb
# echo 1 > /t/events/dwc3/enable
After this is done, you can connect your USB cable and reproduce the
problem. As soon as the fault is reproduced, make a copy of files
``trace`` and ``regdump``, like so:
.. code-block:: sh
# cp /t/trace /root/trace.txt
# cat /d/*dwc3*/regdump > /root/regdump.txt
Make sure to compress ``trace.txt`` and ``regdump.txt`` in a tarball
and email it to `me`_ with `linux-usb`_ in Cc. If you want to be extra
sure that I'll help you, write your subject line in the following
format:
**[BUG REPORT] usb: dwc3: Bug while doing XYZ**
On the email body, make sure to detail what you doing, which gadget
driver you were using, how to reproduce the problem, what SoC you're
using, which OS (and its version) was running on the Host machine.
With all this information, we should be able to understand what's
going on and be helpful to you.
디버깅과 DebugFS 최상위 파일
169-236DebugFS와 TraceFS에 보이는 정보는 Linux kernel의 major release에서 언제든 바뀔 수 있습니다. 스크립트를 작성할 때 현재 형식이 유지된다고 가정해서는 안 됩니다.
DWC3 문제 분석에는 Trace Events가 특히 유용하고 Synopsys Databook 접근 권한도 큰 도움이 됩니다. USB sniffer가 유용할 때도 있지만 필수는 아니며 wire를 직접 보지 않고도 많은 상태를 이해할 수 있습니다.
DWC3의 DebugFS 디렉터리에는 endpoint별 `ep[0..15]{in,out}/` 디렉터리와 `link_state`, `regdump`, `testmode` 파일이 있습니다.
`link_state`를 읽으면 `U0`, `U1`, `U2`, `U3`, `SS.Disabled`, `RX.Detect`, `SS.Inactive`, `Polling`, `Recovery`, `Hot Reset`, `Compliance`, `Loopback`, `Reset`, `Resume` 또는 `UNKNOWN link state`가 출력됩니다. 같은 상태 이름을 써서 link를 해당 상태로 강제할 수도 있습니다.
`regdump`는 DWC3 register dump를 출력하며 필요한 정보를 grep으로 찾을 수 있습니다. `testmode`는 현재 USB 2.0 test mode 이름 또는 `no test`를 출력합니다. `test_j`, `test_k`, `test_se0_nak`, `test_packet`, `test_force_enable` 중 하나를 파일에 쓰면 해당 test mode를 시작합니다.
Debugging
===========
First and foremost a disclaimer::
DISCLAIMER: The information available on DebugFS and/or TraceFS can
change at any time at any Major Linux Kernel Release. If writing
scripts, do **NOT** assume information to be available in the
current format.
With that out of the way, let's carry on.
If you're willing to debug your own problem, you deserve a round of
applause :-)
Anyway, there isn't much to say here other than Trace Events will be
really helpful in figuring out issues with DWC3. Also, access to
Synopsys Databook will be **really** valuable in this case.
A USB Sniffer can be helpful at times but it's not entirely required,
there's a lot that can be understood without looking at the wire.
Feel free to email `me`_ and Cc `linux-usb`_ if you need any help.
``DebugFS``
-------------
``DebugFS`` is very good for gathering snapshots of what's going on
with DWC3 and/or any endpoint.
On DWC3's ``DebugFS`` directory, you will find the following files and
directories:
``ep[0..15]{in,out}/``
``link_state``
``regdump``
``testmode``
``link_state``
``````````````
When read, ``link_state`` will print out one of ``U0``, ``U1``,
``U2``, ``U3``, ``SS.Disabled``, ``RX.Detect``, ``SS.Inactive``,
``Polling``, ``Recovery``, ``Hot Reset``, ``Compliance``,
``Loopback``, ``Reset``, ``Resume`` or ``UNKNOWN link state``.
This file can also be written to in order to force link to one of the
states above.
``regdump``
`````````````
File name is self-explanatory. When read, ``regdump`` will print out a
register dump of DWC3. Note that this file can be grepped to find the
information you want.
``testmode``
``````````````
When read, ``testmode`` will print out a name of one of the specified
USB 2.0 Testmodes (``test_j``, ``test_k``, ``test_se0_nak``,
``test_packet``, ``test_force_enable``) or the string ``no test`` in
case no tests are currently being executed.
In order to start any of these test modes, the same strings can be
written to the file and DWC3 will enter the requested test mode.
Endpoint별 DebugFS 정보
237-266각 endpoint에는 `ep$num$dir` 규칙을 따르는 디렉터리가 하나씩 노출됩니다. 예는 `ep0in`, `ep0out`, `ep1in`이며, 내부에는 `descriptor_fetch_queue`, `event_queue`, `rx_fifo_queue`, `rx_info_queue`, `rx_request_queue`, `transfer_type`, `trb_ring`, `tx_fifo_queue`, `tx_request_queue`가 있습니다.
이 queue 파일들의 정보는 Synopsys Databook을 함께 보면 decode할 수 있습니다.
`transfer_type`은 endpoint descriptor에 따라 `control`, `bulk`, `interrupt`, `isochronous` 중 하나를 출력합니다. endpoint가 아직 enable되지 않았다면 `--`를 출력합니다.
``ep[0..15]{in,out}``
``````````````````````
For each endpoint we expose one directory following the naming
convention ``ep$num$dir`` *(ep0in, ep0out, ep1in, ...)*. Inside each
of these directories you will find the following files:
``descriptor_fetch_queue``
``event_queue``
``rx_fifo_queue``
``rx_info_queue``
``rx_request_queue``
``transfer_type``
``trb_ring``
``tx_fifo_queue``
``tx_request_queue``
With access to Synopsys Databook, you can decode the information on
them.
``transfer_type``
~~~~~~~~~~~~~~~~~~
When read, ``transfer_type`` will print out one of ``control``,
``bulk``, ``interrupt`` or ``isochronous`` depending on what the
endpoint descriptor says. If the endpoint hasn't been enabled yet, it
will print ``--``.
``trb_ring``
~~~~~~~~~~~~~
TRB ring 덤프 해석
267-532`trb_ring`을 읽으면 ring에 있는 모든 TRB의 세부 정보와 enqueue·dequeue pointer의 위치가 출력됩니다.
출력 열은 `buffer_addr`, `size`, `type`, `ioc`, `isp_imi`, `csp`, `chn`, `lst`, `hwo` 순서입니다. 예시의 `D`와 `E` 표시는 각각 dequeue와 enqueue 위치를 나타내며, 마지막 `link` TRB는 ring의 시작으로 연결합니다.
When read, ``trb_ring`` will print out details about all TRBs on the
ring. It will also tell you where our enqueue and dequeue pointers are
located in the ring:
.. code-block:: sh
buffer_addr,size,type,ioc,isp_imi,csp,chn,lst,hwo
000000002c754000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c75c000,481,normal,1,0,1,0,0,0
000000002c780000,481,normal,1,0,1,0,0,0
000000002c784000,481,normal,1,0,1,0,0,0
000000002c788000,481,normal,1,0,1,0,0,0
000000002c78c000,481,normal,1,0,1,0,0,0
000000002c790000,481,normal,1,0,1,0,0,0
000000002c754000,481,normal,1,0,1,0,0,0
000000002c758000,481,normal,1,0,1,0,0,0
000000002c75c000,512,normal,1,0,1,0,0,1 D
0000000000000000,0,UNKNOWN,0,0,0,0,0,0 E
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
0000000000000000,0,UNKNOWN,0,0,0,0,0,0
00000000381ab000,0,link,0,0,0,0,0,1
Trace Events, MMIO, IRQ, Control Request
533-583DWC3는 runtime 중 드라이버 동작을 수집할 수 있도록 여러 trace event를 제공합니다. 사용하려면 kernel configuration에서 `CONFIG_FTRACE`를 enable해야 하며, event 활성화 방법은 **Reporting Bugs** 절을 따릅니다.
MMIO 문제를 조사할 때 모든 접근을 보는 것이 유용할 수 있습니다. DWC3는 `dwc3_readl()`과 `dwc3_writel()` 각각에 대한 trace event를 제공하며 주소와 32비트 값을 기록합니다.
모든 IRQ event는 기록된 뒤 사람이 읽을 수 있는 문자열로 decode할 수 있습니다. event 값과 `ep0state`를 `dwc3_decode_event()`에 넘기는 `TP_printk` 형식을 사용합니다.
모든 USB Control Request도 trace buffer에 기록할 수 있습니다. Standard Control Request는 각 argument와 함께 읽기 쉬운 문자열로 decode되고, Class 및 Vendor request는 8바이트의 16진수열로 출력됩니다.
runtime 문제를 관찰하는 기본 trace 경로입니다.
Trace Events
-------------
DWC3 also provides several trace events which help us gathering
information about the behavior of the driver during runtime.
In order to use these events, you must enable ``CONFIG_FTRACE`` in
your kernel config.
For details about how enable DWC3 events, see section **Reporting
Bugs**.
The following subsections will give details about each Event Class and
each Event defined by DWC3.
MMIO
```````
It is sometimes useful to look at every MMIO access when looking for
bugs. Because of that, DWC3 offers two Trace Events (one for
dwc3_readl() and one for dwc3_writel()). ``TP_printk`` follows::
TP_printk("addr %p value %08x", __entry->base + __entry->offset,
__entry->value)
Interrupt Events
````````````````
Every IRQ event can be logged and decoded into a human readable
string. Because every event will be different, we don't give an
example other than the ``TP_printk`` format used::
TP_printk("event (%08x): %s", __entry->event,
dwc3_decode_event(__entry->event, __entry->ep0state))
Control Request
`````````````````
Every USB Control Request can be logged to the trace buffer. The
output format is::
TP_printk("%s", dwc3_decode_ctrl(__entry->bRequestType,
__entry->bRequest, __entry->wValue,
__entry->wIndex, __entry->wLength)
)
Note that Standard Control Requests will be decoded into
human-readable strings with their respective arguments. Class and
Vendor requests will be printed out a sequence of 8 bytes in hex
format.
Request, command, TRB, endpoint 수명주기 이벤트
584-683`struct usb_request`의 전체 수명주기를 trace buffer에서 추적할 수 있습니다. allocation, free, queueing, dequeueing, giveback마다 event가 있으며 request pointer, 실제·요청 길이, zero·short_not_ok·no_interrupt flag와 status를 출력합니다.
모든 Generic Command는 completion code와 함께 기록하고 decode할 수 있습니다. command 문자열, command 값, parameter, status 문자열이 출력됩니다.
Endpoint command도 completion code와 함께 기록합니다. endpoint 이름, command 문자열과 값, 세 parameter, command status를 출력합니다.
TRB 수명주기는 준비와 완료의 두 event로 표현됩니다. 이를 통해 queue·allocation 수, TRB와 buffer 주소, size, control flag, TRB type이 시간에 따라 어떻게 바뀌는지 볼 수 있습니다. Interrupt와 Isochronous endpoint에서는 PCM 값에 따라 `1x`, `2x`, `3x`도 표시됩니다.
Endpoint 수명주기는 enable과 disable operation으로 요약됩니다. trace에는 max packet 값과 제한, stream 수, burst, TRB enqueue·dequeue 위치, enabled·stall·wedge·transfer started·pending request·end transfer pending flag 및 방향이 기록됩니다.
Lifetime of a ``struct usb_request``
```````````````````````````````````````
The entire lifetime of a ``struct usb_request`` can be tracked on the
trace buffer. We have one event for each of allocation, free,
queueing, dequeueing, and giveback. Output format is::
TP_printk("%s: req %p length %u/%u %s%s%s ==> %d",
__get_str(name), __entry->req, __entry->actual, __entry->length,
__entry->zero ? "Z" : "z",
__entry->short_not_ok ? "S" : "s",
__entry->no_interrupt ? "i" : "I",
__entry->status
)
Generic Commands
````````````````````
We can log and decode every Generic Command with its completion
code. Format is::
TP_printk("cmd '%s' [%x] param %08x --> status: %s",
dwc3_gadget_generic_cmd_string(__entry->cmd),
__entry->cmd, __entry->param,
dwc3_gadget_generic_cmd_status_string(__entry->status)
)
Endpoint Commands
````````````````````
Endpoints commands can also be logged together with completion
code. Format is::
TP_printk("%s: cmd '%s' [%d] params %08x %08x %08x --> status: %s",
__get_str(name), dwc3_gadget_ep_cmd_string(__entry->cmd),
__entry->cmd, __entry->param0,
__entry->param1, __entry->param2,
dwc3_ep_cmd_status_string(__entry->cmd_status)
)
Lifetime of a ``TRB``
``````````````````````
A ``TRB`` Lifetime is simple. We are either preparing a ``TRB`` or
completing it. With these two events, we can see how a ``TRB`` changes
over time. Format is::
TP_printk("%s: %d/%d trb %p buf %08x%08x size %s%d ctrl %08x (%c%c%c%c:%c%c:%s)",
__get_str(name), __entry->queued, __entry->allocated,
__entry->trb, __entry->bph, __entry->bpl,
({char *s;
int pcm = ((__entry->size >> 24) & 3) + 1;
switch (__entry->type) {
case USB_ENDPOINT_XFER_INT:
case USB_ENDPOINT_XFER_ISOC:
switch (pcm) {
case 1:
s = "1x ";
break;
case 2:
s = "2x ";
break;
case 3:
s = "3x ";
break;
}
default:
s = "";
} s; }),
DWC3_TRB_SIZE_LENGTH(__entry->size), __entry->ctrl,
__entry->ctrl & DWC3_TRB_CTRL_HWO ? 'H' : 'h',
__entry->ctrl & DWC3_TRB_CTRL_LST ? 'L' : 'l',
__entry->ctrl & DWC3_TRB_CTRL_CHN ? 'C' : 'c',
__entry->ctrl & DWC3_TRB_CTRL_CSP ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_ISP_IMI ? 'S' : 's',
__entry->ctrl & DWC3_TRB_CTRL_IOC ? 'C' : 'c',
dwc3_trb_type_string(DWC3_TRBCTL_TYPE(__entry->ctrl))
)
Lifetime of an Endpoint
```````````````````````
And endpoint's lifetime is summarized with enable and disable
operations, both of which can be traced. Format is::
TP_printk("%s: mps %d/%d streams %d burst %d ring %d/%d flags %c:%c%c%c%c%c:%c:%c",
__get_str(name), __entry->maxpacket,
__entry->maxpacket_limit, __entry->max_streams,
__entry->maxburst, __entry->trb_enqueue,
__entry->trb_dequeue,
__entry->flags & DWC3_EP_ENABLED ? 'E' : 'e',
__entry->flags & DWC3_EP_STALL ? 'S' : 's',
__entry->flags & DWC3_EP_WEDGE ? 'W' : 'w',
__entry->flags & DWC3_EP_TRANSFER_STARTED ? 'B' : 'b',
__entry->flags & DWC3_EP_PENDING_REQUEST ? 'P' : 'p',
__entry->flags & DWC3_EP_END_TRANSFER_PENDING ? 'E' : 'e',
__entry->direction ? '<' : '>'
)
구조체, 메서드, 정의와 참고 링크
684-711구조체와 내부 구현 문서는 kernel-doc 지시문으로 소스에서 직접 가져옵니다. `drivers/usb/dwc3/core.h`는 main data structures, `drivers/usb/dwc3/gadget.h`는 gadget-only helpers를 설명합니다.
`drivers/usb/dwc3/gadget.c`에서는 gadget-side implementation을, `drivers/usb/dwc3/core.c`에서는 probe와 power management 등을 포함한 core driver를 문서화합니다. 네 지시문 모두 `:internal:` 항목을 포함합니다.
각주에서 TRB는 Transfer Request Block, Link TRB는 다른 Transfer Request Block을 가리키는 TRB, DebugFS는 Debug File System, ConfigFS는 Config File System, CBW는 Command Block Wrapper로 정의됩니다.
참조 링크는 `Linus' tree`의 kernel.org Git 저장소, 저자 Felipe Balbi의 이메일, `linux-usb@vger.kernel.org` mailing list를 가리킵니다.
Structures, Methods and Definitions
====================================
.. kernel-doc:: drivers/usb/dwc3/core.h
:doc: main data structures
:internal:
.. kernel-doc:: drivers/usb/dwc3/gadget.h
:doc: gadget-only helpers
:internal:
.. kernel-doc:: drivers/usb/dwc3/gadget.c
:doc: gadget-side implementation
:internal:
.. kernel-doc:: drivers/usb/dwc3/core.c
:doc: core driver (probe, PM, etc)
:internal:
.. [#trb] Transfer Request Block
.. [#link_trb] Transfer Request Block pointing to another Transfer
Request Block.
.. [#debugfs] The Debug File System
.. [#configfs] The Config File System
.. [#cbw] Command Block Wrapper
.. _Linus' tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
.. _me: felipe.balbi@linux.intel.com
.. _linux-usb: linux-usb@vger.kernel.org
요약·해설
dwc3.rst:1-711DWC3 드라이버는 peripheral·host·dual-role·hub 구성을 지원하며 Gadget API, endpoint TRB ring, DebugFS snapshot, FTRACE 기반 event를 통해 전송과 controller 상태를 관리·진단합니다.