diff mbox series

[5/7] usb: dwc3: gadget: Account for extra TRB

Message ID cdd5ae526c65893998898cfb0734161df7048554.1596674377.git.thinhn@synopsys.com (mailing list archive)
State Superseded
Headers show
Series usb: dwc3: gadget: Fix TRB preparation | expand

Commit Message

Thinh Nguyen Aug. 6, 2020, 12:45 a.m. UTC
When checking for how many TRB remaining, make sure to account for extra
TRBs for ZLP or MPS alignment transfers. Since the dwc3_prepare_trb*
functions should know if we need the extra TRBs, make those functions
return a status code -EAGAIN if there isn't enough TRB. Check against
those status when preparing TRB instead.

Fixes: c6267a51639b ("usb: dwc3: gadget: align transfers to wMaxPacketSize")
Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
---
 drivers/usb/dwc3/gadget.c | 79 ++++++++++++++++++++++++---------------
 1 file changed, 48 insertions(+), 31 deletions(-)

Comments

kernel test robot Aug. 6, 2020, 4:03 a.m. UTC | #1
Hi Thinh,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on e3ee0e740c3887d2293e8d54a8707218d70d86ca]

url:    https://github.com/0day-ci/linux/commits/Thinh-Nguyen/usb-dwc3-gadget-Fix-TRB-preparation/20200806-084719
base:    e3ee0e740c3887d2293e8d54a8707218d70d86ca
config: x86_64-randconfig-a004-20200805 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 076b120bebfd727b502208601012a44ab2e1028e)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/usb/dwc3/gadget.c:1177:16: warning: unused variable 'rem' [-Wunused-variable]
                   unsigned int rem = length % maxp;
                                ^
>> drivers/usb/dwc3/gadget.c:1306:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
   }
   ^
   2 warnings generated.

vim +1306 drivers/usb/dwc3/gadget.c

5ee85d890f8de5 Felipe Balbi         2016-05-13  1235  
5ee85d890f8de5 Felipe Balbi         2016-05-13  1236  /*
5ee85d890f8de5 Felipe Balbi         2016-05-13  1237   * dwc3_prepare_trbs - setup TRBs from requests
5ee85d890f8de5 Felipe Balbi         2016-05-13  1238   * @dep: endpoint for which requests are being prepared
5ee85d890f8de5 Felipe Balbi         2016-05-13  1239   *
5ee85d890f8de5 Felipe Balbi         2016-05-13  1240   * The function goes through the requests list and sets up TRBs for the
5ee85d890f8de5 Felipe Balbi         2016-05-13  1241   * transfers. The function returns once there are no more TRBs available or
5ee85d890f8de5 Felipe Balbi         2016-05-13  1242   * it runs out of requests.
5ee85d890f8de5 Felipe Balbi         2016-05-13  1243   */
e1a8607778079c Thinh Nguyen         2020-08-05  1244  static int dwc3_prepare_trbs(struct dwc3_ep *dep)
5ee85d890f8de5 Felipe Balbi         2016-05-13  1245  {
5ee85d890f8de5 Felipe Balbi         2016-05-13  1246  	struct dwc3_request	*req, *n;
e1a8607778079c Thinh Nguyen         2020-08-05  1247  	int ret = 0;
5ee85d890f8de5 Felipe Balbi         2016-05-13  1248  
5ee85d890f8de5 Felipe Balbi         2016-05-13  1249  	BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
5ee85d890f8de5 Felipe Balbi         2016-05-13  1250  
d86c5a676e5b1e Felipe Balbi         2016-10-25  1251  	/*
d86c5a676e5b1e Felipe Balbi         2016-10-25  1252  	 * We can get in a situation where there's a request in the started list
d86c5a676e5b1e Felipe Balbi         2016-10-25  1253  	 * but there weren't enough TRBs to fully kick it in the first time
d86c5a676e5b1e Felipe Balbi         2016-10-25  1254  	 * around, so it has been waiting for more TRBs to be freed up.
d86c5a676e5b1e Felipe Balbi         2016-10-25  1255  	 *
d86c5a676e5b1e Felipe Balbi         2016-10-25  1256  	 * In that case, we should check if we have a request with pending_sgs
d86c5a676e5b1e Felipe Balbi         2016-10-25  1257  	 * in the started list and prepare TRBs for that request first,
d86c5a676e5b1e Felipe Balbi         2016-10-25  1258  	 * otherwise we will prepare TRBs completely out of order and that will
d86c5a676e5b1e Felipe Balbi         2016-10-25  1259  	 * break things.
d86c5a676e5b1e Felipe Balbi         2016-10-25  1260  	 */
d86c5a676e5b1e Felipe Balbi         2016-10-25  1261  	list_for_each_entry(req, &dep->started_list, list) {
e1a8607778079c Thinh Nguyen         2020-08-05  1262  		if (req->num_pending_sgs > 0) {
e1a8607778079c Thinh Nguyen         2020-08-05  1263  			ret = dwc3_prepare_one_trb_sg(dep, req);
e1a8607778079c Thinh Nguyen         2020-08-05  1264  			if (ret)
e1a8607778079c Thinh Nguyen         2020-08-05  1265  				return ret;
e1a8607778079c Thinh Nguyen         2020-08-05  1266  		}
63c7bb299fc9c4 Thinh Nguyen         2020-05-15  1267  
63c7bb299fc9c4 Thinh Nguyen         2020-05-15  1268  		/*
63c7bb299fc9c4 Thinh Nguyen         2020-05-15  1269  		 * Don't prepare beyond a transfer. In DWC_usb32, its transfer
63c7bb299fc9c4 Thinh Nguyen         2020-05-15  1270  		 * burst capability may try to read and use TRBs beyond the
63c7bb299fc9c4 Thinh Nguyen         2020-05-15  1271  		 * active transfer instead of stopping.
63c7bb299fc9c4 Thinh Nguyen         2020-05-15  1272  		 */
63c7bb299fc9c4 Thinh Nguyen         2020-05-15  1273  		if (dep->stream_capable && req->request.is_last)
e1a8607778079c Thinh Nguyen         2020-08-05  1274  			return 0;
d86c5a676e5b1e Felipe Balbi         2016-10-25  1275  	}
d86c5a676e5b1e Felipe Balbi         2016-10-25  1276  
5ee85d890f8de5 Felipe Balbi         2016-05-13  1277  	list_for_each_entry_safe(req, n, &dep->pending_list, list) {
cdb55b39fab82b Felipe Balbi         2017-05-17  1278  		struct dwc3	*dwc = dep->dwc;
cdb55b39fab82b Felipe Balbi         2017-05-17  1279  
cdb55b39fab82b Felipe Balbi         2017-05-17  1280  		ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request,
cdb55b39fab82b Felipe Balbi         2017-05-17  1281  						    dep->direction);
cdb55b39fab82b Felipe Balbi         2017-05-17  1282  		if (ret)
e1a8607778079c Thinh Nguyen         2020-08-05  1283  			return ret;
cdb55b39fab82b Felipe Balbi         2017-05-17  1284  
cdb55b39fab82b Felipe Balbi         2017-05-17  1285  		req->sg			= req->request.sg;
a31e63b608ff78 Anurag Kumar Vulisha 2018-03-27  1286  		req->start_sg		= req->sg;
c96e6725db9d6a Anurag Kumar Vulisha 2018-03-27  1287  		req->num_queued_sgs	= 0;
cdb55b39fab82b Felipe Balbi         2017-05-17  1288  		req->num_pending_sgs	= req->request.num_mapped_sgs;
cdb55b39fab82b Felipe Balbi         2017-05-17  1289  
1f512119a08c0d Felipe Balbi         2016-08-12  1290  		if (req->num_pending_sgs > 0)
e1a8607778079c Thinh Nguyen         2020-08-05  1291  			ret = dwc3_prepare_one_trb_sg(dep, req);
5ee85d890f8de5 Felipe Balbi         2016-05-13  1292  		else
e1a8607778079c Thinh Nguyen         2020-08-05  1293  			ret = dwc3_prepare_one_trb_linear(dep, req);
5ee85d890f8de5 Felipe Balbi         2016-05-13  1294  
e1a8607778079c Thinh Nguyen         2020-08-05  1295  		if (ret)
e1a8607778079c Thinh Nguyen         2020-08-05  1296  			return ret;
aefe3d232b6629 Thinh Nguyen         2020-05-05  1297  
aefe3d232b6629 Thinh Nguyen         2020-05-05  1298  		/*
aefe3d232b6629 Thinh Nguyen         2020-05-05  1299  		 * Don't prepare beyond a transfer. In DWC_usb32, its transfer
aefe3d232b6629 Thinh Nguyen         2020-05-05  1300  		 * burst capability may try to read and use TRBs beyond the
aefe3d232b6629 Thinh Nguyen         2020-05-05  1301  		 * active transfer instead of stopping.
aefe3d232b6629 Thinh Nguyen         2020-05-05  1302  		 */
aefe3d232b6629 Thinh Nguyen         2020-05-05  1303  		if (dep->stream_capable && req->request.is_last)
e1a8607778079c Thinh Nguyen         2020-08-05  1304  			return 0;
72246da40f3719 Felipe Balbi         2011-08-19  1305  	}
72246da40f3719 Felipe Balbi         2011-08-19 @1306  }
72246da40f3719 Felipe Balbi         2011-08-19  1307  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot Aug. 7, 2020, 2:30 a.m. UTC | #2
Hi Thinh,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on e3ee0e740c3887d2293e8d54a8707218d70d86ca]

url:    https://github.com/0day-ci/linux/commits/Thinh-Nguyen/usb-dwc3-gadget-Fix-TRB-preparation/20200806-084719
base:    e3ee0e740c3887d2293e8d54a8707218d70d86ca
config: mips-randconfig-r005-20200807 (attached as .config)
compiler: mipsel-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/usb/dwc3/gadget.c: In function 'dwc3_prepare_one_trb_sg':
   drivers/usb/dwc3/gadget.c:1177:16: warning: unused variable 'rem' [-Wunused-variable]
    1177 |   unsigned int rem = length % maxp;
         |                ^~~
   drivers/usb/dwc3/gadget.c: In function 'dwc3_prepare_trbs':
>> drivers/usb/dwc3/gadget.c:1306:1: warning: control reaches end of non-void function [-Wreturn-type]
    1306 | }
         | ^

vim +1306 drivers/usb/dwc3/gadget.c

5ee85d890f8de5c Felipe Balbi         2016-05-13  1235  
5ee85d890f8de5c Felipe Balbi         2016-05-13  1236  /*
5ee85d890f8de5c Felipe Balbi         2016-05-13  1237   * dwc3_prepare_trbs - setup TRBs from requests
5ee85d890f8de5c Felipe Balbi         2016-05-13  1238   * @dep: endpoint for which requests are being prepared
5ee85d890f8de5c Felipe Balbi         2016-05-13  1239   *
5ee85d890f8de5c Felipe Balbi         2016-05-13  1240   * The function goes through the requests list and sets up TRBs for the
5ee85d890f8de5c Felipe Balbi         2016-05-13  1241   * transfers. The function returns once there are no more TRBs available or
5ee85d890f8de5c Felipe Balbi         2016-05-13  1242   * it runs out of requests.
5ee85d890f8de5c Felipe Balbi         2016-05-13  1243   */
e1a8607778079c1 Thinh Nguyen         2020-08-05  1244  static int dwc3_prepare_trbs(struct dwc3_ep *dep)
5ee85d890f8de5c Felipe Balbi         2016-05-13  1245  {
5ee85d890f8de5c Felipe Balbi         2016-05-13  1246  	struct dwc3_request	*req, *n;
e1a8607778079c1 Thinh Nguyen         2020-08-05  1247  	int ret = 0;
5ee85d890f8de5c Felipe Balbi         2016-05-13  1248  
5ee85d890f8de5c Felipe Balbi         2016-05-13  1249  	BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
5ee85d890f8de5c Felipe Balbi         2016-05-13  1250  
d86c5a676e5b1ee Felipe Balbi         2016-10-25  1251  	/*
d86c5a676e5b1ee Felipe Balbi         2016-10-25  1252  	 * We can get in a situation where there's a request in the started list
d86c5a676e5b1ee Felipe Balbi         2016-10-25  1253  	 * but there weren't enough TRBs to fully kick it in the first time
d86c5a676e5b1ee Felipe Balbi         2016-10-25  1254  	 * around, so it has been waiting for more TRBs to be freed up.
d86c5a676e5b1ee Felipe Balbi         2016-10-25  1255  	 *
d86c5a676e5b1ee Felipe Balbi         2016-10-25  1256  	 * In that case, we should check if we have a request with pending_sgs
d86c5a676e5b1ee Felipe Balbi         2016-10-25  1257  	 * in the started list and prepare TRBs for that request first,
d86c5a676e5b1ee Felipe Balbi         2016-10-25  1258  	 * otherwise we will prepare TRBs completely out of order and that will
d86c5a676e5b1ee Felipe Balbi         2016-10-25  1259  	 * break things.
d86c5a676e5b1ee Felipe Balbi         2016-10-25  1260  	 */
d86c5a676e5b1ee Felipe Balbi         2016-10-25  1261  	list_for_each_entry(req, &dep->started_list, list) {
e1a8607778079c1 Thinh Nguyen         2020-08-05  1262  		if (req->num_pending_sgs > 0) {
e1a8607778079c1 Thinh Nguyen         2020-08-05  1263  			ret = dwc3_prepare_one_trb_sg(dep, req);
e1a8607778079c1 Thinh Nguyen         2020-08-05  1264  			if (ret)
e1a8607778079c1 Thinh Nguyen         2020-08-05  1265  				return ret;
e1a8607778079c1 Thinh Nguyen         2020-08-05  1266  		}
63c7bb299fc9c43 Thinh Nguyen         2020-05-15  1267  
63c7bb299fc9c43 Thinh Nguyen         2020-05-15  1268  		/*
63c7bb299fc9c43 Thinh Nguyen         2020-05-15  1269  		 * Don't prepare beyond a transfer. In DWC_usb32, its transfer
63c7bb299fc9c43 Thinh Nguyen         2020-05-15  1270  		 * burst capability may try to read and use TRBs beyond the
63c7bb299fc9c43 Thinh Nguyen         2020-05-15  1271  		 * active transfer instead of stopping.
63c7bb299fc9c43 Thinh Nguyen         2020-05-15  1272  		 */
63c7bb299fc9c43 Thinh Nguyen         2020-05-15  1273  		if (dep->stream_capable && req->request.is_last)
e1a8607778079c1 Thinh Nguyen         2020-08-05  1274  			return 0;
d86c5a676e5b1ee Felipe Balbi         2016-10-25  1275  	}
d86c5a676e5b1ee Felipe Balbi         2016-10-25  1276  
5ee85d890f8de5c Felipe Balbi         2016-05-13  1277  	list_for_each_entry_safe(req, n, &dep->pending_list, list) {
cdb55b39fab82b5 Felipe Balbi         2017-05-17  1278  		struct dwc3	*dwc = dep->dwc;
cdb55b39fab82b5 Felipe Balbi         2017-05-17  1279  
cdb55b39fab82b5 Felipe Balbi         2017-05-17  1280  		ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request,
cdb55b39fab82b5 Felipe Balbi         2017-05-17  1281  						    dep->direction);
cdb55b39fab82b5 Felipe Balbi         2017-05-17  1282  		if (ret)
e1a8607778079c1 Thinh Nguyen         2020-08-05  1283  			return ret;
cdb55b39fab82b5 Felipe Balbi         2017-05-17  1284  
cdb55b39fab82b5 Felipe Balbi         2017-05-17  1285  		req->sg			= req->request.sg;
a31e63b608ff78c Anurag Kumar Vulisha 2018-03-27  1286  		req->start_sg		= req->sg;
c96e6725db9d6a0 Anurag Kumar Vulisha 2018-03-27  1287  		req->num_queued_sgs	= 0;
cdb55b39fab82b5 Felipe Balbi         2017-05-17  1288  		req->num_pending_sgs	= req->request.num_mapped_sgs;
cdb55b39fab82b5 Felipe Balbi         2017-05-17  1289  
1f512119a08c0d4 Felipe Balbi         2016-08-12  1290  		if (req->num_pending_sgs > 0)
e1a8607778079c1 Thinh Nguyen         2020-08-05  1291  			ret = dwc3_prepare_one_trb_sg(dep, req);
5ee85d890f8de5c Felipe Balbi         2016-05-13  1292  		else
e1a8607778079c1 Thinh Nguyen         2020-08-05  1293  			ret = dwc3_prepare_one_trb_linear(dep, req);
5ee85d890f8de5c Felipe Balbi         2016-05-13  1294  
e1a8607778079c1 Thinh Nguyen         2020-08-05  1295  		if (ret)
e1a8607778079c1 Thinh Nguyen         2020-08-05  1296  			return ret;
aefe3d232b6629c Thinh Nguyen         2020-05-05  1297  
aefe3d232b6629c Thinh Nguyen         2020-05-05  1298  		/*
aefe3d232b6629c Thinh Nguyen         2020-05-05  1299  		 * Don't prepare beyond a transfer. In DWC_usb32, its transfer
aefe3d232b6629c Thinh Nguyen         2020-05-05  1300  		 * burst capability may try to read and use TRBs beyond the
aefe3d232b6629c Thinh Nguyen         2020-05-05  1301  		 * active transfer instead of stopping.
aefe3d232b6629c Thinh Nguyen         2020-05-05  1302  		 */
aefe3d232b6629c Thinh Nguyen         2020-05-05  1303  		if (dep->stream_capable && req->request.is_last)
e1a8607778079c1 Thinh Nguyen         2020-08-05  1304  			return 0;
72246da40f3719a Felipe Balbi         2011-08-19  1305  	}
72246da40f3719a Felipe Balbi         2011-08-19 @1306  }
72246da40f3719a Felipe Balbi         2011-08-19  1307  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index dcadef105c2a..64c2ebacc73c 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1057,8 +1057,10 @@  static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb,
  * @trb_length: buffer size of the TRB
  * @chain: should this TRB be chained to the next?
  * @node: only for isochronous endpoints. First TRB needs different type.
+ *
+ * Return 0 on success or -EAGAIN if there is not enough TRBs.
  */
-static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
+static int dwc3_prepare_one_trb(struct dwc3_ep *dep,
 		struct dwc3_request *req, unsigned int trb_length,
 		unsigned chain, unsigned node)
 {
@@ -1069,6 +1071,9 @@  static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 	unsigned		no_interrupt = req->request.no_interrupt;
 	unsigned		is_last = req->request.is_last;
 
+	if (!dwc3_calc_trbs_left(dep))
+		return -EAGAIN;
+
 	if (req->request.num_sgs > 0)
 		dma = sg_dma_address(req->start_sg);
 	else
@@ -1086,6 +1091,8 @@  static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
 
 	__dwc3_prepare_one_trb(dep, trb, dma, trb_length, chain, node,
 			stream_id, short_not_ok, no_interrupt, is_last);
+
+	return 0;
 }
 
 /**
@@ -1094,11 +1101,13 @@  static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
  * @req: The request to prepare
  * @entry_length: The last SG entry size
  * @node: Indicates whether this is not the first entry (for isoc only)
+ *
+ * Returns 0 on success or -EAGAIN if there is not enough TRBs.
  */
-static void dwc3_prepare_last_sg(struct dwc3_ep *dep,
-				 struct dwc3_request *req,
-				 unsigned int entry_length,
-				 unsigned int node)
+static int dwc3_prepare_last_sg(struct dwc3_ep *dep,
+				struct dwc3_request *req,
+				unsigned int entry_length,
+				unsigned int node)
 {
 	unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
 	unsigned int rem = req->request.length % maxp;
@@ -1118,6 +1127,9 @@  static void dwc3_prepare_last_sg(struct dwc3_ep *dep,
 	if (num_extra_trbs > 0)
 		req->needs_extra_trb = true;
 
+	if (dwc3_calc_trbs_left(dep) < num_extra_trbs + 1)
+		return -EAGAIN;
+
 	/* Prepare a normal TRB */
 	dwc3_prepare_one_trb(dep, req, entry_length, req->needs_extra_trb, node);
 
@@ -1145,9 +1157,11 @@  static void dwc3_prepare_last_sg(struct dwc3_ep *dep,
 				       req->request.no_interrupt,
 				       req->request.is_last);
 	}
+
+	return 0;
 }
 
-static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
+static int dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
 		struct dwc3_request *req)
 {
 	struct scatterlist *sg = req->start_sg;
@@ -1163,6 +1177,7 @@  static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
 		unsigned int rem = length % maxp;
 		unsigned int trb_length;
 		bool last_sg = false;
+		int ret = 0;
 
 		trb_length = min_t(unsigned int, length, sg_dma_len(req->start_sg));
 
@@ -1179,9 +1194,13 @@  static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
 			last_sg = true;
 
 		if (last_sg)
-			dwc3_prepare_last_sg(dep, req, trb_length, i);
+			ret = dwc3_prepare_last_sg(dep, req, trb_length, i);
 		else
-			dwc3_prepare_one_trb(dep, req, trb_length, 1, i);
+			ret = dwc3_prepare_one_trb(dep, req, trb_length, 1, i);
+
+		/* Ran out of TRBs */
+		if (ret)
+			return ret;
 
 		/*
 		 * There can be a situation where all sgs in sglist are not
@@ -1204,16 +1223,14 @@  static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
 			req->num_pending_sgs -= req->request.num_mapped_sgs - req->num_queued_sgs;
 			break;
 		}
-
-		if (!dwc3_calc_trbs_left(dep))
-			break;
 	}
+	return 0;
 }
 
-static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
+static int dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
 		struct dwc3_request *req)
 {
-	dwc3_prepare_last_sg(dep, req, req->request.length, 0);
+	return dwc3_prepare_last_sg(dep, req, req->request.length, 0);
 }
 
 /*
@@ -1224,9 +1241,10 @@  static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
  * transfers. The function returns once there are no more TRBs available or
  * it runs out of requests.
  */
-static void dwc3_prepare_trbs(struct dwc3_ep *dep)
+static int dwc3_prepare_trbs(struct dwc3_ep *dep)
 {
 	struct dwc3_request	*req, *n;
+	int ret = 0;
 
 	BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);
 
@@ -1241,11 +1259,11 @@  static void dwc3_prepare_trbs(struct dwc3_ep *dep)
 	 * break things.
 	 */
 	list_for_each_entry(req, &dep->started_list, list) {
-		if (req->num_pending_sgs > 0)
-			dwc3_prepare_one_trb_sg(dep, req);
-
-		if (!dwc3_calc_trbs_left(dep))
-			return;
+		if (req->num_pending_sgs > 0) {
+			ret = dwc3_prepare_one_trb_sg(dep, req);
+			if (ret)
+				return ret;
+		}
 
 		/*
 		 * Don't prepare beyond a transfer. In DWC_usb32, its transfer
@@ -1253,17 +1271,16 @@  static void dwc3_prepare_trbs(struct dwc3_ep *dep)
 		 * active transfer instead of stopping.
 		 */
 		if (dep->stream_capable && req->request.is_last)
-			return;
+			return 0;
 	}
 
 	list_for_each_entry_safe(req, n, &dep->pending_list, list) {
 		struct dwc3	*dwc = dep->dwc;
-		int		ret;
 
 		ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request,
 						    dep->direction);
 		if (ret)
-			return;
+			return ret;
 
 		req->sg			= req->request.sg;
 		req->start_sg		= req->sg;
@@ -1271,12 +1288,12 @@  static void dwc3_prepare_trbs(struct dwc3_ep *dep)
 		req->num_pending_sgs	= req->request.num_mapped_sgs;
 
 		if (req->num_pending_sgs > 0)
-			dwc3_prepare_one_trb_sg(dep, req);
+			ret = dwc3_prepare_one_trb_sg(dep, req);
 		else
-			dwc3_prepare_one_trb_linear(dep, req);
+			ret = dwc3_prepare_one_trb_linear(dep, req);
 
-		if (!dwc3_calc_trbs_left(dep))
-			return;
+		if (ret)
+			return ret;
 
 		/*
 		 * Don't prepare beyond a transfer. In DWC_usb32, its transfer
@@ -1284,7 +1301,7 @@  static void dwc3_prepare_trbs(struct dwc3_ep *dep)
 		 * active transfer instead of stopping.
 		 */
 		if (dep->stream_capable && req->request.is_last)
-			return;
+			return 0;
 	}
 }
 
@@ -1298,12 +1315,12 @@  static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep)
 	int				ret;
 	u32				cmd;
 
-	if (!dwc3_calc_trbs_left(dep))
-		return 0;
-
 	starting = !(dep->flags & DWC3_EP_TRANSFER_STARTED);
 
-	dwc3_prepare_trbs(dep);
+	ret = dwc3_prepare_trbs(dep);
+	if (ret)
+		return 0;
+
 	req = next_request(&dep->started_list);
 	if (!req) {
 		dep->flags |= DWC3_EP_PENDING_REQUEST;