diff options
author | Mark Brown <broonie@linaro.org> | 2014-03-11 09:47:53 +0000 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-03-11 09:47:53 +0000 |
commit | 943550a24c51bdd971f579200f286241548deaf7 (patch) | |
tree | 4b275941890744cf4ea588ea59db7cd6558647b6 /drivers/usb/gadget/f_accessory.c | |
parent | 0356888ad14044efe98b16a731ba56d74b89269e (diff) | |
parent | a3b71254e95dc167ddca600c0ca426e8ce2fad3f (diff) |
Merge branch 'linaro-android-3.10-lsk' of git://git.linaro.org/people/jstultz/android into linux-linaro-lsk-androidlsk-android-14.03
Conflicts:
arch/arm64/include/asm/cmpxchg.h
drivers/cpufreq/cpufreq.c
include/net/tcp.h
net/ipv4/ping.c
net/ipv4/sysctl_net_ipv4.c
net/netfilter/xt_qtaguid.c
Diffstat (limited to 'drivers/usb/gadget/f_accessory.c')
-rw-r--r-- | drivers/usb/gadget/f_accessory.c | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c index 092964c2b506..53e50b5e8612 100644 --- a/drivers/usb/gadget/f_accessory.c +++ b/drivers/usb/gadget/f_accessory.c @@ -261,8 +261,10 @@ static void acc_complete_in(struct usb_ep *ep, struct usb_request *req) { struct acc_dev *dev = _acc_dev; - if (req->status != 0) + if (req->status == -ESHUTDOWN) { + pr_debug("acc_complete_in set disconnected"); acc_set_disconnected(dev); + } req_put(dev, &dev->tx_idle, req); @@ -274,8 +276,10 @@ static void acc_complete_out(struct usb_ep *ep, struct usb_request *req) struct acc_dev *dev = _acc_dev; dev->rx_done = 1; - if (req->status != 0) + if (req->status == -ESHUTDOWN) { + pr_debug("acc_complete_out set disconnected"); acc_set_disconnected(dev); + } wake_up(&dev->read_wq); } @@ -552,13 +556,16 @@ static ssize_t acc_read(struct file *fp, char __user *buf, { struct acc_dev *dev = fp->private_data; struct usb_request *req; - int r = count, xfer; + ssize_t r = count; + unsigned xfer; int ret = 0; - pr_debug("acc_read(%d)\n", count); + pr_debug("acc_read(%zu)\n", count); - if (dev->disconnected) + if (dev->disconnected) { + pr_debug("acc_read disconnected"); return -ENODEV; + } if (count > BULK_BUFFER_SIZE) count = BULK_BUFFER_SIZE; @@ -571,6 +578,12 @@ static ssize_t acc_read(struct file *fp, char __user *buf, goto done; } + if (dev->rx_done) { + // last req cancelled. try to get it. + req = dev->rx_req[0]; + goto copy_data; + } + requeue_req: /* queue a request */ req = dev->rx_req[0]; @@ -588,15 +601,23 @@ requeue_req: ret = wait_event_interruptible(dev->read_wq, dev->rx_done); if (ret < 0) { r = ret; - usb_ep_dequeue(dev->ep_out, req); + ret = usb_ep_dequeue(dev->ep_out, req); + if (ret != 0) { + // cancel failed. There can be a data already received. + // it will be retrieved in the next read. + pr_debug("acc_read: cancelling failed %d", ret); + } goto done; } + +copy_data: + dev->rx_done = 0; if (dev->online) { /* If we got a 0-len packet, throw it back and try again. */ if (req->actual == 0) goto requeue_req; - pr_debug("rx %p %d\n", req, req->actual); + pr_debug("rx %p %u\n", req, req->actual); xfer = (req->actual < count) ? req->actual : count; r = xfer; if (copy_to_user(buf, req->buf, xfer)) @@ -605,7 +626,7 @@ requeue_req: r = -EIO; done: - pr_debug("acc_read returning %d\n", r); + pr_debug("acc_read returning %zd\n", r); return r; } @@ -614,13 +635,16 @@ static ssize_t acc_write(struct file *fp, const char __user *buf, { struct acc_dev *dev = fp->private_data; struct usb_request *req = 0; - int r = count, xfer; + ssize_t r = count; + unsigned xfer; int ret; - pr_debug("acc_write(%d)\n", count); + pr_debug("acc_write(%zu)\n", count); - if (!dev->online || dev->disconnected) + if (!dev->online || dev->disconnected) { + pr_debug("acc_write disconnected or not online"); return -ENODEV; + } while (count > 0) { if (!dev->online) { @@ -665,7 +689,7 @@ static ssize_t acc_write(struct file *fp, const char __user *buf, if (req) req_put(dev, &dev->tx_idle, req); - pr_debug("acc_write returning %d\n", r); + pr_debug("acc_write returning %zd\n", r); return r; } |