usb: dwc3: gadget: Bug fixes
Subsystems (2)
cover usb: dwc3: gadget: Bug fixes
This is a re-submission of patches [1/4] and [2/4] from:
http://www.spinics.net/lists/linux-usb/msg118841.html
Commit log of both these patches has been modified for aided clarity. These patches have been rebased on Balbi's testing/next.
Patches [3/4] and [4/4] were accepted as they were.
Amit Virdi (2):
usb: dwc3: gadget: Fix TRB preparation during SG
usb: dwc3: gadget: Stop TRB preparation after limit is reached
drivers/usb/dwc3/gadget.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
Signature · 6 lines
1.8.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH RESEND 1/2 usb: dwc3: gadget: Fix TRB preparation during SG
When scatter gather (SG) is used, multiple TRBs are prepared from one DWC3 request (dwc3_request). So while preparing TRBs, the 'last' flag should be set only when it is the last TRB being prepared from the last dwc3_request entry.
The current implementation uses list_is_last to check if the dwc3_request is the last entry from the request_list. However, list_is_last returns false for the last entry too. This is because, while preparing the first TRB from a request, the function dwc3_prepare_one_trb modifies the request's next and prev pointers while moving the URB to req_queued. Hence, list_is_last always returns false no matter what.
The correct way is not to access the modified pointers of dwc3_request but to use list_empty macro instead.
gather implementation"
--- drivers/usb/dwc3/gadget.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/usb/dwc3/gadget.c +1 -2
@@ -879,8 +879,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)if (i == (request->num_mapped_sgs -1 ) ||sg_is_last (s)) { -if (list_is_last (&req->list, - &dep->request_list)) +if (list_empty (&dep->request_list)) last_one = true; chain = false; }
Signature · 6 lines
1.8.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH RESEND 2/2 usb: dwc3: gadget: Stop TRB preparation after limit is reached
In reply to Amit VirdiDWC3 gadget sets up a pool of 32 TRBs for each EP during initialization. This means, the max TRBs that can be submitted for an EP is fixed to 32. Since the request queue for an EP is a linked list, any number of requests can be queued to it by the gadget layer. However, the dwc3 driver must not submit TRBs more than the pool it has created for. This limit wasn't respected when SG was used resulting in submitting more than the max TRBs, eventually leading to non-transfer of the TRBs submitted over the max limit.
Root cause:
When SG is used, there are two loops iterating to prepare TRBs:
- Outer loop over the request_list
- Inner loop over the SG list
The code was missing break to get out of the outer loop.
--- drivers/usb/dwc3/gadget.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/usb/dwc3/gadget.c +3 -0
@@ -897,6 +897,9 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)if (last_one)break ; } + +if (last_one) +break ; }else { dma = req->request.dma; length = req->request.length;
Signature · 1 line
1.8.0
Quoted 6 lines · Amit VIRDI
This is a re-submission of patches [1/4] and [2/4] from:
http://www.spinics.net/lists/linux-usb/msg118841.htmlCommit log of both these patches has been modified for aided clarity. These patches have been rebased on Balbi's testing/next.
Quoted 9 lines
Patches [3/4] and [4/4] were accepted as they were.
Amit Virdi (2):
usb: dwc3: gadget: Fix TRB preparation during SG
usb: dwc3: gadget: Stop TRB preparation after limit is reacheddrivers/usb/dwc3/gadget.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
I was using older git version, so git failed to send patches to [email protected]
Please discard this patchset. I'm resending with updated git
A message that is not in the archive (sent off-list or not yet received): [email protected]
cover usb: dwc3: gadget: Bug fixes
This is a re-submission of patches [1/4] and [2/4] from:
http://www.spinics.net/lists/linux-usb/msg118841.html
Commit log of both these patches has been modified for aided clarity. These patches have been rebased on Balbi's testing/next.
Patches [3/4] and [4/4] were accepted as they were.
Amit Virdi (2):
usb: dwc3: gadget: Fix TRB preparation during SG
usb: dwc3: gadget: Stop TRB preparation after limit is reached
drivers/usb/dwc3/gadget.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
Signature · 6 lines
1.8.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/2 usb: dwc3: gadget: Fix TRB preparation during SG
When scatter gather (SG) is used, multiple TRBs are prepared from one DWC3 request (dwc3_request). So while preparing TRBs, the 'last' flag should be set only when it is the last TRB being prepared from the last dwc3_request entry.
The current implementation uses list_is_last to check if the dwc3_request is the last entry from the request_list. However, list_is_last returns false for the last entry too. This is because, while preparing the first TRB from a request, the function dwc3_prepare_one_trb modifies the request's next and prev pointers while moving the URB to req_queued. Hence, list_is_last always returns false no matter what.
The correct way is not to access the modified pointers of dwc3_request but to use list_empty macro instead.
gather implementation"
--- drivers/usb/dwc3/gadget.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/usb/dwc3/gadget.c +1 -2
@@ -879,8 +879,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)if (i == (request->num_mapped_sgs -1 ) ||sg_is_last (s)) { -if (list_is_last (&req->list, - &dep->request_list)) +if (list_empty (&dep->request_list)) last_one = true; chain = false; }
Signature · 6 lines
1.8.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 2/2 usb: dwc3: gadget: Stop TRB preparation after limit is reached
In reply to a message not in the archiveDWC3 gadget sets up a pool of 32 TRBs for each EP during initialization. This means, the max TRBs that can be submitted for an EP is fixed to 32. Since the request queue for an EP is a linked list, any number of requests can be queued to it by the gadget layer. However, the dwc3 driver must not submit TRBs more than the pool it has created for. This limit wasn't respected when SG was used resulting in submitting more than the max TRBs, eventually leading to non-transfer of the TRBs submitted over the max limit.
Root cause:
When SG is used, there are two loops iterating to prepare TRBs:
- Outer loop over the request_list
- Inner loop over the SG list
The code was missing break to get out of the outer loop.
--- drivers/usb/dwc3/gadget.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/usb/dwc3/gadget.c +3 -0
@@ -897,6 +897,9 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)if (last_one)break ; } + +if (last_one) +break ; }else { dma = req->request.dma; length = req->request.length;
Signature · 6 lines
1.8.0 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html