ni / usb3vision

Driver for USB3 Vision(TM) class devices
GNU General Public License v2.0
63 stars 31 forks source link

Scatter/gather list failure with Basler camera under Debian Bullseye...? #12

Open nickpelling opened 2 months ago

nickpelling commented 2 months ago

I'm trying to get the latest U3V working under Debian Bullseye, but this is yielding lots of scatter/gather list failures like this:

usb 7-1: calculate_sglist_entries: invalid buffer: if sg_constraint is true, a buffer can only have a scatterlist entry smaller than w_max_packet_size if it's the first or last in the list
usb 7-1: create_buffer: Creating sglist failed with error -131072

Enabling the debug output in calculate_urb_sizes prints out this:

[  121.185909] usb 7-1: calculate_urb_sizes: host image buffer size = 4608000
[  121.193996] usb 7-1: calculate_urb_sizes: device image buffer size = 4608000
[  121.202303] usb 7-1: calculate_urb_sizes: chunk data buffer size = 64
[  121.209867] usb 7-1: calculate_urb_sizes: payload size = 65536
[  121.216746] usb 7-1: calculate_urb_sizes: payload count = 70
[  121.223409] usb 7-1: calculate_urb_sizes: transfer1 = 20480
[  121.229981] usb 7-1: calculate_urb_sizes: transfer2 = 64
[  121.236223] usb 7-1: calculate_urb_sizes: transfer2_data = 64
[  121.242999] usb 7-1: calculate_urb_sizes: max_pglist_count = 1
[  121.249871] usb 7-1: calculate_urb_sizes: alignment_padding = 0
[  121.256818] usb 7-1: calculate_urb_sizes: segment_padding = 0
[  121.263565] usb 7-1: calculate_urb_sizes: segment_size = 4608000
[  121.270641] usb 7-1: calculate_urb_sizes: sg_constraint = true

The problem seems to be that if the desired first USB transaction length of a set is not a multiple of the max packet size (i.e. before being clipped), then the code can cause a second consecutive non-multiple of the max packet size to be emitted, depending on the page alignment.

The specific case causing the problem for me has bytes_remaining = 65536, which is triggering an initial bytes_to_transfer value of 2944, which is then being rounded down to 2048 (because the max packet size is 1024). The second packet is then getting sized to 896 bytes (to go to the page boundary), which is triggering the error condition.

My patch attempting to fix this issue looks like this:

            if (stream->config.sg_constraint) {
                if (bytes_to_transfer > w_max_packet_size) {
                    // If this isn't the first packet or the last packet
                    if ( (sg_count != 0) && (bytes_to_transfer != pglist_bytes_remaining) ) {
                        // If the transfer size is not a multiple of the packet size
                        int remainder = bytes_to_transfer % w_max_packet_size;
                        if (remainder) {
                            // Round the transfer size down to be a multiple of the packet size
                            bytes_to_transfer -= remainder;
                        }
                    }
                } else if (bytes_to_transfer < w_max_packet_size

This prevents the scatter/gather failures, but instead yields a different warning when the packet is received:

[ 2382.175004] usb 7-1: stream_urb_completion: entry 90, urb 72: length = 40, expected >=64

So I'm not sure if my fix is actually fixing the problem.

Is this whole thing a known issue? Or might it be being triggered by something else entirely, e.g. the memory alignment of the USB buffers?

nickpelling commented 2 months ago

After debugging this for a while, it seems that the stream_urb_completion() error is to do with the scatter/gathers being constructed for the stream buffers. So, the patch suggested above seems to be working, and the stream_urb_completion() error is an unrelated problem.