The usb_stor_bulk_transfer_sglist () function is confusing. We have mentioned that sglist is used to improve transmission efficiency. As we know, SG aims to transmit a bunch of discontinuous buffers in one DMA Operation. In fact, this is not the case in the story of USB. However, if you don't care about the behavior in the USB core, it doesn't matter.
Row 3 and row 3 do not pass data if you exit or break the link.
Then in Row 3, The usb_sg_init () function is called. This function comes from drivers/USB/CORE/message. C. That is to say, it is a function provided by the USB core layer. What is it used? Initialize the SG request. The first parameter is the pointer of the struct usb_sg_request struct. Here we pass the address of US-> current_sg to it, here us-> current_sg comes in handy for the first time, so we need to introduce it in detail.
In structus_data, A structusb_sg_request current_sg member is defined. We once saw current_urb, and another current_sg came here. Maybe you are confused. In fact, we can understand that struct urb represents a USB request. Here, structusb_sg_request actually represents a scattergather request. From the perspective of our non-USB core layer, the usage of these two structs is the same. For each urb request, all we do is apply for a struct variable or request a pointer, and then apply for memory. The second step is to submit urb, that is, call usb_submit_urb ().
Core will help us solve the problem. Every module in Linux provides services to others and enjoys the services provided by others.
If you want to work with others, you only need to call the functions provided by others and pass your pointer and your variables to others. You don't have to worry about other functions. You will be notified after the event is completed. Similarly, for SG requests, USB core also implements these features. We only need to apply for and initialize a struct usb_sg_request struct, and then submit it. Then, USB core naturally knows how to handle it. Let's talk about the structure of struct usb_sg_request. It comes from include/Linux/USB. h:
1350 struct usb_sg_request {
1351 int status;
1352 size_t bytes;
1353
1354 /*
1355 * Members below are private: To usbcore,
1356 * andare not provided for driver access!
1357 */
1358 spinlock_t lock;
1359
1360 struct usb_device * dev;
1361 int pipe;
1362 structscatterlist * SG;
1363 int nents;
1364
1365 int entries;
1366 struct urb ** URBS;
1367
1368 int count;
1369 struct completion complete;
1370 };
The entire USB system uses this data structure, if we want to use the scatter gather method. USB core has prepared the data structure and corresponding functions for us. We only need to call them. There are three functions in total: usb_sg_init, usb_sg_wait, and usb_sg_cancel. To submit a SG request, you must first initialize the request with usb_sg_init, and then formally submit usb_sg_wait. To cancel a SG request, call usb_sg_cancel.
Although we don't have to look at how the three functions are implemented internally, we have to know at least what parameters should be passed. Take a closer look at the parameters passed to usb_sg_init () when it is called. The first one is sgrequest and the second one. We need to tell it which USB device is going to send or receive data, and we will pass us-> pusb_dev, 1st to it, there is nothing to say about which pipeline it is. The pipeline was passed down all the way above. 4th parameters, which are specifically applicable to interrupted transmission. The polling rate of the interrupted transmission endpoint is ignored for batch transmission. Therefore, 0 is passed. The 5th and 6th parameters are the number of elements in the SG array and SG array respectively. The length parameter is the length of the data we want to transmit. The last one is slab.
Flag, a flag related to the memory application. If the driver is in the block I/O path, gfp_noio should be used. Here, slab_noio is actually a macro, actually gfp_noio.
For more information about why slab_noio or gfp_noio is used, see the previous section on how to call usb_submit_urb. The return value of this function is 0. Otherwise, the negative error code is returned. After initialization, you can set us_f1_x_sg_active for us-> flags. Is this flag unfamiliar? Go back and check out usb_submit_urb (). At that time, we set such a flag for urb, us_fldx_urb_active. In fact, the history is always surprisingly similar. At the beginning, we treated urb in almost the same way as SG request. So it is actually quite understandable.
By comparing the code that originally called usb_submit_urb (), we will find that we will not be unfamiliar with lines 441 to lines 448. We had such a section before submitting urb. In the usb_stor_msg_common () function, but at that time it was urb rather than SG. What are the similarities between the two codes! It's just that the year-old flowers are similar, and the year-old people are different! In row 3, The usb_sg_wait () function is called. The required parameter is the SG request address. Here, the address of US-> current_sg is passed to it. When this function ends, the flag of us_f1_x_sg_active can be clear. The returned value is saved in US-> current_sg.status and assigned to result. While US-> current_sg.bytes saves the actual transfer length, assigns it to * act_len, and then returns the result by calling interpret_urb_result () again.
Finally, the usb_stor_bulk_transfer_sg () function has done one thing before returning the result, and assigned the remaining length to * residual. * Residual is the form parameter, and the real parameter is & sulfate-> resid. The final value returned by usb_stor_bulk_transfer_sg () is the value translated by interpret_urb_result. However, you need to understand that the return of this function means the key phase in bulk transmission, that is, the end of the Data phase. The next stage is the State stage. The CSW is to be passed, just like the CBW.
Return to the usb_stor_bulk_transport () function to determine whether the result is usb_stor_xfer_error or usb_stor_xfer_long. The former indicates an error, and the latter indicates that the device tries to send more data than we need. In this case, you can use a fake sense data to report an error to the upper layer. However, unlike the common error, the upper layer is notified that this command should not be resold. Fake_sense is set to 0 at the beginning. It is set to 1 and will be used later. Currently, you only need to know that this situation does not exist. In fact, USB massstorage bulk-only
This is defined in the spec. The spec still needs to proceed in the next stage.
Finally, we can explain that usb_stor_xfer_long is just a macro defined by ourselves. It is actually translated by interpret_urb_result (). The result actually transmitted from the USB core layer is-eoverflow, this can be found in the interpret_urb_result function. -Eoverflow is overflow.
Finally, let's try again. In fact, the most user-friendly aspect of the USB core layer is the processing of urb and SG. Code writers like to embody data transmission as request, while urb and SG are also embodied as request, that is, request. The capability of USB core is to enable the device driver writer to apply for a request, call the function provided by USB core for initialization, and then call the function provided by USB core for submission, these steps are fixed, just like using a dumb camera, and then the process can sleep, or do something else, and then the USB core will notify you. You can do other things next.