If we _know_ length is 0, we can just return 1 early. While at that, we're also adding a comment referencing the location where the 64KiB boundary is mentioned in the xhci spec. This will prevent people from thinking this isn't necessary in the future. We're also changing the bitwise-and operator into a mathematically equivalent (albeit slower) modulus operator and trusting the compiler to optimize it back to bitwise-and. The reason for this is that a modulus operator states the intent with much more clarity. Signed-off-by: Felipe Balbi <felipe.balbi@xxxxxxxxxxxxxxx> --- drivers/usb/host/xhci-ring.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 2a1bb76f4d88..d7f9c0cfa047 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2940,14 +2940,23 @@ static int prepare_transfer(struct xhci_hcd *xhci, static unsigned int count_trbs(u64 addr, u64 len) { - unsigned int num_trbs; + u64 aligned_len = len + (addr % TRB_MAX_BUFF_SIZE); - num_trbs = DIV_ROUND_UP(len + (addr & (TRB_MAX_BUFF_SIZE - 1)), - TRB_MAX_BUFF_SIZE); - if (num_trbs == 0) - num_trbs++; + if (len == 0) + return 1; - return num_trbs; + /* + * Note here that we _must_ make sure buffer pointers don't cross 64KiB + * boundaries as stated on section 6.4.1 of the xHCI specification. + * + * We're trusting the compiler to optimize the mod operator down to a + * bitwise and, considering we're dealing with a power-of-two constant. + * + * It's also good to note that some xHCI implementations don't seem to + * sport this limitation, however for the sake of stability we will + * maintain this check here. + */ + return DIV_ROUND_UP(aligned_len, TRB_MAX_BUFF_SIZE); } static inline unsigned int count_trbs_needed(struct urb *urb) -- 2.8.0.rc2 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html