aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/devio.c40
1 files changed, 26 insertions, 14 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index ca948bbc388..a678186f218 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1334,14 +1334,11 @@ static int processcompl(struct async *as, void __user * __user *arg)
}
}
- free_async(as);
-
if (put_user(addr, (void __user * __user *)arg))
return -EFAULT;
return 0;
err_out:
- free_async(as);
return -EFAULT;
}
@@ -1371,8 +1368,11 @@ static struct async *reap_as(struct dev_state *ps)
static int proc_reapurb(struct dev_state *ps, void __user *arg)
{
struct async *as = reap_as(ps);
- if (as)
- return processcompl(as, (void __user * __user *)arg);
+ if (as) {
+ int retval = processcompl(as, (void __user * __user *)arg);
+ free_async(as);
+ return retval;
+ }
if (signal_pending(current))
return -EINTR;
return -EIO;
@@ -1380,11 +1380,16 @@ static int proc_reapurb(struct dev_state *ps, void __user *arg)
static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)
{
+ int retval;
struct async *as;
- if (!(as = async_getcompleted(ps)))
- return -EAGAIN;
- return processcompl(as, (void __user * __user *)arg);
+ as = async_getcompleted(ps);
+ retval = -EAGAIN;
+ if (as) {
+ retval = processcompl(as, (void __user * __user *)arg);
+ free_async(as);
+ }
+ return retval;
}
#ifdef CONFIG_COMPAT
@@ -1497,7 +1502,6 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
}
}
- free_async(as);
if (put_user(ptr_to_compat(addr), (u32 __user *)arg))
return -EFAULT;
return 0;
@@ -1506,8 +1510,11 @@ static int processcompl_compat(struct async *as, void __user * __user *arg)
static int proc_reapurb_compat(struct dev_state *ps, void __user *arg)
{
struct async *as = reap_as(ps);
- if (as)
- return processcompl_compat(as, (void __user * __user *)arg);
+ if (as) {
+ int retval = processcompl_compat(as, (void __user * __user *)arg);
+ free_async(as);
+ return retval;
+ }
if (signal_pending(current))
return -EINTR;
return -EIO;
@@ -1515,11 +1522,16 @@ static int proc_reapurb_compat(struct dev_state *ps, void __user *arg)
static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg)
{
+ int retval;
struct async *as;
- if (!(as = async_getcompleted(ps)))
- return -EAGAIN;
- return processcompl_compat(as, (void __user * __user *)arg);
+ retval = -EAGAIN;
+ as = async_getcompleted(ps);
+ if (as) {
+ retval = processcompl_compat(as, (void __user * __user *)arg);
+ free_async(as);
+ }
+ return retval;
}