diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c index dc157efd5fc3..286cb7622870 100644 --- a/drivers/usb/gadget/function/f_mtp.c +++ b/drivers/usb/gadget/function/f_mtp.c @@ -478,8 +478,7 @@ static ssize_t mtp_read(struct file *fp, char __user *buf, struct mtp_dev *dev = fp->private_data; struct usb_composite_dev *cdev = dev->cdev; struct usb_request *req; - ssize_t r = count; - unsigned xfer; + ssize_t xfer, r = count; int ret = 0; DBG(cdev, "mtp_read(%zu)\n", count); @@ -487,6 +486,10 @@ static ssize_t mtp_read(struct file *fp, char __user *buf, if (count > MTP_BULK_BUFFER_SIZE) return -EINVAL; + if (!IS_ALIGNED(count, dev->ep_out->maxpacket)) + DBG(cdev, "%s - count(%zu) not multiple of mtu(%d)\n", __func__, + count, dev->ep_out->maxpacket); + /* we will block until we're online */ DBG(cdev, "mtp_read: waiting for online state\n"); ret = wait_event_interruptible(dev->read_wq, @@ -508,7 +511,7 @@ static ssize_t mtp_read(struct file *fp, char __user *buf, requeue_req: /* queue a request */ req = dev->rx_req[0]; - req->length = count; + req->length = MTP_BULK_BUFFER_SIZE; dev->rx_done = 0; ret = usb_ep_queue(dev->ep_out, req, GFP_KERNEL); if (ret < 0) { @@ -773,6 +776,9 @@ static void receive_file_work(struct work_struct *data) count = dev->xfer_file_length; DBG(cdev, "receive_file_work(%lld)\n", count); + if (!IS_ALIGNED(count, dev->ep_out->maxpacket)) + DBG(cdev, "%s- count(%lld) not multiple of mtu(%d)\n", __func__, + count, dev->ep_out->maxpacket); while (count > 0 || write_req) { if (count > 0) { @@ -780,8 +786,9 @@ static void receive_file_work(struct work_struct *data) read_req = dev->rx_req[cur_buf]; cur_buf = (cur_buf + 1) % RX_REQ_MAX; - read_req->length = (count > MTP_BULK_BUFFER_SIZE - ? MTP_BULK_BUFFER_SIZE : count); + /* some h/w expects size to be aligned to ep's MTU */ + read_req->length = MTP_BULK_BUFFER_SIZE; + dev->rx_done = 0; ret = usb_ep_queue(dev->ep_out, read_req, GFP_KERNEL); if (ret < 0) { @@ -814,6 +821,11 @@ static void receive_file_work(struct work_struct *data) usb_ep_dequeue(dev->ep_out, read_req); break; } + + /* Check if we aligned the size due to MTU constraint */ + if (count < read_req->length) + read_req->actual = (read_req->actual > count ? + count : read_req->actual); /* if xfer_file_length is 0xFFFFFFFF, then we read until * we get a zero length packet */