From a83df420262a25ec23b23fc9f617eee1a6dc0dff Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 12 Feb 2012 06:00:41 +0000 Subject: [PATCH] --- yaml --- r: 289460 b: refs/heads/master c: 711c68b3c0f7a924ffbee4aa962d8f62b85188ff h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/usb/class/cdc-wdm.c | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/[refs] b/[refs] index ba62205adddd..694c2cc990bf 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c192c8e71a2ded01170c1a992cd21aaedc822756 +refs/heads/master: 711c68b3c0f7a924ffbee4aa962d8f62b85188ff diff --git a/trunk/drivers/usb/class/cdc-wdm.c b/trunk/drivers/usb/class/cdc-wdm.c index b27bbb957e16..7ca54d4dea92 100644 --- a/trunk/drivers/usb/class/cdc-wdm.c +++ b/trunk/drivers/usb/class/cdc-wdm.c @@ -391,7 +391,7 @@ static ssize_t wdm_write static ssize_t wdm_read (struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - int rv, cntr = 0; + int rv, cntr; int i = 0; struct wdm_device *desc = file->private_data; @@ -400,7 +400,8 @@ static ssize_t wdm_read if (rv < 0) return -ERESTARTSYS; - if (desc->length == 0) { + cntr = ACCESS_ONCE(desc->length); + if (cntr == 0) { desc->read = 0; retry: if (test_bit(WDM_DISCONNECTING, &desc->flags)) { @@ -455,25 +456,30 @@ static ssize_t wdm_read goto retry; } clear_bit(WDM_READ, &desc->flags); + cntr = desc->length; spin_unlock_irq(&desc->iuspin); } - cntr = count > desc->length ? desc->length : count; + if (cntr > count) + cntr = count; rv = copy_to_user(buffer, desc->ubuf, cntr); if (rv > 0) { rv = -EFAULT; goto err; } + spin_lock_irq(&desc->iuspin); + for (i = 0; i < desc->length - cntr; i++) desc->ubuf[i] = desc->ubuf[i + cntr]; - spin_lock_irq(&desc->iuspin); desc->length -= cntr; - spin_unlock_irq(&desc->iuspin); /* in case we had outstanding data */ if (!desc->length) clear_bit(WDM_READ, &desc->flags); + + spin_unlock_irq(&desc->iuspin); + rv = cntr; err: