usb: gadget: f_mtp: Make RX buffer size aligned to EP's MTU

Synopsys USB3 Controller (DWC3) has a restriction where size
of OUT requests (TRB) queued to the controller must be aligned
with the endpoint's max packet size. Generally, MTP userspace
module submits RX requests aligned to 512 bytes which works
fine in High speed mode. But, fails in Super-speed mode where
max packet size can be 1024 bytes.
To overcome this just change the size of RX request buffer
while submitting to DCD as the buffers are already allocated
with the size of 16KB.

Change-Id: I68c32ef3d08b2cf943b52a7269785d0a00146953
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
This commit is contained in:
Manu Gautam 2012-10-03 18:49:33 +05:30 committed by Kyle Yan
parent 2142069a88
commit f5bf2e9314

View file

@ -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
*/