Before talking about the data transmission stage, we should first solve the historical issues left over. In usb_stor_bulk_transfer_buf (), row 406 has an interesting function called interpret_urb_result. This function is also from drivers/usb/storage/transport. c:
265 static int interpret_urb_result (struct us_data * us, unsigned int pipe,
266 unsigned int length, int result, unsigned int partial)
267 {
268 US_DEBUGP ("Status code % d; transferred % u/% u \ n ",
269 result, partial, length );
270 switch (result ){
271
272/* no error code; did we send all the data? */
273 case 0:
274 if (partial! = Length ){
275 US_DEBUGP ("-- transfertransfer \ n ");
276 return USB_STOR_XFER_SHORT;
277}
278
279 US_DEBUGP ("-- transfer complete \ n ");
280 return USB_STOR_XFER_GOOD;
281
282/* stalled */
283 case-EPIPE:
284/* for control endpoints, (used by CB [I]) astall indicates
285 * afailed command */
286 if (usb_pipecontrol (pipe )){
287 US_DEBUGP ("-- stall oncontrol pipe \ n ");
288 return USB_STOR_XFER_STALLED;
289}
290
291/* for other sorts of endpoint, clear thestall */
292 US_DEBUGP ("clearing endpoint halt forpipe 0x % x \ n", pipe );
293 if (usb_stor_clear_halt (us, pipe) <0)
294 return USB_STOR_XFER_ERROR;
295 return USB_STOR_XFER_STALLED;
296
297/* babble-the device tried to send morethan we wanted to read */
298 case-EOVERFLOW:
299 US_DEBUGP ("-- babble \ n ");
300 return USB_STOR_XFER_LONG;
301
302/* the transfer was canceled by abort, disconnect, or timeout */
303 case-ECONNRESET:
304 US_DEBUGP ("-- transfercancelled \ n ");
305 return USB_STOR_XFER_ERROR;
306
307/* short scatter-gather read transfer */
308 case-EREMOTEIO:
309 US_DEBUGP ("-- short readtransfer \ n ");
310 return USB_STOR_XFER_SHORT;
311
312/* abort or disconnect in progress */
313 case-EIO:
314 US_DEBUGP ("-- abort or disconnect inprogress \ n ");
315 return USB_STOR_XFER_ERROR;
316
317/* the catch-all error case */
Default 318:
319 US_DEBUGP ("-- unknown error \ n ");
320 return USB_STOR_XFER_ERROR;
321}
322}
It should be said that the role of this function is to be clear at a glance, that is, to determine based on the passed parameter result, so as to take corresponding actions. Partial is the actual length of the transmission, while length is the expected length. If the transmission is over, we must compare the two because of expectation, we will be disappointed. Result is the return value of the usb_stor _ msg_common () function, which is actually the status code. If it is set to 0, everything goes smoothly and the result is successful. 268 in this line, print the result and print the ratio of partial to length at the same time. Note that the "/" in the middle of two % u is the division sign, or the delimiter used to separate the numerator and denominator.
Then, a switch statement is used to determine the result, which is 0, indicating that at least data is transmitted. Then there are two cases, so different values are returned: USB_STOR_XFER_SHORT and USB_STOR_XFER_GOOD. What will happen after these values are returned? Let's take a look. Currently, you only need to know that the returned value can only be USB_STOR_XFER_GOOD if the actual transmission is completely satisfactory. If other values are returned, the problem occurs. Here, the result passed to the switch is actually the value passed from the USB Core layer.
We noticed that the interpret_urb_result function is displayed in usb_stor_bulk_transfer_buf () as a return value. In other words, after the former is returned, the latter is immediately returned, that is, it is returned to usb_stor_Bulk_transport () again. Therefore, we pull the line of sight back to usb_stor_Bulk_transport () and line 3. If the result is not USB_STOR_XFER_GOOD, it indicates that there are some problems, so usb_stor_Bulk_transport () is also returned, there is no need to transfer data in the next phase. Otherwise, you can proceed to the next stage.
The next phase is the so-called Bulk-only transmission. There are three phases in total, namely the Command Transmission Phase, data transmission phase, and state transmission phase. Obviously, the most meaningful stage is the data transmission stage. Before that, we have already talked about the first stage, namely the Command Transmission stage. Next we can look at the data phase.
There is nothing to say about lines 3 and lines 3. Some companies' products have to be delayed by 989 μs in the command and data phases, at first, we found that Genesys Logic's products had this problem, and later we found that more products had the same problem. Therefore, the flag US_FL_GO_SLOW is used. If you are interested in looking at the early Linux Kernel, you will find that there was actually no such flag. At that time, a USB_VENDOR_ID_GENESYS is defined, directly compare whether this product is from Genesys Logic. If yes, consider this latency. Otherwise, you will not need to use it.
Line 3, transfer_length may be 0, because some commands do not require data transmission, so there is no data stage. For those with data stages, we enter the if section.
There is nothing to say about Row 3: determine whether to use the receiving or sending Pipeline Based on the Data Transmission Direction.
Then, in Row 3, The usb_stor_bulk_transfer_sg () function truly implements batch data transmission. This function is from drivers/usb/storage/transport. c:
470 int usb_stor_bulk_transfer_sg (struct us_data * us, unsigned int pipe,
471 void * buf, unsigned int length_left, int use_sg, int * residual)
472 {
473 int result;
474 unsigned int parttial;
475
476/* are we scatter-gathering? */
477 if (use_sg ){
478/* use the usb core scatter-gather primitives */
479 result = usb_stor_bulk_transfer_sglist (us, pipe,
480 (structscatterlist *) buf, use_sg,
481 length_left, & partial );
482 length_left-= partial;
483} else {
484/* no scatter-gather, just make the request */
485 result = usb_stor_bulk_transfer_buf (us, pipe, buf,
486 length_left, & partial );
487 length_left-= partial;
488}
489
490/* store the residual and return the error code */
491 if (residual)
492 * residual = length_left;
493 return result;
494}
Note that this function is a shell. The two functions called or used are: usb_stor_bulk_transfer_sglist () and usb_stor_bulk_transfer_buf (). The latter has just met, and the former is a function specially designed for scatter-gather transmission. It also comes from drivers/usb/storage/transport. c:
416 static int usb_stor_bulk_transfer_sglist (structus_data * us, unsigned int pipe,
417 struct scatterlist * sg, int num_sg, unsigned int length,
418 unsigned int * act_len)
419 {
420 int result;
421
422/* don't submit s-g requests during abort/disconnect processing */
423 if (us-> flags & ABORTING_OR_DISCONNECTING)
424 return USB_STOR_XFER_ERROR;
425
426/* initialize the scatter-gather request block */
427 US_DEBUGP ("% s: xfer % u Bytes, % dentries \ n", _ FUNCTION __,
428 length, num_sg );
429 result = usb_sg_init (& us-> current_sg, us-> pusb_dev, pipe, 0,
430 sg, num_sg, length, GFP_NOIO );
431 if (result ){
432 US_DEBUGP ("usb_sg_init returned % d \ n", result );
433 return USB_STOR_XFER_ERROR;
434}
435
436/* since the block has been initializedsuccessfully, it's now
437 * okayto cancel it */
438 set_bit (us_f1_x_sg_active, & us-> flags );
439
440/* did an abort/disconnect occur during thesubmission? */
441 if (us-> flags & ABORTING_OR_DISCONNECTING ){
442
443/* cancel the request, if it hasn' t beencancelled already */
444 if (test_and_clear_bit (us_f1_x_sg_active, & us-> flags )){
445 US_DEBUGP ("-- canceling sg request \ n ");
446 usb_sg_cancel (& us-> current_sg );
447}
448}
449
450/* wait for the completion of the transfer */
451 usb_sg_wait (& us-> current_sg );
452 clear_bit (us_f1_x_sg_active, & us-> flags );
453
454 result = us-> current_sg.status;
455 if (act_len)
456 * act_len = us-> current_sg.Bytes;
457 return interpret_urb_result (us, pipe, length, result,
458 us-> current_sg.Bytes );
459}
In the usb_stor_bulk_transfer_sg () function, determine whether use_sg is 0 to determine whether scatter-gather is used. If use_sg is equal to 0, scatter-gather is not required. Then, call usb_stor_bulk_transfer_buf () to send the scsi command. The actual length of transmitted data is recorded with partial, and then length_left records the number of records that are not transferred. The initial value is of course the expected length. You can subtract the actual length from each input. When use_sg is not equal to 0, the usb_stor_bulk_transfer_sglist () function is called. Let's look at this function.