Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0e1b607 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "fastboot: Increase maximum usbfs bulk size for writes to 256KiB" into main

parents 8097002e ab8cc2f7
Loading
Loading
Loading
Loading
+38 −20
Original line number Diff line number Diff line
@@ -83,7 +83,18 @@ using namespace std::chrono_literals;
// be reliable.
// 256KiB seems to work, but 1MiB bulk transfers lock up my z620 with a 3.13
// kernel.
#define MAX_USBFS_BULK_SIZE (16 * 1024)
// 128KiB was experimentally found to be enough to saturate the bus at
// SuperSpeed+, so we first try double that for writes. If the operation fails
// due to a lack of contiguous regions (or an ancient kernel), try smaller sizes
// until we find one that works (see LinuxUsbTransport::Write). Reads are less
// performance critical so for now just use a known good size.
#define MAX_USBFS_BULK_WRITE_SIZE (256 * 1024)
#define MAX_USBFS_BULK_READ_SIZE (16 * 1024)

// This size should pretty much always work (it's compatible with pre-3.3
// kernels and it's what we used to use historically), so if it doesn't work
// something has gone badly wrong.
#define MIN_USBFS_BULK_WRITE_SIZE (16 * 1024)

struct usb_handle
{
@@ -108,6 +119,7 @@ class LinuxUsbTransport : public UsbTransport {
  private:
    std::unique_ptr<usb_handle> handle_;
    const uint32_t ms_timeout_;
    size_t max_usbfs_bulk_write_size_ = MAX_USBFS_BULK_WRITE_SIZE;

    DISALLOW_COPY_AND_ASSIGN(LinuxUsbTransport);
};
@@ -415,7 +427,8 @@ ssize_t LinuxUsbTransport::Write(const void* _data, size_t len)
    }

    auto submit_urb = [&](size_t i) {
        int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
        while (true) {
            int xfer = (len > max_usbfs_bulk_write_size_) ? max_usbfs_bulk_write_size_ : len;

            urb[i].type = USBDEVFS_URB_TYPE_BULK;
            urb[i].endpoint = handle_->ep_out;
@@ -425,6 +438,10 @@ ssize_t LinuxUsbTransport::Write(const void* _data, size_t len)

            int n = ioctl(handle_->desc, USBDEVFS_SUBMITURB, &urb[i]);
            if (n != 0) {
                if (errno == ENOMEM && max_usbfs_bulk_write_size_ > MIN_USBFS_BULK_WRITE_SIZE) {
                    max_usbfs_bulk_write_size_ /= 2;
                    continue;
                }
                DBG("ioctl(USBDEVFS_SUBMITURB) failed\n");
                return false;
            }
@@ -435,6 +452,7 @@ ssize_t LinuxUsbTransport::Write(const void* _data, size_t len)
            data += xfer;

            return true;
        }
    };

    auto reap_urb = [&](size_t i) {
@@ -500,7 +518,7 @@ ssize_t LinuxUsbTransport::Read(void* _data, size_t len)
    }

    while (len > 0) {
        int xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
        int xfer = (len > MAX_USBFS_BULK_READ_SIZE) ? MAX_USBFS_BULK_READ_SIZE : len;

        bulk.ep = handle_->ep_in;
        bulk.len = xfer;